[Top][All Lists]
[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>
>>>
>>>
>>
>
- Re: [libvirt] mingw: virsh event loop failure in current git, (continued)
- Re: non-blocking I/O, Bruno Haible, 2011/03/29
- Re: non-blocking I/O, Eric Blake, 2011/03/30
- Re: non-blocking I/O, Eric Blake, 2011/03/30
- Re: non-blocking I/O, Paolo Bonzini, 2011/03/31
- Re: non-blocking I/O, Bruno Haible, 2011/03/31
- [PATCH] nonblocking: new module, Eric Blake, 2011/03/31
- Re: [PATCH] nonblocking: new module, Bruno Haible, 2011/03/31