From: Eric Blake Date: Fri, 8 Apr 2011 16:52:55 +0000 (-0600) Subject: pipe2: fix O_NONBLOCK support on mingw X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0568a6e8985cc2ae9c57cb03fc81f5305458b7d2;p=pspp pipe2: fix O_NONBLOCK support on mingw * modules/pipe2 (Depends-on): Add nonblocking. * lib/pipe2.c (pipe2) [WIN32]: Add O_NONBLOCK support. * tests/test-pipe2.c (is_nonblocking): Adjust test accordingly. * tests/test-nonblocking.c (main): Likewise. * modules/pipe2-tests (Makefile.am): Avoid link failure. Signed-off-by: Eric Blake --- diff --git a/ChangeLog b/ChangeLog index 58f0c53cad..a8d45212ff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2011-04-08 Eric Blake + pipe2: fix O_NONBLOCK support on mingw + * modules/pipe2 (Depends-on): Add nonblocking. + * lib/pipe2.c (pipe2) [WIN32]: Add O_NONBLOCK support. + * tests/test-pipe2.c (is_nonblocking): Adjust test accordingly. + * tests/test-nonblocking.c (main): Likewise. + * modules/pipe2-tests (Makefile.am): Avoid link failure. + fcntl-h: fix O_ACCMODE on cygwin * doc/posix-headers/fcntl.texi (fcntl.h): Document the bug. * lib/fcntl.in.h (O_ACCMODE): Fix it. diff --git a/lib/pipe2.c b/lib/pipe2.c index 4fa014f82b..6ffb101f3d 100644 --- a/lib/pipe2.c +++ b/lib/pipe2.c @@ -24,6 +24,7 @@ #include #include "binary-io.h" +#include "nonblocking.h" #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ /* Native Woe32 API. */ @@ -55,34 +56,43 @@ pipe2 (int fd[2], int flags) } #endif -#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ -/* Native Woe32 API. */ - /* Check the supported flags. */ - if ((flags & ~(O_CLOEXEC | O_BINARY | O_TEXT)) != 0) + if ((flags & ~(O_CLOEXEC | O_NONBLOCK | O_BINARY | O_TEXT)) != 0) { errno = EINVAL; return -1; } +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +/* Native Woe32 API. */ + + if (flags & O_NONBLOCK) + { + int result = _pipe (fd, 4096, flags & ~O_NONBLOCK); + if (result != 0) + return result; + if (set_nonblocking_flag (fd[0], true) != 0 + || set_nonblocking_flag (fd[1], true) != 0) + { + int saved_errno = errno; + close (fd[0]); + close (fd[1]); + result = -1; + errno = saved_errno; + } + return result; + } return _pipe (fd, 4096, flags); #else /* Unix API. */ - /* Check the supported flags. */ - if ((flags & ~(O_CLOEXEC | O_NONBLOCK | O_TEXT | O_BINARY)) != 0) - { - errno = EINVAL; - return -1; - } - if (pipe (fd) < 0) return -1; /* POSIX says that initially, the O_NONBLOCK and FD_CLOEXEC flags are cleared on - both fd[0] amd fd[1]. */ + both fd[0] and fd[1]. */ if (flags & O_NONBLOCK) { diff --git a/modules/pipe2 b/modules/pipe2 index 1183657659..ca722168a7 100644 --- a/modules/pipe2 +++ b/modules/pipe2 @@ -10,6 +10,7 @@ unistd fcntl-h binary-io extensions +nonblocking configure.ac: gl_FUNC_PIPE2 diff --git a/modules/pipe2-tests b/modules/pipe2-tests index 5d24bd747c..9e751dc327 100644 --- a/modules/pipe2-tests +++ b/modules/pipe2-tests @@ -11,3 +11,4 @@ configure.ac: Makefile.am: TESTS += test-pipe2 check_PROGRAMS += test-pipe2 +test_pipe2_LDADD = $(LDADD) @LIBSOCKET@ diff --git a/tests/test-pipe2.c b/tests/test-pipe2.c index ddfb819abb..8ca8e01363 100644 --- a/tests/test-pipe2.c +++ b/tests/test-pipe2.c @@ -33,6 +33,7 @@ SIGNATURE_CHECK (pipe2, int, (int[2], int)); #include "binary-io.h" #include "macros.h" +#include "nonblocking.h" /* Return true if FD is open. */ static bool @@ -67,49 +68,23 @@ is_cloexec (int fd) #endif } -/* Return true if FD is in non-blocking mode. */ -static bool -is_nonblocking (int fd) -{ -#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ - /* We don't use the non-blocking mode for sockets here. */ - return 0; -#else - int flags; - ASSERT ((flags = fcntl (fd, F_GETFL)) >= 0); - return (flags & O_NONBLOCK) != 0; -#endif -} - int main () { int use_nonblocking; int use_cloexec; -#if !((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) for (use_nonblocking = 0; use_nonblocking <= 1; use_nonblocking++) -#else - use_nonblocking = 0; -#endif -#if O_CLOEXEC - for (use_cloexec = 0; use_cloexec <= 1; use_cloexec++) -#else - use_cloexec = 0; -#endif + for (use_cloexec = 0; use_cloexec <= !!O_CLOEXEC; use_cloexec++) { int o_flags; int fd[2]; o_flags = 0; -#if !((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) if (use_nonblocking) o_flags |= O_NONBLOCK; -#endif -#if O_CLOEXEC if (use_cloexec) o_flags |= O_CLOEXEC; -#endif fd[0] = -1; fd[1] = -1; @@ -131,14 +106,17 @@ main () } if (use_nonblocking) { - ASSERT (is_nonblocking (fd[0])); - ASSERT (is_nonblocking (fd[1])); + ASSERT (get_nonblocking_flag (fd[0]) == 1); + ASSERT (get_nonblocking_flag (fd[1]) == 1); } else { - ASSERT (!is_nonblocking (fd[0])); - ASSERT (!is_nonblocking (fd[1])); + ASSERT (get_nonblocking_flag (fd[0]) == 0); + ASSERT (get_nonblocking_flag (fd[1]) == 0); } + + ASSERT (close (fd[0]) == 0); + ASSERT (close (fd[1]) == 0); } return 0;