开发者

No Child Process Error from waitpid() when waiting for process group

Writing my own toy shell, and have run into a bump trying to implement job control.

I am setting the process group of the child, both in the child and the parent with setpgid. My wait call is:

pid = waitpid(-pid, &status, 0)

However, waitpid returns -1 and perror says "No child process". However, it does seem to wait every time. Also, ps output looks right to mean when run from the shell. Since ps parent's process is kbsh like I would expect.

% ps -o pid,ppid,pgrp,session,tpgid,comm
Forking
In Parent: Setting process group to 20809 of process 20809 with setpgid
In Child Processes, pid of child process is 20809
in Child: Setting process group to 20809 of process 20809 with setpgid
Requesting that Process Group 20809 becomes the foreground process with tcsetpgrp
Waiting for job with process group 20809
  PID  PPID  PGRP  SESS TPGID COMMAND
12002 32573 12002 12002 20809 zsh
20808 12002 20808 12002 208开发者_如何学Python09 kbsh
20809 20808 20809 12002 20809 ps
Wait Error: No child processes
Restoring Shell process group 20808 to forground

Anyone see what I am doing wrong? can post more code if need be...


I was ignoring sigchld, from the waitpid man page:

POSIX.1-2001 specifies that if the disposition of SIGCHLD is set to SIG_IGN or the SA_NOCLDWAIT flag is set for SIGCHLD (see sigaction(2)), then children that terminate do not become zombies and a call to wait() or waitpid() will block until all children have terminated, and then fail with errno set to ECHILD. (The original POSIX standard left the behaviour of setting SIGCHLD to SIG_IGN unspecified.) Linux 2.6 conforms to this specification. However, Linux 2.4 (and earlier) does not: if a wait() or waitpid() call is made while SIGCHLD is being ignored, the call behaves just as though SIGCHLD were not being ignored, that is, the call blocks until the next child terminates and then returns the process ID and status of that child.


I found this thread while trying to implement a tiny shell for my computer science course, and figured I would share what worked for me. I was getting the following error:

Waitpid error: No child processes

In my case, I was using a wrapper provided by the Computer Systems: A Programmer’s Perspective textbook. To fix my error, I changed Waitpid in csapp.c from

pid_t Waitpid(pid_t pid, int *iptr, int options) 
{
    pid_t retpid;

    if ((retpid  = waitpid(pid, iptr, options)) < 0) 
        unix_error("Waitpid error");
    return(retpid);
}

to

pid_t Waitpid(pid_t pid, int *iptr, int options)
{
        pid_t retpid;

        retpid  = waitpid(pid, iptr, options);
        if (retpid < 0 && errno != ECHILD)
                unix_error("Waitpid error");
        return(retpid);
}


You don't have to set the process group ID. The child inherits the parent's pid as group by default. When you wait, you need to wait for the parent's pid:

int main(int argc, char **argv)
{
    pid_t pid;
    int stat;

    if ((pid = fork()))
    {
        printf("PARENT: %d | CHILD: %d\n", getpid(), pid);
        waitpid(-getpid(), &stat, 0);
        printf("DONE: %m\n");
    }
    else
    {
        printf("CHILD: %d\n", getpid());
        sleep(3);
    }
    return 0;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