Switch to side-by-side view

--- a/src/utils/closefrom.cpp
+++ b/src/utils/closefrom.cpp
@@ -50,7 +50,18 @@
  *     descriptors. Only descriptors 0, 1, 2 are shown except if
  *     fdescfs is mounted which it is not by default
  *
+ *  Solaris:
+ *   - Solaris 10+ has closefrom, and can specify closefrom to posix_spawn()
+ *
+ *  Linux:
+ *   - Has nothing. The method we used (opening /dev/fd) was very
+ *     unsafe in multithread fork/exec context. We now use a close()
+ *     loop. glibc maintainers think that closefrom() is a bad idea
+ *     *especially* because it is implemented on *BSD and Solaris. Go
+ *     figure...: https://sourceware.org/bugzilla/show_bug.cgi?id=10353
+ *
  * Interface:
+ *
  * int libclf_closefrom(fd)
  *  @param fd All open file descriptors with equal or higher numeric 
  *       values will be closed. fd needs not be a valid descriptor.
@@ -62,8 +73,12 @@
 #include <fcntl.h>
 #include <string.h>
 #include <sys/param.h>
-
-/* #define DEBUG_CLOSEFROM*/
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include "closefrom.h"
+
+/* #define DEBUG_CLOSEFROM */
 #ifdef DEBUG_CLOSEFROM
 #define DPRINT(X) fprintf X
 #else
@@ -110,7 +125,12 @@
 }
 
 /*************************************************************************/
-#elif (defined(linux) || defined(__linux))
+#elif 0 && (defined(linux) || defined(__linux))
+
+/* We don't do this on linux anymore because opendir() may call
+   malloc which is unsafe in the [fork-exec] interval for a
+   multithreaded program. Linux does not have a good solution for
+   implementing closefrom as far as I know */
 
 /* Use /proc/self/fd directory */
 #include <sys/types.h>
@@ -142,11 +162,16 @@
 
 /*************************************************************************/
 #else 
-/* System has no native support for this functionality whatsoever.
+
+/* System has no native support for this functionality.
  *
  * Close all descriptors up to compiled/configured maximum.
  * The caller will usually have an idea of a reasonable maximum, else
  * we retrieve a value from the system.
+ *
+ * Note that there is actually no real guarantee that no open
+ * descriptor higher than the reported limit can exist, as noted by
+ * the Solaris man page for closefrom()
  */
 
 static int closefrom_maxfd = -1;
@@ -156,21 +181,18 @@
     closefrom_maxfd = max;
 }
 
-#ifdef sun
 #include <limits.h>
-#endif
+
+#ifndef OPEN_MAX
+#define OPEN_MAX 1024
+#endif
+
 int libclf_closefrom(int fd0)
 {
     int i, maxfd = closefrom_maxfd;
 
     if (maxfd < 0) {
-#ifdef _SC_OPEN_MAX
-        maxfd = sysconf(_SC_OPEN_MAX);
-        DPRINT((stderr, "Maxfd is %d after sysconf()\n", maxfd));
-#else
-        maxfd = getdtablesize();
-        DPRINT((stderr, "Maxfd is %d after getdtablesize()\n", maxfd));
-#endif 
+        maxfd = libclf_maxfd();
     }
     if (maxfd < 0)
 	maxfd = OPEN_MAX;
@@ -184,6 +206,12 @@
 }
 #endif
 
+int libclf_maxfd(int)
+{
+    struct rlimit lim;
+    getrlimit(RLIMIT_NOFILE, &lim);
+    return int(lim.rlim_cur);
+}
 
 #else /* TEST_CLOSEFROM */