Dejwi
Dejwi

Reputation: 4487

Wait for forked child until it starts another program

I'm trying to start another process (daemon) from my own:

pid_t pid=fork();
if (pid==0) { /* child */
    static char *argv[]={NULL};
    execv("/sbin/daemon", argv);
    exit(127); /* only if execv fails */
}
/* parent */
sleep(5); /* ugly way to wait for /sbin/daemon */
/* THIS_POINT */

How can I get rid of this sleep? I have to be sure that after THIS_POINT the /sbin/daemon is already started.

What kind of approach would you suggest?

Upvotes: 1

Views: 70

Answers (1)

Jonathan Leffler
Jonathan Leffler

Reputation: 753890

If you have control over the daemon (so you can modify it if necessary), consider creating a pipe, and have the daemon write "OK" on its standard output (the write end of the pipe) when it is running (and then close it). Your parent process reads from the pipe and knows the daemon is running if it gets "OK". It would be sensible to include a newline after the OK; it is important to remember that the data read won't be null terminated.

int fd[2];
if (pipe(fd) != 0) { …report error… }
pid_t pid=fork();
if (pid < 0) { …report error… }
if (pid == 0)
{
    static char *argv[] = { "/sbin/daemon", NULL };
    dup2(fd[1], FILENO_STDOUT);
    close(fd[0]);
    close(fd[1]);
    execv(argv[0], argv);
    exit(127);
}
close(fd[1]);
char buffer[16];
if (read(fd[0], buffer, sizeof(buffer)) >= 2 && memcmp(buffer, "OK", 2) == 0)
    …daemon started successfully…
else
    …daemon failed…
close(fd[0]);

If you don't have control over the daemon, you can still create the pipe, but you have to rely on the daemon daemonizing itself properly by closing its standard output. In that case, the parent process will simply get zero bytes to read (EOF) from the pipe, and you then check with waitpid(pid, &status, WNOHANG) whether the child died (which would also give you EOF).

Upvotes: 2

Related Questions