Skip to content

Instantly share code, notes, and snippets.

@savanovich
Last active August 29, 2015 14:21
Show Gist options
  • Save savanovich/b7ebf5e4ad3460e5c5c3 to your computer and use it in GitHub Desktop.
Save savanovich/b7ebf5e4ad3460e5c5c3 to your computer and use it in GitHub Desktop.
Safe posix_spawn alternative
/*
http://blog.kazuhooku.com/2015/05/how-to-properly-spawn-external-command.html
https://github.com/h2o/h2o/blob/08e6f20b0e85b830f6334253b72735bb15980dab/lib/common/serverutil.c
*/
pid_t safe_spawnp(const char *cmd, char **argv)
{
int pipefds[2] = {-1, -1}, errnum;
pid_t pid;
ssize_t rret;
/* create pipe, used for sending error codes */
if (pipe2(pipefds, O_CLOEXEC) != 0)
goto Error;
/* fork */
if ((pid = fork()) == -1)
goto Error;
if (pid == 0) {
/* in child process */
execvp(cmd, argv);
errnum = errno;
write(pipefds[1], &errnum, sizeof(errnum));
_exit(127);
}
/* parent process */
close(pipefds[1]);
pipefds[1] = -1;
errnum = 0;
while ((rret = read(pipefds[0], &errnum, sizeof(errnum))) == -1
&& errno == EINTR)
;
if (rret != 0) {
/* spawn failed */
while (waitpid(pid, NULL, 0) != pid)
;
pid = -1;
errno = errnum;
goto Error;
}
/* spawn succeeded */
close(pipefds[0]);
return pid;
Error:
errnum = errno;
if (pipefds[0] != -1)
close(pipefds[0]);
if (pipefds[1] != -1)
close(pipefds[1]);
errno = errnum;
return -1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment