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

17 篇文章 0 订阅
11 篇文章 0 订阅

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_POSIX199309	1
 
//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 SIGQUIT
	if(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 caught
	quitflag = 0;
 
	//pr_mask("nafter return from sigsuspend: ");
 
	if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
		err_sys("SIG_SETMASK error");
 
	exit(0);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值