X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=lib%2Fpipe2.c;h=12cac6e7729147e9e1d675115aae4e32552066c8;hb=a046525c54d375ff2b3d9d0f8c78f5c779ce4f99;hp=4fa014f82b43b5b701c972ac58c9a5af764ed8cc;hpb=d60f3b0c6b0f93a601acd1cfd3923f94ca05abb0;p=gnulib.git diff --git a/lib/pipe2.c b/lib/pipe2.c index 4fa014f82..12cac6e77 100644 --- a/lib/pipe2.c +++ b/lib/pipe2.c @@ -24,6 +24,11 @@ #include #include "binary-io.h" +#include "verify.h" + +#if GNULIB_defined_O_NONBLOCK +# include "nonblocking.h" +#endif #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ /* Native Woe32 API. */ @@ -35,6 +40,13 @@ int pipe2 (int fd[2], int flags) { + /* Mingw _pipe() corrupts fd on failure; also, if we succeed at + creating the pipe but later fail at changing fcntl, we want + to leave fd unchanged: http://austingroupbugs.net/view.php?id=467 */ + int tmp[2]; + tmp[0] = fd[0]; + tmp[1] = fd[1]; + #if HAVE_PIPE2 # undef pipe2 /* Try the system call first, if it exists. (We may be running with a glibc @@ -55,35 +67,51 @@ 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; } - return _pipe (fd, 4096, flags); - -#else -/* Unix API. */ +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +/* Native Woe32 API. */ - /* Check the supported flags. */ - if ((flags & ~(O_CLOEXEC | O_NONBLOCK | O_TEXT | O_BINARY)) != 0) + if (_pipe (fd, 4096, flags & ~O_NONBLOCK) < 0) { - errno = EINVAL; + fd[0] = tmp[0]; + fd[1] = tmp[1]; return -1; } + /* O_NONBLOCK handling. + On native Windows platforms, O_NONBLOCK is defined by gnulib. Use the + functions defined by the gnulib module 'nonblocking'. */ +# if GNULIB_defined_O_NONBLOCK + if (flags & O_NONBLOCK) + { + if (set_nonblocking_flag (fd[0], true) != 0 + || set_nonblocking_flag (fd[1], true) != 0) + goto fail; + } +# else + verify (O_NONBLOCK == 0); +# endif + + return 0; + +#else +/* Unix API. */ + 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]. */ + /* O_NONBLOCK handling. + On Unix platforms, O_NONBLOCK is defined by the system. Use fcntl(). */ if (flags & O_NONBLOCK) { int fcntl_flags; @@ -121,14 +149,16 @@ pipe2 (int fd[2], int flags) return 0; +#endif + fail: { int saved_errno = errno; close (fd[0]); close (fd[1]); + fd[0] = tmp[0]; + fd[1] = tmp[1]; errno = saved_errno; return -1; } - -#endif }