/ Published in: C++
                    
                                        
With the typical fork+exec method of spawning an application, you are left in the dark about failures in the exec.  Once the fork occurs, the "main" process doesn't have any communication channel except waitpid, so it's hard to tell what happened.
With this function, a pipe is opened for the forked child to communicate errors. If the exec succeeds, then the pipe is automatically closed, and the main process reports success. Otherwise, the errno from exec is communicated through the pipe.
                With this function, a pipe is opened for the forked child to communicate errors. If the exec succeeds, then the pipe is automatically closed, and the main process reports success. Otherwise, the errno from exec is communicated through the pipe.
                            
                                Expand |
                                Embed | Plain Text
                            
                        
                        Copy this code and paste it in your HTML
#include <errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
pid_t
spawn(const char *file, char *const argv[])
{
pid_t pid;
int forkpipe[2];
int fd_flags, err, ret;
// set up a pipe for communication between forks
ret = pipe(forkpipe);
if (ret == -1)
return -1;
pid = fork();
if (pid == -1) {
err = errno;
// close the write pipe
close(forkpipe[1]);
goto parent_exit;
}
if (pid == 0) {
// forked child
// close the read pipe
ret = close(forkpipe[0]);
if (ret == -1)
goto child_err;
// make the write end close-on-exec
ret = fcntl(forkpipe[1], F_GETFD);
if (ret == -1)
goto child_err;
fd_flags = ret | FD_CLOEXEC;
ret = fcntl(forkpipe[1], F_SETFD, fd_flags);
if (ret == -1)
goto child_err;
// try to run the app
execvp(file, argv);
// if we continue executing here, an error occurred
child_err:
// send the error code through the write pipe
err = errno;
write(forkpipe[1], &err, sizeof(err));
exit(1);
}
// parent
// close the write pipe
close(forkpipe[1]);
// get the error code from the read pipe
ret = read(forkpipe[0], &err, sizeof(err));
if (ret == -1) {
err = errno;
pid = -1;
} else if (ret == sizeof(err))
pid = -1;
else
err = 0;
parent_exit:
// close the read pipe
close(forkpipe[0]);
if (err)
errno = err;
return pid;
}
Comments
 Subscribe to comments
                    Subscribe to comments
                
                