X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fpipe2.c;h=cd1fe56413c7048a2ce9d0f6a83a948295e9f8ef;hb=39a489fa27ab3873e0fc0f65844413f46fcb2117;hp=6ffb101f3d0ce6cdac672b2733a31ad631834257;hpb=0568a6e8985cc2ae9c57cb03fc81f5305458b7d2;p=gnulib.git diff --git a/lib/pipe2.c b/lib/pipe2.c index 6ffb101f3..cd1fe5641 100644 --- a/lib/pipe2.c +++ b/lib/pipe2.c @@ -24,7 +24,11 @@ #include #include "binary-io.h" -#include "nonblocking.h" +#include "verify.h" + +#if GNULIB_defined_O_NONBLOCK +# include "nonblocking.h" +#endif #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ /* Native Woe32 API. */ @@ -36,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 @@ -66,23 +77,30 @@ pipe2 (int fd[2], int flags) #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ /* Native Woe32 API. */ + if (_pipe (fd, 4096, flags & ~O_NONBLOCK) < 0) + { + 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) { - 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; + goto fail; } - return _pipe (fd, 4096, flags); +# else + { + verify (O_NONBLOCK == 0); + } +# endif + + return 0; #else /* Unix API. */ @@ -94,6 +112,8 @@ pipe2 (int fd[2], int flags) says that initially, the O_NONBLOCK and FD_CLOEXEC flags are cleared on 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; @@ -131,14 +151,19 @@ pipe2 (int fd[2], int flags) return 0; +#endif + +#if GNULIB_defined_O_NONBLOCK || \ + !((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) 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 }