1 //定义USE_SIGWAIT时
2 --Thread b7f316c0 Received Signal  3(Quit)!   //Ctrl+
3 sigwait returns 0(Success), signo = 2         //Ctrl+C
4 //未定义USE_SIGWAIT时
5 --Thread b7fb66c0 Received Signal  3(Quit)!   //Ctrl+
6 sigwaitinfo returns -1(Interrupted system call), signo = 0

  对比可见,sigwaitinfo()可被等待信号集以外的信号中断,而sigwait()不会被中断。
  3.2 示例2
  本示例测试多线程中,sigwait()和sigwaitinfo()函数对信号的同步等待。

 

1 void *SigMgrThread(void *pvArg)
2 {
3     pthread_detach(pthread_self());
4
5     //捕获SIGQUIT信号,以免程序收到该信号后退出
6     signal(SIGQUIT, sighandler);
7
8     //使用创建线程时的pvArg传递信号屏蔽字
9     int dwRet;
10     while(1)
11     {
12 #ifdef USE_SIGWAIT
13         int dwSigNo;
14         dwRet = sigwait((sigset_t*)pvArg, &dwSigNo);
15         if(dwRet == 0)
16             SigHandler(dwSigNo);
17         else
18             printf("sigwait() failed, errno: %d(%s)! ", dwRet, strerror(dwRet));
19 #else
20         siginfo_t tSigInfo;
21         dwRet = sigwaitinfo((sigset_t*)pvArg, &tSigInfo);
22         if(dwRet != -1) //dwRet与tSigInfo.si_signo值相同
23             SigHandler(tSigInfo.si_signo);
24         else
25         {
26             if(errno == EINTR) //被其他信号中断
27                 printf("sigwaitinfo() was interrupted by a signal handler! ");
28             else
29                 printf("sigwaitinfo() failed, errno: %d(%s)! ", errno, strerror(errno));
30         }
31     }
32 #endif
33 }
34
35 void *WorkerThread(void *pvArg)
36 {
37     pthread_t tThrdId = pthread_self();
38     pthread_detach(tThrdId);
39
40     printf("Thread %x starts to work! ", (unsigned int)tThrdId);
41     //working...
42     int dwVal = 1;
43     while(1)
44         dwVal += 5;
45 }
46
47 int main(void)
48 {
49     printf("Main thread %x is running! ", (unsigned int)pthread_self());
50
51     //屏蔽SIGUSR1等信号,新创建的线程将继承该屏蔽字
52     sigset_t tBlockSigs;
53     sigemptyset(&tBlockSigs);
54     sigaddset(&tBlockSigs, SIGRTMIN);
55     sigaddset(&tBlockSigs, SIGRTMIN+2);
56     sigaddset(&tBlockSigs, SIGRTMAX);
57     sigaddset(&tBlockSigs, SIGUSR1);
58     sigaddset(&tBlockSigs, SIGUSR2);
59     sigaddset(&tBlockSigs, SIGINT);
60
61     sigaddset(&tBlockSigs, SIGSEGV); //试图阻塞SIGSEGV信号
62
63     //设置线程信号屏蔽字
64     pthread_sigmask(SIG_BLOCK, &tBlockSigs, NULL);
65
66     signal(SIGINT, sighandler); //试图捕捉SIGINT信号
67
68     //创建一个管理线程,该线程负责信号的同步处理
69     pthread_t tMgrThrdId;
70     pthread_create(&tMgrThrdId, NULL, SigMgrThread, &tBlockSigs);
71     printf("Create a signal manager thread %x! ", (unsigned int)tMgrThrdId);
72     //创建另一个管理线程,该线程试图与tMgrThrdId对应的管理线程竞争信号
73     pthread_t tMgrThrdId2;
74     pthread_create(&tMgrThrdId2, NULL, SigMgrThread, &tBlockSigs);
75     printf("Create another signal manager thread %x! ", (unsigned int)tMgrThrdId2);
76
77     //创建一个工作线程,该线程继承主线程(创建者)的信号屏蔽字
78     pthread_t WkrThrdId;
79     pthread_create(&WkrThrdId, NULL, WorkerThread, NULL);
80     printf("Create a worker thread %x! ", (unsigned int)WkrThrdId);
81
82     pid_t tPid = getpid();
83     //向进程自身发送信号,这些信号将由tMgrThrdId线程统一处理
84     //信号发送时若tMgrThrdId尚未启动,则这些信号将一直阻塞
85     printf("Send signals... ");
86     kill(tPid, SIGRTMAX);
87     kill(tPid, SIGRTMAX);
88     kill(tPid, SIGRTMIN+2);
89     kill(tPid, SIGRTMIN);
90     kill(tPid, SIGRTMIN+2);
91     kill(tPid, SIGRTMIN);
92     kill(tPid, SIGUSR2);
93     kill(tPid, SIGUSR2);
94     kill(tPid, SIGUSR1);
95     kill(tPid, SIGUSR1);
96
97     int dwRet = sleep(1000);
98     printf("%d seconds left to sleep! ", dwRet);
99
100     ThreadKill(WkrThrdId, 0); //不建议向已经分离的线程发送信号
101
102     sleep(1000);
103     int *p=NULL; *p=0; //触发段错误(SIGSEGV)
104
105     return 0;
106 }