fork multiple shells

Hi,

i was trying to play with fork,exec and signal for spawning multiple new shells, but it seems that i'm doing blunder somewhere.

<sample code>

1 /*
2 * The idea is to fork multpile(equal to $ULIMIT) childs
3 * and replace their images with process:csh
4 * during this the parent will save the pids of all the spawned childs
5 * till count reaches $ULIMIT and will start killing all the
6 * childs.
7 /
8
9 /

10 * The implementation to store the PIDs of all the child
11 * forked here is using an array
12 /
13
14 #include <sys/types.h>
15 #include <unistd.h>
16 #include <stdio.h>
17 #include <signal.h>
18 #include <stdlib.h>
19 #include <errno.h>
20
21 #define ULIMIT 2
22 int main(void){
23 pid_t pid;
24 int count;
25 int ret;
26 int childpids[ULIMIT];
27 for(count = 0; count < ULIMIT; count++){
28 pid = vfork();
29 if(pid < 0){
30 perror("fork error");
31 exit(1);
32 }
33 if(pid == 0){ /In child,Replace it with a new process: csh/
34 ret = execlp("csh", "/bin/csh",(char )0);
35 if(ret){
36 fprintf(stderr,"could not exec csh for count: %d\n:",count);
37 exit(1);
38 }
39 }
40 else{ /In Parent/
41 printf("child's pid is %d\n",pid);
42 printf("count reached = %d\n",count);
43 childpids[count] = pid;
44 }
45 }
/
Now start killing all the childs(c- shells)
/
46 while(--count){
47 if(kill(SIGKILL,childpids[count]) == -1){
48 perror("kill error");
49 exit(1);
50 }
51 }
52 kill(SIGKILL,childpids[count]);
53 exit(EXIT_SUCCESS);
54 }

<sample code>

root@localhost ]# gcc -Wall -Werror fork-csh.c -o fork-csh

[root@localhost ]# ./fork-csh
# child id is 14318

[1]+ Stopped ./fork-csh

[root@localhost ]# ps -el|grep csh|grep -v grep
4 T 0 14317 12639 0 75 0 - 344 finish pts/1 00:00:00 fork-csh
4 Z 0 14318 14317 0 80 0 - 0 do_exi pts/1 00:00:00 csh <defunct>
4 T 0 14319 14317 0 75 0 - 421 finish pts/1 00:00:00 csh

instead of my logic working i get "zombie process"
please let me know how to let my logic working.

~amit

Hello,

You are getting zombies, because the child from childpids[0] isn't killed.
See in while(--count) : When count is 1 -> --count gives 0 and loop exits. The program "forget" to kill first child and when the father program closes, that child becomes a zombie.

You can replace the while loop with:
for(count-=1; count >= 0; count--) { ...
or something equivalent.

A note, I see you use vfork() for creating childrens.... which will always work fine in your example. However, its behaviour will become undefined when you will call other functions than execl after the fork, or modify other variables. Fork() would be safer for programs which are not using execl.

Hope it helps.

Best regards.

I'm rewriting my post... It seems it got lost somehow.

Check the line while(--count). The "While" loop will exit when count is 1, as --count is evaluated to 0, so the child from childpids[0] isn't killed.

You can simply replace the "while" line with:
for(count-=1; count >= 0; count--)

Best regards!

That's not going to be a terrifically useful enterprise without giving the shells the environment they expect. See man forkpty if on linux/*BSD.
Also you could handle child exits asynchronously by using waitpid in a handler for SIGCHLD and avoid your zombie woes.
An example: rmathew: Terminal Sickness

HTH