[前][次][番号順一覧][スレッド一覧]

ruby-changes:21756

From: akr <ko1@a...>
Date: Mon, 21 Nov 2011 23:41:27 +0900 (JST)
Subject: [ruby-changes:21756] akr:r33805 (trunk): * io.c (linux_get_maxfd): new function to find maximum fd on Linux.

akr	2011-11-21 23:40:09 +0900 (Mon, 21 Nov 2011)

  New Revision: 33805

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=33805

  Log:
    * io.c (linux_get_maxfd): new function to find maximum fd on Linux.
      (rb_close_before_exec): use linux_get_maxfd.

  Modified files:
    trunk/ChangeLog
    trunk/io.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 33804)
+++ ChangeLog	(revision 33805)
@@ -1,3 +1,8 @@
+Mon Nov 21 23:39:14 2011  Tanaka Akira  <akr@f...>
+
+	* io.c (linux_get_maxfd): new function to find maximum fd on Linux.
+	  (rb_close_before_exec): use linux_get_maxfd.
+
 Mon Nov 21 06:16:24 2011  NARUSE, Yui  <naruse@r...>
 
 	* cont.c (fiber_switch): ignore fiber context switch
Index: io.c
===================================================================
--- io.c	(revision 33804)
+++ io.c	(revision 33805)
@@ -5131,20 +5131,66 @@
     }
 }
 
+#if defined(__linux__)
+/* Linux /proc/self/status contains a line: "FDSize:\t<nnn>\n"
+ * Since /proc may not be available, linux_get_maxfd is just a hint.
+ * This function, linux_get_maxfd, must be async-signal-safe.
+ * I.e. opendir() is not usable.
+ *
+ * Note that memchr() and memcmp is *not* async-signal-safe in POSIX.
+ * However they are easy to re-implement in async-signal-safe manner.
+ * (Also note that there is missing/memcmp.c.)
+ */
+static int
+linux_get_maxfd(void)
+{
+    int fd;
+    char buf[4096], *p, *n, *e;
+    ssize_t ss;
+    fd = rb_cloexec_open("/proc/self/status", O_RDONLY|O_NOCTTY, 0);
+    if (fd == -1) return -1;
+    ss = read(fd, buf, sizeof(buf));
+    if (ss == -1) goto err;
+    p = buf;
+    e = buf + ss;
+    while (sizeof("FDSize:\t0\n")-1 <= e-p &&
+           (n = memchr(p, '\n', e-p)) != NULL) {
+        if (memcmp(p, "FDSize:", sizeof("FDSize:")-1) == 0) {
+            int fdsize;
+            p += sizeof("FDSize:")-1;
+            *n = '\0';
+            fdsize = (int)ruby_strtoul(p, (char **)NULL, 10);
+            close(fd);
+            return fdsize;
+        }
+        p = n+1;
+    }
+    /* fall through */
+
+  err:
+    close(fd);
+    return -1;
+}
+#endif
+
 void
 rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
 {
     int fd, ret;
     int max = max_file_descriptor;
-    if (max < maxhint)
-        max = maxhint;
 #ifdef F_MAXFD
     /* F_MAXFD is available since NetBSD 2.0. */
     ret = fcntl(0, F_MAXFD);
-    if (ret != -1) {
-        max = ret;
-    }
+    if (ret != -1)
+        maxhint = max = ret;
+#elif defined(__linux__)
+    ret = linux_get_maxfd();
+    if (maxhint < ret)
+        maxhint = ret;
+    /* maxhint = max = ret; if (ret == -1) abort(); // test */
 #endif
+    if (max < maxhint)
+        max = maxhint;
     for (fd = lowfd; fd <= max; fd++) {
         if (!NIL_P(noclose_fds) &&
             RTEST(rb_hash_lookup(noclose_fds, INT2FIX(fd))))

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]