bug-gnulib
[Top][All Lists]
Advanced

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

[PATCH 1/2] getdtablesize: work around cygwin issue


From: Eric Blake
Subject: [PATCH 1/2] getdtablesize: work around cygwin issue
Date: Thu, 26 Sep 2013 12:38:33 -0600

Cygwin 1.7.25 has a bug that even though it claims to support
RLIMIT_NOFILE inheritance, there is no enforcement of the soft
limit, and getdtablesize() automatically grows until it reaches
the hard limit which cannot be changed by setrlimit().  Best is
to just treat things as an invariant limit, as several other
modules assume that getdtablesize() will not change without an
intervening setrlimit().

* m4/getdtablesize.m4 (gl_FUNC_GETDTABLESIZE): Detect problem.
* modules/getdtablesize (configure.ac): Build replacement.
* m4/unistd_h.m4 (gl_UNISTD_H_DEFAULTS): Set up a witness.
* modules/unistd (Makefile.am): Expose the witness.
* lib/unistd.in.h (getdtablesize): Declare replacement.
* lib/getdtablesize.c (rpl_getdtablesize): Work around it.
* tests/test-getdtablesize.c (main): Test it.
* doc/glibc-functions/getdtablesize.texi (getdtablesize): Document it.

Signed-off-by: Eric Blake <address@hidden>
---
 ChangeLog                              |   12 +++++++++++
 doc/glibc-functions/getdtablesize.texi |    5 ++++
 lib/getdtablesize.c                    |   33 ++++++++++++++++++++++++++-----
 lib/unistd.in.h                        |   13 ++++++++++-
 m4/getdtablesize.m4                    |   31 ++++++++++++++++++++++++++++-
 m4/unistd_h.m4                         |    3 +-
 modules/getdtablesize                  |    5 ++-
 modules/unistd                         |    1 +
 tests/test-getdtablesize.c             |    2 +
 9 files changed, 92 insertions(+), 13 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 770710c..812ea54 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2013-09-26  Eric Blake  <address@hidden>
+
+       getdtablesize: work around cygwin issue
+       * m4/getdtablesize.m4 (gl_FUNC_GETDTABLESIZE): Detect problem.
+       * modules/getdtablesize (configure.ac): Build replacement.
+       * m4/unistd_h.m4 (gl_UNISTD_H_DEFAULTS): Set up a witness.
+       * modules/unistd (Makefile.am): Expose the witness.
+       * lib/unistd.in.h (getdtablesize): Declare replacement.
+       * lib/getdtablesize.c (rpl_getdtablesize): Work around it.
+       * tests/test-getdtablesize.c (main): Test it.
+       * doc/glibc-functions/getdtablesize.texi (getdtablesize): Document it.
+
 2013-09-25  Mats Erik Andersson  <address@hidden>

        pmccabe2html: escaping of special characters
diff --git a/doc/glibc-functions/getdtablesize.texi 
b/doc/glibc-functions/getdtablesize.texi
index d342b2f..c28a546 100644
--- a/doc/glibc-functions/getdtablesize.texi
+++ b/doc/glibc-functions/getdtablesize.texi
@@ -9,6 +9,11 @@ getdtablesize
 @item
 This function is missing on some platforms:
 mingw, MSVC 9.
+
address@hidden
+This function does not represent the true @code{RLIMIT_NOFILE} soft
+limit on some platforms:
+Cygwin 1.7.25.
 @end itemize

 Portability problems not fixed by Gnulib:
diff --git a/lib/getdtablesize.c b/lib/getdtablesize.c
index 9947405..355c17e 100644
--- a/lib/getdtablesize.c
+++ b/lib/getdtablesize.c
@@ -22,11 +22,11 @@

 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__

-#include <stdio.h>
+# include <stdio.h>

-#include "msvc-inval.h"
+# include "msvc-inval.h"

-#if HAVE_MSVC_INVALID_PARAMETER_HANDLER
+# if HAVE_MSVC_INVALID_PARAMETER_HANDLER
 static int
 _setmaxstdio_nothrow (int newmax)
 {
@@ -44,10 +44,11 @@ _setmaxstdio_nothrow (int newmax)

   return result;
 }
