简体   繁体   中英

waitpid not returning after child has exited

Using a fairly standard fork process:

int   pipe_to_child[2];
int   pipe_from_child[2];
int   child_exit_status = -1;

pid_t child_pid = fork();
if (child_pid == 0) {
    close(pipe_from_child[0]); // close their read end
    close(pipe_to_child[1]); // Close their write end
    dup2(pipe_to_child[0], STDIN_FILENO); // Tie the in pipe to stdin
    dup2(pipe_from_child[1], STDOUT_FILENO); // Tie stdout to the out pipe
    // Run the child process
    execve(file_to_run, argv_for_prog, env_for_prog);
}
else {
    close(pipe_from_child[1]); // close their write end
    close(pipe_to_child[0]); // Close their read end
    if (input_to_prog != NULL) write(pipe_to_child[1], input_to_prog, strlen(input_to_prog)); // Send the stdin stuff
    close(pipe_to_child[1]); // Done so send EOF

    // Wait for the child to end
    waitpid(child_pid, &child_exit_status, 0);

    // Do post end-of-child stuff
}

This generally works as expected.

However, when the child process, a shell script, sets a further process off in the background. Even though the child process then exits (and is no longer listed by ps ), the waitpid doesn't return.

The script is this case is meant to start inadyn-mt (a DDNS updater) running in the background.

#!/bin/sh
inadyn-mt --background

(If I put an & after inadyn-mt it makes no difference)

It turns out that the issue is that the pipes don't get closed. Although the child process exits fine, because it has spawned a further process, this process (even though it doesn't want them) is tied to the pipes to the child's stdin and stdout. The solution I used was to not set up the pipes when I was going to spin off a child from the child.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM