Help with wait or waitpid

Help with wait or waitpid

Post by Abhinav D » Sun, 22 Sep 2002 15:39:05



Hi,

I am writing a C program that acts like a Unix shell. In my shell, the
parent shell forks and the child then creates more children depending
on the number of processes to execute in parallel. The algorithm is,
the main child forks again and the child process is used to create
another process while the parent changes its environment using the
execvp command. The new child may fork more or do an exec if it has
the last process. The problem is that the shell(main parent) must wait
for all these processes to end before displaying the prompt. I use the
wait system call but as soon as the first child finishes the parent
displays the prompt with the message that "There are no more
children". How can I wait for all these "grandchildren" and
"great-grandchildren" i.e. children created by the main child process.
The parent seems to know nothing about them. I am a new to such kind
of programming so any help would be greatly appreciated.

Abhinav

 
 
 

Help with wait or waitpid

Post by Barry Margoli » Wed, 25 Sep 2002 07:31:20




>I am writing a C program that acts like a Unix shell. In my shell, the
>parent shell forks and the child then creates more children depending
>on the number of processes to execute in parallel. The algorithm is,
>the main child forks again and the child process is used to create
>another process while the parent changes its environment using the
>execvp command. The new child may fork more or do an exec if it has
>the last process. The problem is that the shell(main parent) must wait
>for all these processes to end before displaying the prompt. I use the
>wait system call but as soon as the first child finishes the parent
>displays the prompt with the message that "There are no more
>children". How can I wait for all these "grandchildren" and
>"great-grandchildren" i.e. children created by the main child process.
>The parent seems to know nothing about them. I am a new to such kind
>of programming so any help would be greatly appreciated.

A process can only wait for its immediate children.

You should either fork all the child processes directly from the parent
shell process and then have it wait for all of them, or have each child
that forks again wait for its child before it exits.

What I think most real shells do is something in between.  The parent shell
forks a single child process and waits for it.  If the command is a
pipeline of N commands, that first child then forks N-1 grandchild
processes for each command, and the child process executes the last command
in the pipeline.  The original shell waits only for this child process.

Here's an example using ksh on Solaris 2.6:

$ (sleep 100 | sleep 50 | sleep 10) &
[1]     1656
$ ps ltpts/8
 F   UID   PID  PPID %C PRI NI   SZ  RSS    WCHAN S TT        TIME COMMAND
 8 10892   708   564  0  58 20 1952 1512 nksyms_c S pts/8     0:00 /bin/tcsh -i
 8 10892  1655   708  0  38 20 1616 1216          R pts/8     0:00 ksh
 8 10892  1656  1655  0  36 24  824  600 nksyms_i S pts/8     0:00 sleep 10
 8 10892  1657  1656  0  56 24  824  600 nksyms_i S pts/8     0:00 sleep 100
 8 10892  1658  1656  0  46 24  824  600 nksyms_i S pts/8     0:00 sleep 50
 8     0  1659  1655  0  59 20 1240 1080          O pts/8     0:00 ps ltpts/8

1656 is the child, 1657 and 1658 are the grandchildren.  I wait about 10
seconds.

$ ps ltpts/8
 F   UID   PID  PPID %C PRI NI   SZ  RSS    WCHAN S TT        TIME COMMAND
 8 10892   708   564  0  58 20 1952 1512 nksyms_c S pts/8     0:00 /bin/tcsh -i
 8 10892  1655   708  0  48 20 1616 1216          R pts/8     0:00 ksh
 8 10892  1657     1  0  56 24  824  600 nksyms_i S pts/8     0:00 sleep 100
 8 10892  1658     1  0  46 24  824  600 nksyms_i S pts/8     0:00 sleep 50
 8     0  1660  1655  0  59 20 1240 1080          O pts/8     0:00 ps ltpts/8
[1] +  Done                    (sleep 100 | sleep 50 | sleep 10) &

The message comes out when the child exits, but the grandchildren are still
running.  They've become orphans, inherited by init (PPID = 1).

Bash works a little differently.  It creates a child whose only purpose is
to fork all the grandchildren.  All the commands get run in grandchildren
processes, and the child waits for all of them before exiting.

bash$ (sleep 100 | sleep 50 | sleep 10) &
[1] 1664
bash$ ps ltpts/8
 F   UID   PID  PPID %C PRI NI   SZ  RSS    WCHAN S TT        TIME COMMAND
 8 10892   708   564  0  58 20 1952 1512 nksyms_c S pts/8     0:00 /bin/tcsh -i
 8 10892  1663   708  0  38 20 1288 1176          R pts/8     0:00 bash
 8 10892  1664  1663  0  38 20 1288  888 nksyms_i S pts/8     0:00 bash
 8 10892  1665  1664  0  59 20  824  600 nksyms_i S pts/8     0:00 sleep 100
 8 10892  1666  1664  0  58 20  824  600 nksyms_i S pts/8     0:00 sleep 50
 8 10892  1667  1664  0  48 20  824  600 nksyms_i S pts/8     0:00 sleep 10
 8     0  1668  1663  0  59 20 1240 1080          O pts/8     0:00 ps ltpts/8

1664 is the child, 1665, 1666, and 1667 are the grandchildren.  I wait 10
second.

bash$ ps ltpts/8
 F   UID   PID  PPID %C PRI NI   SZ  RSS    WCHAN S TT        TIME COMMAND
 8 10892   708   564  0  58 20 1952 1512 nksyms_c S pts/8     0:00 /bin/tcsh -i
 8 10892  1663   708  0  38 20 1288 1176          R pts/8     0:00 bash
 8 10892  1664  1663  0  59 20 1288  888 nksyms_i S pts/8     0:00 bash
 8 10892  1665  1664  0  59 20  824  600 nksyms_i S pts/8     0:00 sleep 100
 8 10892  1666  1664  0  58 20  824  600 nksyms_i S pts/8     0:00 sleep 50
 8     0  1669  1663  0  59 20 1240 1080          O pts/8     0:00 ps ltpts/8

Now 1667 is gone, but I haven't been informed that the job is done yet.  I
wait another couple of minutes.

bash$ ps ltpts/8
 F   UID   PID  PPID %C PRI NI   SZ  RSS    WCHAN S TT        TIME COMMAND
 8 10892   708   564  0  58 20 1952 1512 nksyms_c S pts/8     0:00 /bin/tcsh -i
 8 10892  1663   708  0  38 20 1288 1176          R pts/8     0:00 bash
 8     0  1673  1663  0  59 20 1240 1080          O pts/8     0:00 ps ltpts/8
[1]+  Done                    ( sleep 100 | sleep 50 | sleep 10 )

Now they're all gone.

--

Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

 
 
 

Help with wait or waitpid

Post by Abhinav Da » Fri, 27 Sep 2002 12:11:24





> >I am writing a C program that acts like a Unix shell. In my shell, the
> >parent shell forks and the child then creates more children depending
> >on the number of processes to execute in parallel. The algorithm is,
> >the main child forks again and the child process is used to create
> >another process while the parent changes its environment using the
> >execvp command. The new child may fork more or do an exec if it has
> >the last process. The problem is that the shell(main parent) must wait
> >for all these processes to end before displaying the prompt. I use the
> >wait system call but as soon as the first child finishes the parent
> >displays the prompt with the message that "There are no more
> >children". How can I wait for all these "grandchildren" and
> >"great-grandchildren" i.e. children created by the main child process.
> >The parent seems to know nothing about them. I am a new to such kind
> >of programming so any help would be greatly appreciated.

> A process can only wait for its immediate children.

> You should either fork all the child processes directly from the parent
> shell process and then have it wait for all of them, or have each child
> that forks again wait for its child before it exits.

> What I think most real shells do is something in between.  The parent shell
> forks a single child process and waits for it.  If the command is a
> pipeline of N commands, that first child then forks N-1 grandchild
> processes for each command, and the child process executes the last command
> in the pipeline.  The original shell waits only for this child process.

> Here's an example using ksh on Solaris 2.6:

> $ (sleep 100 | sleep 50 | sleep 10) &
> [1]     1656
> $ ps ltpts/8
>  F   UID   PID  PPID %C PRI NI   SZ  RSS    WCHAN S TT        TIME COMMAND
>  8 10892   708   564  0  58 20 1952 1512 nksyms_c S pts/8     0:00 /bin/tcsh -i
>  8 10892  1655   708  0  38 20 1616 1216          R pts/8     0:00 ksh
>  8 10892  1656  1655  0  36 24  824  600 nksyms_i S pts/8     0:00 sleep 10
>  8 10892  1657  1656  0  56 24  824  600 nksyms_i S pts/8     0:00 sleep 100
>  8 10892  1658  1656  0  46 24  824  600 nksyms_i S pts/8     0:00 sleep 50
>  8     0  1659  1655  0  59 20 1240 1080          O pts/8     0:00 ps ltpts/8

> 1656 is the child, 1657 and 1658 are the grandchildren.  I wait about 10
> seconds.

