内容: 记录一个解除信号阻塞时一个有趣的问题
测试代码:设置信号阻塞之后,看收到此信号后未决状态集的状态,然后再解除阻塞看会发生什么?
#include <iostream>
#include <signal.h>
#include <cstdlib>
#include <unistd.h>
using namespace std;
void handler(int num)
{
if(num == SIGINT){
cout << "recv the SIGINT" << endl;
}
else if (num == SIGQUIT){
sigset_t unblock_set;
sigemptyset(&unblock_set);
sigaddset(&unblock_set, SIGINT);
sigprocmask(SIG_UNBLOCK, &unblock_set, NULL);
}
}
void print_pending(sigset_t * pset)
{
int i = 0;
cout << "未决状态字(64位):";
for (i = 1; i <= 64; ++i){
if(sigismember(pset, i))
cout << 1;
else
cout << 0;
if(i % 8 == 0){
cout << " ";
}
}
cout << endl;
}
int main()
{
sigset_t block_set;
sigset_t print_set;
sigemptyset(&block_set);
sigaddset(&block_set, SIGINT);
sigprocmask(SIG_BLOCK, &block_set, NULL);
signal(SIGINT, handler);
signal(SIGQUIT, handler);
while(1){
sigpending(&print_set);
print_pending(&print_set);
sleep(1);
}
return 0;
}
运行结果分析:
1.刚开始,设置了阻塞,但是没有发送信号,所以未决集合为空
2.ctrl+c发送信号后,未决信号集显示有信号未决
3.ctrl+\解除信号集后看到阻塞的信号送达,信号处理函数调用
这一切貌似很正常对吧,但是你再发送一次ctrl+c看看发生了什么?
你会发现又阻塞了,这是为什么?刚不是解除阻塞了吗?而且也没有再设置阻塞呀?
原因:如果在信号处理函数中对某个信号进行解除阻塞时,则只是将pending位清0,让此信号递达一次,但不会将block位清0,即再次产生此信号时还是会被阻塞,处于未决状态。如果你在main函数解除一下阻塞发现是真的把block位给清0了
测试代码如下:我们设置10秒后main函数while中会解除阻塞
#include <iostream>
#include <signal.h>
#include <cstdlib>
#include <unistd.h>
using namespace std;
void handler(int num)
{
if(num == SIGINT){
cout << "recv the SIGINT" << endl;
}
else if (num == SIGQUIT){
sigset_t unblock_set;
sigemptyset(&unblock_set);
sigaddset(&unblock_set, SIGINT);
sigprocmask(SIG_UNBLOCK, &unblock_set, NULL);
}
}
void print_pending(sigset_t * pset)
{
int i = 0;
cout << "未决状态字(64位):";
for (i = 1; i <= 64; ++i){
if(sigismember(pset, i))
cout << 1;
else
cout << 0;
if(i % 8 == 0){
cout << " ";
}
}
cout << endl;
}
int main()
{
int i = 0;
sigset_t block_set;
sigset_t print_set;
sigemptyset(&block_set);
sigaddset(&block_set, SIGINT);
sigprocmask(SIG_BLOCK, &block_set, NULL);
signal(SIGINT, handler);
signal(SIGQUIT, handler);
while(1){
i++;
sigpending(&print_set);
print_pending(&print_set);
sleep(1);
if (i >19 && i<21)
{
sigset_t unblock_set;
sigemptyset(&unblock_set);
sigaddset(&unblock_set, SIGINT);
sigprocmask(SIG_UNBLOCK, &unblock_set, NULL);
}
}
return 0;
}
运行结果:观察到10s后解除阻塞,再收到ctrl+c已经不再阻塞,未决信号集一直为0
总结:即如果在信号处理函数中对某个信号进行解除阻塞时,则只是将pending位清0,让此信号递达一次,但不会将block位清0,即再次产生此信号时还是会被阻塞,处于未决状态。