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

ruby-changes:39751

From: nobu <ko1@a...>
Date: Sat, 12 Sep 2015 14:30:11 +0900 (JST)
Subject: [ruby-changes:39751] nobu:r51832 (trunk): process.c: do not inherit saved fds

nobu	2015-09-12 14:30:05 +0900 (Sat, 12 Sep 2015)

  New Revision: 51832

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

  Log:
    process.c: do not inherit saved fds
    
    * process.c (save_redirect_fd): make saved FDs close-on-exec not
      to be inherited.
    * process.c (run_exec_dup2): restore close-on-exec flags too.

  Modified files:
    trunk/ChangeLog
    trunk/process.c
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 51831)
+++ ChangeLog	(revision 51832)
@@ -1,4 +1,9 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
-Sat Sep 12 14:23:20 2015  Nobuyoshi Nakada  <nobu@r...>
+Sat Sep 12 14:30:03 2015  Nobuyoshi Nakada  <nobu@r...>
+
+	* process.c (save_redirect_fd): make saved FDs close-on-exec not
+	  to be inherited.
+
+	* process.c (run_exec_dup2): restore close-on-exec flags too.
 
 	* win32/win32.c (fcntl): implement F_GETFD, F_SETFD, and
 	  F_DUPFD_CLOEXEC.
Index: process.c
===================================================================
--- process.c	(revision 51831)
+++ process.c	(revision 51832)
@@ -350,6 +350,24 @@ redirect_dup2(int oldfd, int newfd) https://github.com/ruby/ruby/blob/trunk/process.c#L350
 }
 
 static int
