[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: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>
>>
>>
>
- Re: [libvirt] mingw: virsh event loop failure in current git, Eric Blake, 2011/03/28
- 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