On Tue, Mar 29, 2011 at 6:43 PM, Bastien ROUCARIES <roucaries.bast...@gmail.com> wrote: > On Tue, Mar 29, 2011 at 6:34 PM, Bastien ROUCARIES > <roucaries.bast...@gmail.com> wrote: >> On Tue, Mar 29, 2011 at 5:16 PM, Bruno Haible <br...@clisp.org> wrote: >>> Paolo Bonzini wrote: >>>> Without guessing what your bias is, I also :) prefer to implement >>>> {g,s}et_nonblock_flag functions. It would use either >>>> SetNamedPipeHandleState or ioctlsocket (using the socket detection trick >>>> in sockets.c to detect sockets, and then GetFileType to detect pipes if >>>> it fails). >>> >>> Here's proposed code to that effect. Note that the getter function cannot >>> be implemented: How to determine whether a Woe32 socket is non-blocking?
At least they achieve to do it in C# http://msdn.microsoft.com/en-us/library/system.net.sockets.socketinformation.aspx >> >> according to crappy doc: >> The WSAEventSelect function automatically sets a socket to nonblocking >> mode. If WSAEventSelect has been issued on a socket, then any attempt >> to use ioctlsocket to set the socket back to blocking mode will fail >> with WSAEINVAL. >> >> To set the socket back to blocking mode, an application must first >> disable WSAEventSelect by calling WSAEventSelect with the >> lNetworkEvents parameter equal to zero. >> >> Using this trick will allow to ask the socket (but not thread safe :S) > > I am stupid It will not work > > Bastien >> >> Bastien >> >>> >>> >>> ================================ nonblocking.h >>> ================================ >>> /* Non-blocking I/O for pipe or socket descriptors. >>> Copyright (C) 2011 Free Software Foundation, Inc. >>> >>> This program is free software: you can redistribute it and/or modify >>> it under the terms of the GNU General Public License as published by >>> the Free Software Foundation; either version 3 of the License, or >>> (at your option) any later version. >>> >>> This program is distributed in the hope that it will be useful, >>> but WITHOUT ANY WARRANTY; without even the implied warranty of >>> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >>> GNU General Public License for more details. >>> >>> You should have received a copy of the GNU General Public License >>> along with this program. If not, see <http://www.gnu.org/licenses/>. */ >>> >>> #ifndef _NONBLOCKING_H >>> #define _NONBLOCKING_H >>> >>> #include <stdbool.h> >>> >>> /* Non-blocking I/O is an I/O mode by which read(), write() calls avoid >>> blocking the current thread. When non-blocking is enabled: >>> - A read() call returns -1 with errno set to EAGAIN when no data or EOF >>> information is immediately available. >>> - A write() call returns -1 with errno set to EAGAIN when it cannot >>> transport the requested amount of data (but at most one pipe buffer) >>> without blocking. >>> >>> There are two modern alternatives to non-blocking I/O: >>> - use select() or poll() followed by read() or write() if the descriptor >>> is ready, >>> - call read() or write() in separate threads. */ >>> >>> >>> #ifdef __cplusplus >>> extern "C" { >>> #endif >>> >>> >>> #if 0 /* cannot be portably implemented */ >>> /* Return true if I/O to the descriptor DESC is currently non-blocking, >>> or false if it is blocking. */ >>> extern bool get_nonblocking_flag (int desc); >>> #endif >>> >>> /* Specify the non-blocking flag for the descriptor DESC. >>> Return 0 upon success, or -1 with errno set upon failure. >>> The default depends on the presence of the O_NONBLOCK flag for files >>> or pipes opened with open() or on the presence of the SOCK_NONBLOCK >>> flag for pipes. */ >>> extern int set_nonblocking_flag (int desc, bool value); >>> >>> >>> #ifdef __cplusplus >>> } >>> #endif >>> >>> #endif /* _NONBLOCKING_H */ >>> ================================ nonblocking.c >>> ================================ >>> /* Non-blocking I/O for pipe or socket descriptors. >>> Copyright (C) 2011 Free Software Foundation, Inc. >>> >>> This program is free software: you can redistribute it and/or modify >>> it under the terms of the GNU General Public License as published by >>> the Free Software Foundation; either version 3 of the License, or >>> (at your option) any later version. >>> >>> This program is distributed in the hope that it will be useful, >>> but WITHOUT ANY WARRANTY; without even the implied warranty of >>> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >>> GNU General Public License for more details. >>> >>> You should have received a copy of the GNU General Public License >>> along with this program. If not, see <http://www.gnu.org/licenses/>. */ >>> >>> #include <config.h> >>> >>> /* Specification. */ >>> #include "nonblocking.h" >>> >>> #include <errno.h> >>> >>> #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ >>> /* Native Woe32 API. */ >>> >>> # if 0 >>> bool >>> get_nonblocking_flag (int desc) >>> { >>> HANDLE h = (HANDLE) _get_osfhandle (desc); >>> if (GetFileType (h) == FILE_TYPE_PIPE) >>> { >>> /* h is a pipe or socket. */ >>> DWORD state; >>> if (GetNamedPipeHandleState (h, &state, NULL, NULL, NULL, NULL, 0)) >>> /* h is a pipe. */ >>> return (state & PIPE_NOWAIT) != 0; >>> else >>> /* h is a socket. */ >>> ?? How can this be implemented ?? >>> } >>> else >>> return false; >>> } >>> # endif >>> >>> int >>> set_nonblocking_flag (int desc, bool value) >>> { >>> HANDLE h = (HANDLE) _get_osfhandle (desc); >>> if (GetFileType (h) == FILE_TYPE_PIPE) >>> { >>> /* h is a pipe or socket. */ >>> DWORD state; >>> if (GetNamedPipeHandleState (h, &state, NULL, NULL, NULL, NULL, 0)) >>> { >>> /* h is a pipe. */ >>> if ((state & PIPE_NOWAIT) != 0) >>> { >>> if (value) >>> return 0; >>> state &= ~PIPE_NOWAIT; >>> } >>> else >>> { >>> if (!value) >>> return 0; >>> state |= PIPE_NOWAIT; >>> } >>> if (SetNamedPipeHandleState (h, &state, NULL, NULL)) >>> return 0; >>> errno = EINVAL; >>> return -1; >>> } >>> else >>> { >>> /* h is a socket. */ >>> int v = value; >>> return ioctl ((SOCKET) h, FIONBIO, &v); >>> } >>> } >>> else >>> { >>> /* Win32 does not support non-blocking on regular files. */ >>> errno = ENOTSUP; >>> return -1; >>> } >>> } >>> >>> #else >>> /* Unix API. */ >>> >>> # include <fcntl.h> >>> >>> /* We don't need the gnulib replacement of fcntl() here. */ >>> # undef fcntl >>> >>> # if 0 >>> bool >>> get_nonblocking_flag (int desc) >>> { >>> int fcntl_flags; >>> >>> fcntl_flags = fcntl (desc, F_GETFL, 0); >>> if (fcntl_flags < 0) >>> return false; >>> return (fcntl_flags & O_NONBLOCK) != 0; >>> } >>> # endif >>> >>> int >>> set_nonblocking_flag (int desc, bool value) >>> { >>> int fcntl_flags; >>> >>> fcntl_flags = fcntl (desc, F_GETFL, 0); >>> if (fcntl_flags < 0) >>> return -1; >>> if ((O_NONBLOCK & ~fcntl_flags) == 0) >>> return 0; >>> return fcntl (desc, F_SETFL, fcntl_flags | O_NONBLOCK); >>> } >>> >>> #endif >>> =============================================================================== >>> --- lib/ioctl.c.orig Tue Mar 29 17:15:16 2011 >>> +++ lib/ioctl.c Tue Mar 29 16:08:53 2011 >>> @@ -63,6 +63,10 @@ >>> buf = va_arg (args, void *); >>> va_end (args); >>> >>> + /* We don't support FIONBIO on pipes here. If you want to make pipe fds >>> + non-blocking, use the gnulib 'nonblocking' module, until gnulib >>> implements >>> + fcntl F_GETFL / F_SETFL with O_NONBLOCK. */ >>> + >>> sock = FD_TO_SOCKET (fd); >>> r = ioctlsocket (sock, req, buf); >>> if (r < 0) >>> >>> -- >>> In memoriam Rachel Levy <http://en.wikipedia.org/wiki/Rachel_Levy> >>> >>> >> >