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:43:27 +0200

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?
>
> 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]