Chinaunix首页 | 论坛 | 博客
  • 博客访问: 558867
  • 博文数量: 142
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1452
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-12 16:28
文章分类

全部博文(142)

文章存档

2016年(10)

2015年(60)

2014年(72)

我的朋友

分类: LINUX

2015-04-28 17:48:56

在处理SIGTSTP信号时需要清楚一些细节问题
1)如果SIGTSTP被捕获了,那么就不会执行默认的停止进程的动作。
2)如果在SIGTSTP信号处理函数中,生成一个SIGSTOP信号来解决问题(1),由于SIGSTOP信号是无法被捕获、阻塞和忽略的,因此能确保立即停止进程。但是如果使用wait或waitpid返回的状态来判断是哪个信号导致了子进程停止。显示是SIGSTOP,而不是SIGTSTP

为了解决上面的问题,最好是在SIGTSTP的信号处理函数中再生成一个SIGTSTP信号来停止进程。
步骤如下:
1)在处理函数中将SIGTSTP的处理方式修改为SIG_DEF
2)生成新的SIGTSTP信号,raise(SIGTSTP)
3) 由于在信号SIGTSTP处理函数中,新的SIGTSTP是被阻塞的,所以第2步产生的SIGTSTP信号将被阻塞,所以这里要调用sigpromask函数将SIGTSTP信号从阻塞改为非阻塞。此时第2步生成的信号就可以执行了,并且按照默认的方式挂起进程。
4)在后面的某个时刻,当进程接收到SIGCONT信号恢复时。这时候,SIGTSTP的信号处理函数继续执行。
5)调用sigprocmask信号来阻塞SIGTSTP信号,以便在执行完(6)之后,(7)之前又收到一个SIGTSTP信号,导致提前进入信号处理函数。
6)在信号处理函数返回前,重新注册一个SIGTSTP的信号处理函数来处理下一个SIGTSTP信号。
7)信号处理函数返回,pause()退出,打印Main后,主函数继续停留在pause函数上。

点击(此处)折叠或打开

  1. gwwu@hz-dev2.wgw.com:~/test/signal>more handling_SIGSTP.c
  2. #include <unistd.h>
  3. #include <signal.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <errno.h>

  7. static void tstpHandler(int sig)
  8. {
  9.     sigset_t tstpMask,prevMask;
  10.     int saveErrno;
  11.     struct sigaction sa;

  12.     saveErrno = errno;

  13.     printf("Caught SIGTSTP\n");
  14.     /*1)在处理函数中将SIGTSTP的处理方式修改为SIG_DEF*/
  15.     if(signal(SIGTSTP,SIG_DFL) == SIG_ERR) {     
  16.         printf("signal error\n");
  17.         return;
  18.     }
  19.     printf("before raise\n");
  20.     raise(SIGTSTP);/*2)生成新的SIGTSTP信号,raise(SIGTSTP)*/
  21.     printf("after raise\n");
  22.     sigemptyset(&tstpMask);
  23.     sigaddset(&tstpMask,SIGTSTP);
  24.     printf("wjx.....\n");
  25.     /*/*3) 由于在信号SIGTSTP处理函数中,新的SIGTSTP是被阻塞的,所以第2步产生的SIGTSTP信号将被阻塞,所以这里要调用sigpromask函数将SIGTSTP信号从阻塞改为非阻塞。此时第2步生成的信号就可以执行了,并且按照默认的方式挂起进程。*/
        */
  26.     if(sigprocmask(SIG_UNBLOCK,&tstpMask,&prevMask) == -1) {
  27.         printf("sigprocmask error\n");
  28.         return;
  29.     }
  30.     printf("is SIGTSTP in prevMask: %s\n",sigismember(&prevMask,SIGTSTP)?"yes":"no");
  31.     printf("is SIGINT in prevMask: %s\n",sigismember(&prevMask,SIGINT)?"yes":"no");
  32.     printf("wgw.....\n");

  33. /*4)在后面的某个时刻,当进程接收到SIGCONT信号恢复时。这时候,SIGTSTP的信号处理函数继续执行。*/
  34. /*5)调用sigprocmask信号来阻塞SIGTSTP信号,以便在执行完(6)之后,(7)之前又收到一个SIGTSTP信号,导致提前进入信号处理函数。*/
  35.     if(sigprocmask(SIG_SETMASK,&prevMask,NULL) == -1) {
  36.         printf("sigprocmask error\n");
  37.         return;
  38.     }
  39.     printf("tyx.....\n");
  40. /*6)在信号处理函数返回前,重新注册一个SIGTSTP的信号处理函数来处理下一个SIGTSTP信号。*/
  41.     sigemptyset(&sa.sa_mask);
  42.     sa.sa_flags = SA_RESTART;
  43.     sa.sa_handler = tstpHandler;
  44.     if(sigaction(SIGTSTP,&sa,NULL) == -1) {
  45.         printf("sigaction error\n");
  46.         return;
  47.     }
  48.     
  49.     printf("exiting tstpHandler\n");
  50.     errno = saveErrno;
  51. }

  52. int main(int argc, char *argv[])
  53. {
  54.     struct sigaction sa;

  55.     if(sigaction(SIGTSTP,NULL,&sa) == -1) {
  56.         printf("sigaction error\n");
  57.         return -1;
  58.     }
  59.     if(sa.sa_handler != SIG_IGN) {
  60.         sigemptyset(&sa.sa_mask);
  61.         sa.sa_flags = SA_RESTART;
  62.         sa.sa_handler = tstpHandler;
  63.         if(sigaction(SIGTSTP,&sa,NULL) == -1) {
  64.             printf("sigaction error\n");
  65.             return -1;
  66.         }
  67.     }
  68.     for(;;) {
  69.         pause();
  70.         printf("Main\n");
  71.     }
  72. }
编译运行:

点击(此处)折叠或打开

  1. gwwu@hz-dev2.wgw.com:~/test/signal>gcc -g handling_SIGSTP.c -o handling_SIGSTP
  2. gwwu@hz-dev2.wgw.com:~/test/signal>./handling_SIGSTP
  3. ^ZCaught SIGTSTP                   ----------------------CONTROL+Z
  4. before raise
  5. after raise
  6. wjx.....

  7. [1]+ Stopped ./handling_SIGSTP
  8. gwwu@hz-dev2.wgw.com:~/test/signal>fg
  9. ./handling_SIGSTP
  10. is SIGTSTP in prevMask: yes
  11. is SIGINT in prevMask: no
  12. wgw.....
  13. tyx.....
  14. exiting tstpHandler
  15. Main
  16. ^ZCaught SIGTSTP                   ------------------CONTROL+Z
  17. before raise
  18. after raise
  19. wjx.....

  20. [1]+ Stopped ./handling_SIGSTP
  21. gwwu@hz-dev2.wgw.com:~/test/signal>fg
  22. ./handling_SIGSTP
  23. is SIGTSTP in prevMask: yes
  24. is SIGINT in prevMask: no
  25. wgw.....
  26. tyx.....
  27. exiting tstpHandler
  28. Main
  29. ^C                                 -----------------CONTROL+C
  30. gwwu@hz-dev2.wgw.com:~/test/signal>

阅读(6260) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~