Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!cs.utexas.edu!sm.unisys.com!oberon!nunki.usc.edu!dwu From: dwu@nunki.usc.edu (Daniel Wu) Newsgroups: comp.unix.questions Subject: help with signals Summary: 2 simple question sbout signals .... Keywords: signals, wait, signal number Message-ID: <2718@nunki.usc.edu> Date: 16 Feb 89 04:31:10 GMT References: <8517@dasys1.UUCP> <201@carroll1.UUCP> Reply-To: dwu@nunki.usc.edu () Organization: University of Southern California, Los Angeles, CA Lines: 122 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@castor.usc.edu