> $ ps ltpts/8
>  F   UID   PID  PPID %C PRI NI   SZ  RSS    WCHAN S TT        TIME COMMAND
>  8 10892   708   564  0  58 20 1952 1512 nksyms_c S pts/8     0:00 /bin/tcsh -i
>  8 10892  1655   708  0  48 20 1616 1216          R pts/8     0:00 ksh
>  8 10892  1657     1  0  56 24  824  600 nksyms_i S pts/8     0:00 sleep 100
>  8 10892  1658     1  0  46 24  824  600 nksyms_i S pts/8     0:00 sleep 50
>  8     0  1660  1655  0  59 20 1240 1080          O pts/8     0:00 ps ltpts/8
> [1] +  Done                    (sleep 100 | sleep 50 | sleep 10) &

> The message comes out when the child exits, but the grandchildren are still
> running.  They've become orphans, inherited by init (PPID = 1).

> Bash works a little differently.  It creates a child whose only purpose is
> to fork all the grandchildren.  All the commands get run in grandchildren
> processes, and the child waits for all of them before exiting.

> bash$ (sleep 100 | sleep 50 | sleep 10) &
> [1] 1664
> bash$ ps ltpts/8
>  F   UID   PID  PPID %C PRI NI   SZ  RSS    WCHAN S TT        TIME COMMAND
>  8 10892   708   564  0  58 20 1952 1512 nksyms_c S pts/8     0:00 /bin/tcsh -i
>  8 10892  1663   708  0  38 20 1288 1176          R pts/8     0:00 bash
>  8 10892  1664  1663  0  38 20 1288  888 nksyms_i S pts/8     0:00 bash
>  8 10892  1665  1664  0  59 20  824  600 nksyms_i S pts/8     0:00 sleep 100
>  8 10892  1666  1664  0  58 20  824  600 nksyms_i S pts/8     0:00 sleep 50
>  8 10892  1667  1664  0  48 20  824  600 nksyms_i S pts/8     0:00 sleep 10
>  8     0  1668  1663  0  59 20 1240 1080          O pts/8     0:00 ps ltpts/8

> 1664 is the child, 1665, 1666, and 1667 are the grandchildren.  I wait 10
> second.

> bash$ ps ltpts/8
>  F   UID   PID  PPID %C PRI NI   SZ  RSS    WCHAN S TT        TIME COMMAND
>  8 10892   708   564  0  58 20 1952 1512 nksyms_c S pts/8     0:00 /bin/tcsh -i
>  8 10892  1663   708  0  38 20 1288 1176          R pts/8     0:00 bash
>  8 10892  1664  1663  0  59 20 1288  888 nksyms_i S pts/8     0:00 bash
>  8 10892  1665  1664  0  59 20  824  600 nksyms_i S pts/8     0:00 sleep 100
>  8 10892  1666  1664  0  58 20  824  600 nksyms_i S pts/8     0:00 sleep 50
>  8     0  1669  1663  0  59 20 1240 1080          O pts/8     0:00 ps ltpts/8

> Now 1667 is gone, but I haven't been informed that the job is done yet.  I
> wait another couple of minutes.

> bash$ ps ltpts/8
>  F   UID   PID  PPID %C PRI NI   SZ  RSS    WCHAN S TT        TIME COMMAND
>  8 10892   708   564  0  58 20 1952 1512 nksyms_c S pts/8     0:00 /bin/tcsh -i
>  8 10892  1663   708  0  38 20 1288 1176          R pts/8     0:00 bash
>  8     0  1673  1663  0  59 20 1240 1080          O pts/8     0:00 ps ltpts/8
> [1]+  Done                    ( sleep 100 | sleep 50 | sleep 10 )

> Now they're all gone.

> --

> Genuity, Woburn, MA
> *** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
> Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

Thanks for the reply. I thought of the same solution and implemented it.

Abhinav

 
 
 

1. wait, waitpid - help

Hello All,

the following is a handler for SIGCHLD signal in a program.
this function was written to prevent zombies and to terminate the
child by catching the SIGCHLD.

void sig_chld()
{
  pid_t pid;
  int stat;

 pid=wait(&stat);
 printf("child %d terminated \n",pid);
 return ;

the man pages are unclear about this :
now, i want to know what happens when  "  pid=wait(&stat) " statement
executes. how the child terminates (without becoming a zombie) . what is
the significance of "&stat ".
also in case of waitpid(-1,&stat, WNOHNG) --what happens here

Thanks
Srinath

2. SLIP oddity...route lost

3. fork,exec and wait and wait and wait and wait

4. RH6.2 install error: "no valid devices were found on which to create new filesystems"

5. Wait/Waitpid problem in gcc-2.72 on Slackware 3.1

6. Freeing space on root directory

7. wait()/waitpid() implementation in Linux doesn't conform to POSIX?

8. Which Linux dist.?

9. Wait/Waitpid

10. waitpid() does not wait for child to exit

11. wait(), waitpid question?

12. doubt about fork, wait and waitpid

13. wait(2) and waitpid(2) in a SIGCHLD handler