Search code examples
clinuxposixwaitwaitpid

Waitpid blocks forever


I have a little confusion with waitpid function:

int main(int argc, char** argv) {
    if (pid_t pid = fork()) {
        setpgid(pid, pid);
        waitpid(pid, NULL, 0);
    } else {
        setpgid(0, 0);
        char *args[] = {"man", "2", "pipe", NULL};
        execvp(args[0], args);
    }

    return 0;
}

In this example program just blocks and to nothing. The same story goes with less and every program which waits for you to press 'q'. On the other hand if I replace man with say "ls" - everything works perfectly: it prints content of a directory.

char *args[] = {"ls", NULL};

So what is it so special about man?

EDIT: I forget to say that I need the process to be the leader of a group. In case I remove setpgid() everything is also OK:

int main(int argc, char** argv) {
    if (pid_t pid = fork()) {
        waitpid(pid, NULL, 0);
    } else {
        char *args[] = {"man", "2", "pipe", NULL};
        execvp(args[0], args);
    }

    return 0;
}

Solution

  • You are putting the child process in its own process group. The session's controlling terminal has only one foreground process group at any given time, and you do nothing to put the child's process group in the foreground. Therefore, it does not receive keyboard input, and its standard output is not displayed on the terminal.

    Because the command you are exec'ing in the child waits for keyboard input that will never come while that command is in the background, that command never exits, and waitpid() never collects it.

    Unless you have a specific reason for putting the child in a different process group, you probably should not do so.