APUE2e之signal function, signal handler, and signal mask on Ubuntu

来源:互联网 发布:知天下图吧 编辑:程序博客网 时间:2024/05/18 17:55

When I was trying to run the program in Figure 10.23 in APUE2e using Ubuntu command line, after I typed Ctrl+C twice, the program terminated, which meant that the second SIGINT signal generated was not caught by the signal handler (sig_int) installed previously. This was different from the book’s running results. So I added a checking line in sig_int to check whether the signal handler of SIGINT was changed after sig_int was called. The running result revealed that the signal handler of SIGINT has been set to default SIG_DFL, which meant the handler installed previously was called only one time. To make the program catch the SIGINT signal continuously, an additional call to signal had to be called in sig_intsignal(SIGINT, sig_int). I checked the Ubuntu manual for signal function and it said that:

If the disposition is set to a function, then first either the disposition is reset to SIG_DFL, or the signal is blocked (see Portability below), and then handler is called with argument signum. If invocation of the handler caused the signal to be blocked, then the signal is unblocked upon return from the handler.


This is the unreliable signal discussed in section 10.4, where one sentence saying that “One problem with these early versions is that the action for a signal was reset to its default each time the signal occurred”.

However, if sigaction is used instead of signal function, the signal handler installed won’t be changed until explicitly changing it by calling sigaction again.

Another issue. The book on page 330 said that “When a signal is caught, the signal-catching function is entered with the current signal automatically being added to the signal mask of the process“. This is not always the case. I tried the program in Figure 10.20, it worked as the result on page 332 showed. But for the program in Figure 10.22 on page 335, the running result for line “in sig_int:” didn’t include SIGINT. When I tried printing out the signal being masked in the following program in the signal handler, it gave me nothing, which meant that the signal being caught is not added to the mask of the process. I don’t know why.


/**    * apue-chap10: fig10-24.c * * Description: TODO * * Created On: Dec 16, 2011  * * @author: Huang Zhu * * @email: zhuhuang.zp@gmail.com */  #include <apueerr.h># define __USE_POSIX1993091 //sig_atomic_t:/* An integral type that can be modified atomically, without the   possibility of a signal arriving in the middle of the operation.  */ volatile sig_atomic_t quitflag;  //set nonzero by signal handler void pr_mask(const char *str){sigset_t sigset;int errno_save; errno_save = errno;if(sigprocmask(0, NULL, &sigset) < 0)err_sys("sigprocmask error"); printf("%s", str); if(sigismember(&sigset, SIGINT)) printf("SIGINT ");if(sigismember(&sigset, SIGQUIT)) printf("SIGQUIT ");if(sigismember(&sigset, SIGUSR1)) printf("SIGUSR1 ");if(sigismember(&sigset, SIGUSR2)) printf("SIGUSR2 ");if(sigismember(&sigset, SIGALRM)) printf("SIGALRM "); //other signals printf("n");errno = errno_save;} static void sig_alrm(int signo){//pr_mask("nint sig_alrm: "); if(signal(SIGALRM, sig_alrm) == SIG_DFL){printf("nSIGALRM handler reset to default after one call to sig_alrmn");printf("Reset it to sig_alrmn");}} static void sig_int(signo){//pr_mask("nint sig_int: "); if(signo == SIGINT)printf("ninterruptn");else if(signo == SIGQUIT)quitflag = 1; alarm(3); if(signal(SIGINT, sig_int) == SIG_DFL){printf("nSIGINT handler reset to default after one call to sig_intn");printf("Reset it to sig_intn");}} int main(void){sigset_t newmask, oldmask, zeromask; struct sigaction act, oact;act.sa_handler = sig_int;sigemptyset(&act.sa_mask);act.sa_flags = 0; //if(sigaction(SIGINT, &act, &oact) < 0) //if use sigaction, don't need to add signal in sig_int//err_sys("sigaction error");if(signal(SIGINT, sig_int) == SIG_ERR)err_sys("signal(SIGINT) error");if(signal(SIGQUIT, sig_int) == SIG_ERR)err_sys("signal(SIGQUIT) error");if(signal(SIGALRM, sig_alrm) == SIG_ERR)err_sys("can't catch SIGALRM"); sigemptyset(&zeromask);sigemptyset(&newmask);sigaddset(&newmask, SIGQUIT); //pr_mask("nbefore sigprocmask(SIG_BLOCK): "); //block SIGQUITif(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)err_sys("SIG_BLOCK error"); //pr_mask("nafter sigprocmask(SIG_BLOCK): "); while(quitflag == 0)sigsuspend(&zeromask);  //using zeromask here, not newmask //SIGQUIT has been caughtquitflag = 0; //pr_mask("nafter return from sigsuspend: "); if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)err_sys("SIG_SETMASK error"); exit(0);}


原创粉丝点击