-# define _setmaxstdio _setmaxstdio_nothrow
-#endif
+#  define _setmaxstdio _setmaxstdio_nothrow
+# endif

-/* Cache for the previous getdtablesize () result.  */
+/* Cache for the previous getdtablesize () result.  Safe to cache because
+   Windows also lacks setrlimit.  */
 static int dtablesize;

 int
@@ -83,4 +84,24 @@ getdtablesize (void)
   return dtablesize;
 }

+#elif HAVE_GETDTABLESIZE
+
+# include <sys/resource.h>
+# undef getdtablesize
+
+int
+rpl_getdtablesize(void)
+{
+  /* To date, this replacement is only compiled for Cygwin 1.7.25,
+     which auto-increased the RLIMIT_NOFILE soft limit until it
+     hits the compile-time constant hard limit of 3200.  Although
+     that version of cygwin supported a child process inheriting
+     a smaller soft limit, the smaller limit is not enforced, so
+     we might as well just report the hard limit.  */
+  struct rlimit lim;
+  if (!getrlimit (RLIMIT_NOFILE, &lim) && lim.rlim_max != RLIM_INFINITY)
+    return lim.rlim_max;
+  return getdtablesize ();
+}
+
 #endif
diff --git a/lib/unistd.in.h b/lib/unistd.in.h
index 2543a40..bd2b099 100644
--- a/lib/unistd.in.h
+++ b/lib/unistd.in.h
@@ -654,10 +654,19 @@ _GL_WARN_ON_USE (getdomainname, "getdomainname is 
unportable - "
 #if @GNULIB_GETDTABLESIZE@
 /* Return the maximum number of file descriptors in the current process.
    In POSIX, this is same as sysconf (_SC_OPEN_MAX).  */
-# if address@hidden@
+# if @REPLACE_GETDTABLESIZE@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef getdtablesize
+#   define getdtablesize rpl_getdtablesize
+#  endif
+_GL_FUNCDECL_RPL (getdtablesize, int, (void));
+_GL_CXXALIAS_RPL (getdtablesize, int, (void));
+# else
+#  if address@hidden@
 _GL_FUNCDECL_SYS (getdtablesize, int, (void));
-# endif
+#  endif
 _GL_CXXALIAS_SYS (getdtablesize, int, (void));
+# endif
 _GL_CXXALIASWARN (getdtablesize);
 #elif defined GNULIB_POSIXCHECK
 # undef getdtablesize
diff --git a/m4/getdtablesize.m4 b/m4/getdtablesize.m4
index 8f04b3b..e7dcff5 100644
--- a/m4/getdtablesize.m4
+++ b/m4/getdtablesize.m4
@@ -1,4 +1,4 @@
-# getdtablesize.m4 serial 4
+# getdtablesize.m4 serial 5
 dnl Copyright (C) 2008-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,
@@ -7,8 +7,35 @@ dnl with or without modifications, as long as this notice is 
preserved.
 AC_DEFUN([gl_FUNC_GETDTABLESIZE],
 [
   AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+  AC_REQUIRE([AC_CANONICAL_HOST])
   AC_CHECK_FUNCS_ONCE([getdtablesize])
-  if test $ac_cv_func_getdtablesize != yes; then
+  if test $ac_cv_func_getdtablesize = yes; then
+    # Cygwin 1.7.25 automatically increases the RLIMIT_NOFILE soft limit
+    # up to an unchangeable hard limit; all other platforms correctly
+    # require setrlimit before getdtablesize() can report a larger value.
+    AC_CACHE_CHECK([whether getdtablesize works],
+      [gl_cv_func_getdtablesize_works],
+      [AC_RUN_IFELSE([
+        AC_LANG_PROGRAM([[#include <unistd.h>]],
+          [int size = getdtablesize();
+           if (dup2 (0, getdtablesize()) != -1)
+             return 1;
+           if (size != getdtablesize())
+            return 2;
+          ])],
+        [gl_cv_func_getdtablesize_works=yes],
+       [gl_cv_func_getdtablesize_works=no],
+        [case "$host_os" in
+          cygwin*) # on cygwin 1.5.25, getdtablesize() automatically grows
+            gl_cv_func_getdtablesize_works="guessing no" ;;
+          *) gl_cv_func_getdtablesize_works="guessing yes" ;;
+         esac])
+      ])
+    case "$gl_cv_func_getdtablesize_works" in
+      *yes) ;;
+      *) REPLACE_GETDTABLESIZE=1 ;;
+    esac  
+  else
     HAVE_GETDTABLESIZE=0
   fi
 ])
