[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: non-blocking I/O
From: |
Bruno Haible |
Subject: |
Re: non-blocking I/O |
Date: |
Tue, 29 Mar 2011 16:16:20 +0100 |
User-agent: |
KMail/1.9.9 |
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?
================================ 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 <=
- 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