bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: non-blocking I/O


From: Bastien ROUCARIES
Subject: Re: non-blocking I/O
Date: Tue, 29 Mar 2011 18:57:28 +0200

On Tue, Mar 29, 2011 at 6:43 PM, Bastien ROUCARIES
<address@hidden> wrote:
> On Tue, Mar 29, 2011 at 6:34 PM, Bastien ROUCARIES
> <address@hidden> wrote:
>> On Tue, Mar 29, 2011 at 5:16 PM, Bruno Haible <address@hidden> 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>
>>>
>>>
>>
>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]