Mercurial > gnulib
changeset 37189:82ff83d5d4a7
dup2, dup3: work around another cygwin crasher
Cygwin 1.7.25 can crash due to an off-by-one bug on an attempt to
duplicate a file into the current RLIMIT_NOFILE soft limit, when
that limit is smaller than the hard limit. The intent in the
cygwin code was to allow the dup and auto-increase the soft limit,
which is itself questionable (and which we work around in the
gnulib getdtablesize module); but avoiding the crash is worth
doing even if the soft limit semantics are wrong.
http://cygwin.com/ml/cygwin/2013-09/msg00397.html
http://cygwin.com/ml/cygwin-developers/2013-q3/msg00010.html
* m4/dup2.m4 (gl_FUNC_DUP2): Expose the bug.
* m4/dup3.m4 (gl_FUNC_DUP3): Likewise.
* tests/test-dup2.c (main): Likewise.
* lib/dup2.c (rpl_dup2): Use setdtablesize to avoid it.
* lib/dup3.c (dup3): Likewise.
* doc/posix-functions/dup2.texi (dup2): Document it.
* doc/glibc-functions/dup3.texi (dup3): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
author | Eric Blake <eblake@redhat.com> |
---|---|
date | Thu, 26 Sep 2013 07:07:07 -0600 |
parents | ae8079a89eec |
children | 375bd75c4123 |
files | ChangeLog doc/glibc-functions/dup3.texi doc/posix-functions/dup2.texi lib/dup2.c lib/dup3.c m4/dup2.m4 m4/dup3.m4 tests/test-dup2.c tests/test-dup3.c |
diffstat | 9 files changed, 50 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Thu Sep 26 11:26:29 2013 -0600 +++ b/ChangeLog Thu Sep 26 07:07:07 2013 -0600 @@ -1,5 +1,14 @@ 2013-09-26 Eric Blake <eblake@redhat.com> + dup2, dup3: work around another cygwin crasher + * m4/dup2.m4 (gl_FUNC_DUP2): Expose the bug. + * m4/dup3.m4 (gl_FUNC_DUP3): Likewise. + * tests/test-dup2.c (main): Likewise. + * lib/dup2.c (rpl_dup2): Use setdtablesize to avoid it. + * lib/dup3.c (dup3): Likewise. + * doc/posix-functions/dup2.texi (dup2): Document it. + * doc/glibc-functions/dup3.texi (dup3): Likewise. + getdtablesize: work around cygwin issue * m4/getdtablesize.m4 (gl_FUNC_GETDTABLESIZE): Detect problem. * modules/getdtablesize (configure.ac): Build replacement.
--- a/doc/glibc-functions/dup3.texi Thu Sep 26 11:26:29 2013 -0600 +++ b/doc/glibc-functions/dup3.texi Thu Sep 26 07:07:07 2013 -0600 @@ -10,6 +10,10 @@ This function is missing on many non-glibc platforms: Mac OS X 10.5, FreeBSD 6.0, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 5.1, HP-UX 11, IRIX 6.5, OSF/1 5.1, Solaris 11 2011-11, Cygwin 1.7.1, mingw, MSVC 9, Interix 3.5, BeOS. + +@item +This function can crash on some platforms: +Cygwin 1.7.25. @end itemize Portability problems not fixed by Gnulib:
--- a/doc/posix-functions/dup2.texi Thu Sep 26 11:26:29 2013 -0600 +++ b/doc/posix-functions/dup2.texi Thu Sep 26 07:07:07 2013 -0600 @@ -21,6 +21,10 @@ Cygwin 1.7.17, MSVC 9. @item +This function crashes when invoked with valid arguments on some platforms: +Cygwin 1.7.25. + +@item This function resets the @code{FD_CLOEXEC} flag when duplicating an fd to itself on some platforms: Haiku.
--- a/lib/dup2.c Thu Sep 26 11:26:29 2013 -0600 +++ b/lib/dup2.c Thu Sep 26 07:07:07 2013 -0600 @@ -96,7 +96,11 @@ /* On Linux kernels 2.6.26-2.6.29, dup2 (fd, fd) returns -EBADF. On Cygwin 1.5.x, dup2 (1, 1) returns 0. On Cygwin 1.7.17, dup2 (1, -1) dumps core. + On Cygwin 1.7.25, dup2 (1, 256) can dump core. On Haiku, dup2 (fd, fd) mistakenly clears FD_CLOEXEC. */ +# if HAVE_SETDTABLESIZE + setdtablesize (desired_fd + 1); +# endif if (desired_fd < 0) fd = desired_fd; if (fd == desired_fd)
--- a/lib/dup3.c Thu Sep 26 11:26:29 2013 -0600 +++ b/lib/dup3.c Thu Sep 26 07:07:07 2013 -0600 @@ -30,6 +30,10 @@ { #if HAVE_DUP3 # undef dup3 +# if HAVE_SETDTABLESIZE + /* Avoid a cygwin crasher. */ + setdtablesize (newfd + 1); +# endif /* Try the system call first, if it exists. (We may be running with a glibc that has the function but with an older kernel that lacks it.) */ {
--- a/m4/dup2.m4 Thu Sep 26 11:26:29 2013 -0600 +++ b/m4/dup2.m4 Thu Sep 26 07:07:07 2013 -0600 @@ -1,4 +1,4 @@ -#serial 19 +#serial 20 dnl Copyright (C) 2002, 2005, 2007, 2009-2013 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -39,9 +39,11 @@ /* Many gnulib modules require POSIX conformance of EBADF. */ if (dup2 (2, 1000000) == -1 && errno != EBADF) result |= 16; - /* Flush out a cygwin core dump. */ + /* Flush out some cygwin core dumps. */ if (dup2 (2, -1) != -1 || errno != EBADF) result |= 32; + dup2 (2, 255); + dup2 (2, 256); return result; ]) ], @@ -65,6 +67,7 @@ *yes) ;; *) REPLACE_DUP2=1 + AC_CHECK_FUNCS([setdtablesize]) ;; esac fi
--- a/m4/dup3.m4 Thu Sep 26 11:26:29 2013 -0600 +++ b/m4/dup3.m4 Thu Sep 26 07:07:07 2013 -0600 @@ -1,4 +1,4 @@ -# dup3.m4 serial 4 +# dup3.m4 serial 5 dnl Copyright (C) 2009-2013 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -11,7 +11,7 @@ dnl Persuade glibc <unistd.h> to declare dup3(). AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) - AC_CHECK_FUNCS_ONCE([dup3]) + AC_CHECK_FUNCS_ONCE([dup3 setdtablesize]) if test $ac_cv_func_dup3 != yes; then HAVE_DUP3=0 fi
--- a/tests/test-dup2.c Thu Sep 26 11:26:29 2013 -0600 +++ b/tests/test-dup2.c Thu Sep 26 07:07:07 2013 -0600 @@ -150,6 +150,15 @@ errno = 0; ASSERT (dup2 (fd, -2) == -1); ASSERT (errno == EBADF); + if (bad_fd > 256) + { + ASSERT (dup2 (fd, 255) == 255); + ASSERT (dup2 (fd, 256) == 256); + ASSERT (close (255) == 0); + ASSERT (close (256) == 0); + } + ASSERT (dup2 (fd, bad_fd - 1) == bad_fd - 1); + ASSERT (close (bad_fd - 1) == 0); errno = 0; ASSERT (dup2 (fd, bad_fd) == -1); ASSERT (errno == EBADF);
--- a/tests/test-dup3.c Thu Sep 26 11:26:29 2013 -0600 +++ b/tests/test-dup3.c Thu Sep 26 07:07:07 2013 -0600 @@ -124,6 +124,15 @@ errno = 0; ASSERT (dup3 (fd, -2, o_flags) == -1); ASSERT (errno == EBADF); + if (bad_fd > 256) + { + ASSERT (dup3 (fd, 255, 0) == 255); + ASSERT (dup3 (fd, 256, 0) == 256); + ASSERT (close (255) == 0); + ASSERT (close (256) == 0); + } + ASSERT (dup3 (fd, bad_fd - 1, 0) == bad_fd - 1); + ASSERT (close (bad_fd - 1) == 0); errno = 0; ASSERT (dup3 (fd, bad_fd, o_flags) == -1); ASSERT (errno == EBADF);