bug-gnulib
[Top][All Lists]
Advanced

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

Re: non-blocking I/O


From: Eric Blake
Subject: Re: non-blocking I/O
Date: Wed, 30 Mar 2011 11:46:06 -0600
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110307 Fedora/3.1.9-0.39.b3pre.fc14 Lightning/1.0b3pre Mnenhy/0.8.3 Thunderbird/3.1.9

On 03/29/2011 09:16 AM, Bruno Haible 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.

Let's get it checked in.

>  Note that the getter function cannot
> be implemented: How to determine whether a Woe32 socket is non-blocking?

I don't know.

> /* 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:

three

>      - use select() or poll() followed by read() or write() if the descriptor
>        is ready,
>      - call read() or write() in separate threads.  */

- use aio_*, although that is not as widely portable

> 
> #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

Should we make this tri-state?

-1 for unable to determine (such as mingw sockets for now), 0 for
blocking (such as mingw regular files, or Unix platforms where
fcntl(F_GETFL) works), 1 for non-blocking.

> /* 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);

Should we document this function's behavior on fd's exempt by POSIX?
For regular files and directories, non-blocking has no effect, but it is
implementation-defined whether fcntl(F_SETFL) can modify the O_NONBLOCK
flag or whether the flag is silently ignored.  Having consistent
behavior (such as making this function always return -1 EBADF on a
non-pipe non-socket, rather than triggering implementation-defined
behavior with subtle differences across platforms) might be worth the
extra effort of an fstat().  I'm not sure whether block and character
special devices can usefully be set non-blocking, or whether that is a
per-device setting.

> #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;

This would be a case for returning -1 in a tri-state implementation.

>   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);

This doesn't honor the 'value' parameter, but blindly assumes it was
true.  Sometimes it is also desirable to clear non-blocking, by passing
false.

-- 
Eric Blake   address@hidden    +1-801-349-2682
Libvirt virtualization library http://libvirt.org

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

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