This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH v2] [BZ 18433] Check posix_spawn return value in case of failure


Using pipe approach to check status of child.The vfork usage (in the
spawni function) is more restricted therefore pipe approach would be
better. I use fallback (combination of pipe and fcntl with FD_CLOEXEC)
mode for platform which does not support pipe2.
diff --git a/ChangeLog b/ChangeLog
index eb731cc..b8a1efb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2015-09-13  Navid Rahimi  <rahimi.nv@gmail.com>
+
+	[BZ #18433]
+	* sysdeps/posix/spawni.c (__spawni): Check child status.
+
 2015-09-12  Rasmus Villemoes  <rv@rasmusvillemoes.dk>
 
	* sysdeps/unix/sysv/linux/getsysstats.c (__get_phys_pages):
diff --git a/sysdeps/posix/spawni.c b/sysdeps/posix/spawni.c
index eee9331..8994216 100644
--- a/sysdeps/posix/spawni.c
+++ b/sysdeps/posix/spawni.c
@@ -89,6 +89,24 @@ __spawni (pid_t *pid, const char *file,
   char *path, *p, *name;
   size_t len;
   size_t pathlen;
+  int pipefd[2];
+
+  errno = 0;
+  /* Open Read/Write pipe for parent/child communication.  */
+#ifdef __ASSUME_PIPE2
+  if (__pipe2 (pipefd, O_CLOEXEC))
+    return errno;
+#else
+  if (__pipe (pipefd))
+    return errno;
+  if (__fcntl(pipefd[0], F_SETFD, FD_CLOEXEC) == -1
+      || __fcntl(pipefd[1], F_SETFD, FD_CLOEXEC) == -1)
+    {
+      close(pipefd[0]);
+      close(pipefd[1]);
+      return errno;
+    }
+#endif
 
   /* Do this once.  */
   short int flags = attrp == NULL ? 0 : attrp->__flags;
@@ -109,20 +127,26 @@ __spawni (pid_t *pid, const char *file,
 
   if (new_pid != 0)
     {
-      if (new_pid < 0)
+      __close (pipefd[1]);
+      if (new_pid < 0){
+	__close (pipefd[0]);
 	return errno;
-
+      }
       /* The call was successful.  Store the PID if necessary.  */
       if (pid != NULL)
 	*pid = new_pid;
 
-      return 0;
+      __read (pipefd[0], &errno, sizeof errno);
+      __close (pipefd[0]);
+      return errno;
     }
+  else
+    __close (pipefd[0]);
 
   /* Set signal mask.  */
   if ((flags & POSIX_SPAWN_SETSIGMASK) != 0
       && __sigprocmask (SIG_SETMASK, &attrp->__ss, NULL) != 0)
-    _exit (SPAWN_ERROR);
+    goto fail;
 
   /* Set signal default action.  */
   if ((flags & POSIX_SPAWN_SETSIGDEF) != 0)
@@ -140,7 +164,7 @@ __spawni (pid_t *pid, const char *file,
       for (sig = 1; sig <= _NSIG; ++sig)
 	if (__sigismember (&attrp->__sd, sig) != 0
 	    && __sigaction (sig, &sa, NULL) != 0)
-	  _exit (SPAWN_ERROR);
+	  goto fail;
 
     }
 
@@ -150,25 +174,25 @@ __spawni (pid_t *pid, const char *file,
       == POSIX_SPAWN_SETSCHEDPARAM)
     {
       if (__sched_setparam (0, &attrp->__sp) == -1)
-	_exit (SPAWN_ERROR);
+	goto fail;
     }
   else if ((flags & POSIX_SPAWN_SETSCHEDULER) != 0)
     {
       if (__sched_setscheduler (0, attrp->__policy, &attrp->__sp) == -1)
-	_exit (SPAWN_ERROR);
+	goto fail;
     }
 #endif
 
   /* Set the process group ID.  */
   if ((flags & POSIX_SPAWN_SETPGROUP) != 0
       && __setpgid (0, attrp->__pgrp) != 0)
-    _exit (SPAWN_ERROR);
+    goto fail;
 
   /* Set the effective user and group IDs.  */
   if ((flags & POSIX_SPAWN_RESETIDS) != 0
       && (local_seteuid (__getuid ()) != 0
 	  || local_setegid (__getgid ()) != 0))
-    _exit (SPAWN_ERROR);
+    goto fail;
 
   /* Execute the file actions.  */
   if (file_actions != NULL)
@@ -196,7 +220,7 @@ __spawni (pid_t *pid, const char *file,
 		  if (action->action.close_action.fd < 0
 		      || action->action.close_action.fd >= fdlimit.rlim_cur)
 		    /* Signal the error.  */
-		    _exit (SPAWN_ERROR);
+		    goto fail;
 		}
 	      break;
 
@@ -209,7 +233,7 @@ __spawni (pid_t *pid, const char *file,
 
 		if (new_fd == -1)
 		  /* The `open' call failed.  */
-		  _exit (SPAWN_ERROR);
+		  goto fail;
 
 		/* Make sure the desired file descriptor is used.  */
 		if (new_fd != action->action.open_action.fd)
@@ -217,11 +241,11 @@ __spawni (pid_t *pid, const char *file,
 		    if (__dup2 (new_fd, action->action.open_action.fd)
 			!= action->action.open_action.fd)
 		      /* The `dup2' call failed.  */
-		      _exit (SPAWN_ERROR);
+		      goto fail;
 
 		    if (close_not_cancel (new_fd) != 0)
 		      /* The `close' call failed.  */
-		      _exit (SPAWN_ERROR);
+		      goto fail;
 		  }
 	      }
 	      break;
@@ -231,7 +255,7 @@ __spawni (pid_t *pid, const char *file,
 			  action->action.dup2_action.newfd)
 		  != action->action.dup2_action.newfd)
 		/* The `dup2' call failed.  */
-		_exit (SPAWN_ERROR);
+		goto fail;
 	      break;
 	    }
 	}
@@ -245,7 +269,7 @@ __spawni (pid_t *pid, const char *file,
       maybe_script_execute (file, argv, envp, xflags);
 
       /* Oh, oh.  `execve' returns.  This is bad.  */
-      _exit (SPAWN_ERROR);
+      goto fail;
     }
 
   /* We have to search for FILE on the path.  */
@@ -304,11 +328,15 @@ __spawni (pid_t *pid, const char *file,
 	  /* Some other error means we found an executable file, but
 	     something went wrong executing it; return the error to our
 	     caller.  */
-	  _exit (SPAWN_ERROR);
+	  goto fail;
 	    }
     }
   while (*p++ != '\0');
 
+ fail:
+  /* Send parent what was the reason of failure.  */
+  __write (pipefd[1], &errno, sizeof errno);
+  __close (pipefd[1]);
   /* Return with an error.  */
   _exit (SPAWN_ERROR);
 }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]