summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Blake <eblake@redhat.com>2013-09-26 11:26:29 -0600
committerEric Blake <eblake@redhat.com>2013-09-26 13:16:03 -0600
commit3bd0d48db800994cc10c3340c41d3242390dc68f (patch)
treec7dbaa2d28baa06e25645eaec87102fa32d83a58
parent883e87df0a2236794c97afdd985c3706074d3195 (diff)
downloadgnulib-3bd0d48db800994cc10c3340c41d3242390dc68f.tar.gz
getdtablesize: work around cygwin issue
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 <eblake@redhat.com>
-rw-r--r--ChangeLog12
-rw-r--r--doc/glibc-functions/getdtablesize.texi5
-rw-r--r--lib/getdtablesize.c33
-rw-r--r--lib/unistd.in.h13
-rw-r--r--m4/getdtablesize.m431
-rw-r--r--m4/unistd_h.m43
-rw-r--r--modules/getdtablesize5
-rw-r--r--modules/unistd1
-rw-r--r--tests/test-getdtablesize.c2
9 files changed, 92 insertions, 13 deletions
diff --git a/ChangeLog b/ChangeLog
index 770710c0b2..812ea54833 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2013-09-26 Eric Blake <eblake@redhat.com>
+
+ 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 <gnu@gisladisker.se>
pmccabe2html: escaping of special characters
diff --git a/doc/glibc-functions/getdtablesize.texi b/doc/glibc-functions/getdtablesize.texi
index d342b2f52a..c28a546537 100644
--- a/doc/glibc-functions/getdtablesize.texi
+++ b/doc/glibc-functions/getdtablesize.texi
@@ -9,6 +9,11 @@ Portability problems fixed by Gnulib:
@item
This function is missing on some platforms:
mingw, MSVC 9.
+
+@item
+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 9947405af6..355c17e3b9 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 2543a40005..bd2b09961b 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 !@HAVE_GETDTABLESIZE@
+# 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 !@HAVE_GETDTABLESIZE@
_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 8f04b3b8c2..b3fa1af6a5 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 32dcfa5820..4231578cf2 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 109be1fda1..1c2d642777 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 c887d4f16f..c470ba6029 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 7046481ba3..b371ccf0d4 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;
}