diff --git a/m4/unistd_h.m4 b/m4/unistd_h.m4
index 32dcfa5..4231578 100644
--- a/m4/unistd_h.m4
+++ b/m4/unistd_h.m4
@@ -1,4 +1,4 @@
-# unistd_h.m4 serial 66
+# unistd_h.m4 serial 67
 dnl Copyright (C) 2006-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,
@@ -160,6 +160,7 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS],
   REPLACE_FTRUNCATE=0;    AC_SUBST([REPLACE_FTRUNCATE])
   REPLACE_GETCWD=0;       AC_SUBST([REPLACE_GETCWD])
   REPLACE_GETDOMAINNAME=0; AC_SUBST([REPLACE_GETDOMAINNAME])
+  REPLACE_GETDTABLESIZE=0; AC_SUBST([REPLACE_GETDTABLESIZE])
   REPLACE_GETLOGIN_R=0;   AC_SUBST([REPLACE_GETLOGIN_R])
   REPLACE_GETGROUPS=0;    AC_SUBST([REPLACE_GETGROUPS])
   REPLACE_GETPAGESIZE=0;  AC_SUBST([REPLACE_GETPAGESIZE])
diff --git a/modules/getdtablesize b/modules/getdtablesize
index 109be1f..1c2d642 100644
--- a/modules/getdtablesize
+++ b/modules/getdtablesize
@@ -7,11 +7,12 @@ m4/getdtablesize.m4

 Depends-on:
 unistd
+extensions
 msvc-inval      [test $HAVE_GETDTABLESIZE = 0]

 configure.ac:
 gl_FUNC_GETDTABLESIZE
-if test $HAVE_GETDTABLESIZE = 0; then
+if test $HAVE_GETDTABLESIZE = 0 || test $REPLACE_GETDTABLESIZE = 1; then
   AC_LIBOBJ([getdtablesize])
   gl_PREREQ_GETDTABLESIZE
 fi
@@ -26,5 +27,5 @@ License:
 LGPLv2+

 Maintainer:
-Bruno Haible
+Bruno Haible, Eric Blake

diff --git a/modules/unistd b/modules/unistd
index c887d4f..c470ba6 100644
--- a/modules/unistd
+++ b/modules/unistd
@@ -137,6 +137,7 @@ unistd.h: unistd.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) $(ARG_NONNULL_H
              -e 's|@''REPLACE_FTRUNCATE''@|$(REPLACE_FTRUNCATE)|g' \
              -e 's|@''REPLACE_GETCWD''@|$(REPLACE_GETCWD)|g' \
              -e 's|@''REPLACE_GETDOMAINNAME''@|$(REPLACE_GETDOMAINNAME)|g' \
+             -e 's|@''REPLACE_GETDTABLESIZE''@|$(REPLACE_GETDTABLESIZE)|g' \
              -e 's|@''REPLACE_GETLOGIN_R''@|$(REPLACE_GETLOGIN_R)|g' \
              -e 's|@''REPLACE_GETGROUPS''@|$(REPLACE_GETGROUPS)|g' \
              -e 's|@''REPLACE_GETPAGESIZE''@|$(REPLACE_GETPAGESIZE)|g' \
diff --git a/tests/test-getdtablesize.c b/tests/test-getdtablesize.c
index 7046481..b371ccf 100644
--- a/tests/test-getdtablesize.c
+++ b/tests/test-getdtablesize.c
@@ -29,6 +29,8 @@ int
 main (int argc, char *argv[])
 {
   ASSERT (getdtablesize () >= 3);
+  ASSERT (dup2 (0, getdtablesize() - 1) == getdtablesize () - 1);
+  ASSERT (dup2 (0, getdtablesize()) == -1);

   return 0;
 }
-- 
1.7.1




reply via email to

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