help with signals
Daniel Wu
dwu at nunki.usc.edu
Thu Feb 16 14:31:10 AEST 1989
I have 2 simple questions about signals...which may get a little involved:
1. How do you tell which signal has been sent from within the signal
handler?
Instead of typing
if ( signal(SIGINT,SIG_IGN) != SIG_IGN )
signal(SIGINT,sig_catch1);
if ( signal(SIGQUIT,SIG_IGN) != SIG_IGN )
signal(SIGQUIT,sig_catch2);
if ( signal(SIGHUP,SIG_IGN) != SIG_IGN )
signal(SIGHUP,sig_catch3);
.
.
.
for each signal, defining an individual
handler to process a particular signal, I was thinking of doing
something along these lines:
u_short si_arr[]= {SIGINT,SIGQUIT,SIGHUP,...};
for ( i=0; i < MAX_SIGNO; i++ )
if ( signal(sig_arr[i],sig_catch) != SIG_IGN )
signal(sig_arr[i],sig_catch);
and then in the function sig_catch(),
sig_catch()
{
switch( signal_no ) { /* whatever signal_no is */
case SIGINIT:
/* do something */
break;
case SIGQUIT:
/* do something more */
break;
case SIGHUP:
/* and then some */
default:
}
}
Now, I did RTFM, or at least read signal(3), so I know I can declare
sig_catch(signal_no,code,scp,addr)
int signal_no,code;
struct sigcontext *scp;
char *addr;
{
switch( signal_no ) { /* and indeed, this works! */
/* I get the right signal number */
case SIGINT: /* But now if I try to call signal again*/
signal(SIGINT,SIG_IGN);
break; /* This WON'T work */
/* When I try to compile, I get a improper
function error */
default:
break;
}
As long as I don't try to call signal() agian, my code compiles and runs
just fine, but no matter if I try
signal(SIGINT,sig_catch);
or signal(SIGINT,SIG_IGN);
I can't get the program to compile. Why is this, and what should I do?
Alternately, can I find out what signal was delivered, without declaring
those signal_no,code,scp,addr arguments?
2. How do you reset the signal mask so that wait() will continue to wait for
the child to finish, after a signal interrupts the parent?
Here's what I mean: I do a
ppid = getpid(); /* parent's pid*/
setjmp(reset_pt);
if ( ppid != getpid() ) /* kill all child processes */
exit();
if ( signal(SIGINT,SIG_IGN) != SIG_IGN )
signal(sigarr[i],sig_catch);
.
.
.
if ( !(cpid1=fork()) ) { /* child 1 */
/* do something */
exit(0);
}
if ( !(cpid2=fork()) ) { /* child 2 */
/* do something */
exit(0);
}
wait(&status); /* for a child to finish */
wait(&status); /* for the other child to finish*/
}
sig_catch()
{
longjmp(reset_pt);
}
Now let's say I start the program up, and let it advance to the wait()
calls. (The child processes take a long time to complete). I hit ^C,
and all 3 processes longjmp to the reset_pt. There, the children get
nuked, and only the parent process survives---to fork() off the second
generation of children. However, when the parent hits the wait() statments,
it slips through! I believe wait() is reading the exit signal of the
deceased children, not the newly hatched ones. How can I reset the signal
mask that wait() reads, so that wait() ignores the exit signal of the
first 2 child processes?
Actually, I already do have a fix for this. I do:
while ( (pid=wait(&status)) != cpid1 && pid != -1 )
;
while ( (pid=wait(&status)) != cpid2 && pid != -1 )
;
which works as intended. However, I would like to understand the details
of how signals work, and how I could have resolved the wait() problem
without embedding it in the while loop. I've tried reading sigvec(3)
for futher information, but I couldn't make heads or tails of it.
Can please someone help me?
Daniel
dwu at castor.usc.edu
More information about the Comp.unix.questions
mailing list