+redirect_cloexec_dup(int oldfd)
+{
+    int ret;
+    ret = rb_cloexec_dup(oldfd);
+    ttyprintf("cloexec_dup(%d) => %d\n", oldfd, ret);
+    return ret;
+}
+
+static int
+redirect_cloexec_dup2(int oldfd, int newfd)
+{
+    int ret;
+    ret = rb_cloexec_dup2(oldfd, newfd);
+    ttyprintf("cloexec_dup2(%d, %d) => %d\n", oldfd, newfd, ret);
+    return ret;
+}
+
+static int
 redirect_close(int fd)
 {
     int ret;
@@ -379,6 +397,8 @@ parent_redirect_close(int fd) https://github.com/ruby/ruby/blob/trunk/process.c#L397
 #else
 #define redirect_dup(oldfd) dup(oldfd)
 #define redirect_dup2(oldfd, newfd) dup2((oldfd), (newfd))
+#define redirect_cloexec_dup(oldfd) rb_cloexec_dup(oldfd)
+#define redirect_cloexec_dup2(oldfd, newfd) rb_cloexec_dup2((oldfd), (newfd))
 #define redirect_close(fd) close_unless_reserved(fd)
 #define parent_redirect_open(pathname, flags, perm) rb_cloexec_open((pathname), (flags), (perm))
 #define parent_redirect_close(fd) close_unless_reserved(fd)
@@ -2598,12 +2618,16 @@ rb_f_exec(int argc, const VALUE *argv) https://github.com/ruby/ruby/blob/trunk/process.c#L2618
 #define ERRMSG1(str, a) do { if (errmsg && 0 < errmsg_buflen) snprintf(errmsg, errmsg_buflen, (str), (a)); } while (0)
 #define ERRMSG2(str, a, b) do { if (errmsg && 0 < errmsg_buflen) snprintf(errmsg, errmsg_buflen, (str), (a), (b)); } while (0)
 
+static int fd_get_cloexec(int fd, char *errmsg, size_t errmsg_buflen);
+static int fd_set_cloexec(int fd, char *errmsg, size_t errmsg_buflen);
+static int fd_clear_cloexec(int fd, char *errmsg, size_t errmsg_buflen);
+
 static int
 save_redirect_fd(int fd, struct rb_execarg *sargp, char *errmsg, size_t errmsg_buflen)
 {
     if (sargp) {
-        VALUE newary;
-        int save_fd = redirect_dup(fd);
+        VALUE newary, redirection;
+        int save_fd = redirect_cloexec_dup(fd), cloexec;
         if (save_fd == -1) {
             if (errno == EBADF)
                 return 0;
@@ -2616,8 +2640,10 @@ save_redirect_fd(int fd, struct rb_execa https://github.com/ruby/ruby/blob/trunk/process.c#L2640
             newary = hide_obj(rb_ary_new());
             sargp->fd_dup2 = newary;
         }
-        rb_ary_push(newary,
-                    hide_obj(rb_assoc_new(INT2FIX(fd), INT2FIX(save_fd))));
+	cloexec = fd_get_cloexec(fd, errmsg, errmsg_buflen);
+	redirection = hide_obj(rb_assoc_new(INT2FIX(fd), INT2FIX(save_fd)));
+	if (cloexec) rb_ary_push(redirection, Qtrue);
+	rb_ary_push(newary, redirection);
 
         newary = sargp->fd_close;
         if (newary == Qfalse) {
@@ -2647,6 +2673,7 @@ struct run_exec_dup2_fd_pair { https://github.com/ruby/ruby/blob/trunk/process.c#L2673
     int newfd;
     long older_index;
     long num_newer;
+    int cloexec;
 };
 
 static long
@@ -2657,6 +2684,45 @@ run_exec_dup2_tmpbuf_size(long n) https://github.com/ruby/ruby/blob/trunk/process.c#L2684
 
 /* This function should be async-signal-safe.  Actually it is. */
 static int
+fd_get_cloexec(int fd, char *errmsg, size_t errmsg_buflen)
+{
+#ifdef F_GETFD
+    int ret = 0;
+    ret = fcntl(fd, F_GETFD); /* async-signal-safe */
+    if (ret == -1) {
+        ERRMSG("fcntl(F_GETFD)");
+        return -1;
+    }
+    if (ret & FD_CLOEXEC) return 1;
+#endif
+    return 0;
+}
+
+/* This function should be async-signal-safe.  Actually it is. */
+static int
+fd_set_cloexec(int fd, char *errmsg, size_t errmsg_buflen)
+{
+#ifdef F_GETFD
+    int ret = 0;
+    ret = fcntl(fd, F_GETFD); /* async-signal-safe */
+    if (ret == -1) {
+        ERRMSG("fcntl(F_GETFD)");
+        return -1;
+    }
+    if (!(ret & FD_CLOEXEC)) {
+        ret |= FD_CLOEXEC;
+        ret = fcntl(fd, F_SETFD, ret); /* async-signal-safe */
+        if (ret == -1) {
+            ERRMSG("fcntl(F_SETFD)");
+            return -1;
+        }
+    }
+#endif
+    return 0;
+}
+
+/* This function should be async-signal-safe.  Actually it is. */
+static int
 fd_clear_cloexec(int fd, char *errmsg, size_t errmsg_buflen)
 {
 #ifdef F_GETFD
@@ -2695,6 +2761,7 @@ run_exec_dup2(VALUE ary, VALUE tmpbuf, s https://github.com/ruby/ruby/blob/trunk/process.c#L2761
         VALUE elt = RARRAY_AREF(ary, i);
         pairs[i].oldfd = FIX2INT(RARRAY_AREF(elt, 1));
         pairs[i].newfd = FIX2INT(RARRAY_AREF(elt, 0)); /* unique */
+        pairs[i].cloexec = RARRAY_LEN(elt) > 2 && RTEST(RARRAY_AREF(elt, 2));
         pairs[i].older_index = -1;
     }
 
@@ -2733,6 +2800,10 @@ run_exec_dup2(VALUE ary, VALUE tmpbuf, s https://github.com/ruby/ruby/blob/trunk/process.c#L2800
                 ERRMSG("dup2");
                 goto fail;
             }
+	    if (pairs[j].cloexec &&
+		fd_set_cloexec(pairs[j].newfd, errmsg, errmsg_buflen)) {
+		goto fail;
+	    }
             rb_update_max_fd(pairs[j].newfd); /* async-signal-safe but don't need to call it in a child process. */
             pairs[j].oldfd = -1;
             j = pairs[j].older_index;

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

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