funny SIGCHLD behavior
- From: sam.n.seaborn@xxxxxxxxx
- Date: Tue, 9 Sep 2008 11:46:02 -0700 (PDT)
Hello all,
I'm trying to implement a simple shell (as below) and am facing some
funny behavior. Hoping one of you has some ideas.
The behavior I see is:
bash $ ./sh
$ /bin/sleep 4 &
job 97705 (/bin/sleep) started in background
back to loop
$ ls
sh.c jobs.c sh.h Makefile
back to loop
$ chewba
job: pid 97705 finished
done, exit
bash $ chewba ## I typed this into my program!
bash $
My questions:
1. I think I have set up the signal handlers correctly i.e. every
SIGCHLD must get sent to the handler. Also, the handler is supposed to
return to the main prog, right? Instead, the main prog just exits!
2. I've tried doing the same thing below by writing a small program
like so:
/* set up signal handler exactly like below */
while (i++ < 10)
{
if ((pid = fork()) == 0) { execv(cpu_stress[0], cpu_stress); }
}
do {
printf(" enter a number\n"); scanf("%d", i);
} while (i != -1);
exit(0);
3. In the program above, cpu_stress refers to a non-interactive
program that does some computation (1million sin(x) calculations) and
simply exits. The handler handles all those children exiting. In the
meantime, I still get to enter numbers to the do { } loop until I want
to exit.
4. So then, why does my shell exit involuntarily while the same code
in the test program seems to behave ok? I mean, my shell is in the
middle of reading my next command (chewbacca) and it just, well,
quits.
I've spent about half a day reading through manuals and the web, but
this is truly confounding me! Appreciate any suggestions from ye gurus
out there.
-SNS
---------------
main()
{
/* basic bookeeping */
init_jobs();
/* init_jobs is declared and defined in another file jobs.c
* it does the following:
*
* sigemptyset( & (handler_action.sa_mask) );
* sigaddset( & (handler_action.sa_mask), SIGINT );
* sigaddset( & (handler_action.sa_mask), SIGQUIT );
* handler_action.sa_flags = SA_SIGINFO;
* handler_action.sa_sigaction = handle_reap;
*
* sigaction (SIGCHLD, &handler_action, (struct sigaction *)0);
*
* and handle_reap(), also in jobs.c, uses this loop
*
* while ( (pid = waitpid(-1, &status, WNOHANG)) > 0 )
* {
* if (pid != 0) printf("\n job %d finished\n", pid);
* }
*/
/* readcmd() uses getc(stdin) repeatedly to build up
* cmdbuf as required by execv() functions
*/
char **cmdbuf;
while ((cmdbuf = readcmd()) != EOF)
exec_cmd(cmdbuf);
printf(" done, exit\n");
exit(0);
}
exec_cmd(char **cmdbuf)
{
/* more housekeeping */
if (is_background_job(cmdbuf))
{
if ( (pid = fork()) == 0)
{ execv(cmdbuf[0], cmdbuf); }
else
{ printf(" job %d (%s) started in background\n", pid, cmdbuf[0]); }
}
else /* assume foreground job */
{
if ( (pid = fork()) == 0)
{ execv(cmdbuf[0], cmdbuf); }
else
{ status = 0; w = wait(&status); }
}
printf("back to loop\n");
return;
}
.
- Follow-Ups:
- Re: funny SIGCHLD behavior
- From: viza
- Re: funny SIGCHLD behavior
- Prev by Date: Re: POSIX's send() on non blocking sockets may partially write?
- Next by Date: Re: I don't understand how the child gets placed in the background
- Previous by thread: I don't understand how the child gets placed in the background
- Next by thread: Re: funny SIGCHLD behavior
- Index(es):
Relevant Pages
|