解除阻塞信号后代码不执行第二部分
Code does not execute second part after unblocking signals
我正在通过 sigaction
学习 C 中信号的使用。在做我自己的练习时,我试图先阻止信号(SIGINT 和 SIGQUIT),然后再解除阻止。
在我的终端输出中,在信号被阻塞的 for 循环中,如果我试图按下 Ctrl+C 或 Ctrl+,它仍然打印出如下语句,但是在它解除阻塞之后,它是没有打印出第二个 for 循环中的内容。
(block) working ....
(block) working ....
^C(block) working ....
(block) working ....
^\(block) working ....
The work is done, now you can ...
但是,如果我在第一个 for 循环的程序执行期间没有尝试按 Ctrl+C 或 Ctrl+\,那么第二个 for 循环将被打印出来。
(block) working ....
(block) working ....
(block) working ....
(block) working ....
(block) working ....
The work is done, now you can ...
(unblock) working ....
(unblock) working ....
(unblock) working ....
(unblock) working ....
(unblock) working ....
我希望达到的预期结果如下:
(block) working ....
(block) working ....
^C(block) working ....
(block) working ....
^\(block) working ....
The work is done, now you can ...
(unblock) working ....
^C
其中我可以尝试在第一个 for 循环中按多次 Ctrl+C 或 Ctrl+\ 次,然后在进入第二个 for 循环时按任一信号将终止命令。
这是我的代码:
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
int i;
sigset_t sigs, sigs2;
sigemptyset(&sigs);
sigaddset(&sigs, SIGINT);
sigaddset(&sigs, SIGQUIT);
sigprocmask(SIG_SETMASK, &sigs, NULL); // tried with SIGBLOCK, same issues
for (i=0; i<5; ++i)
{
printf("(block) working ....\n");
sleep (1);
}
printf("The work is done, now you can ...\n");
// unblock signals
sigprocmask(SIG_UNBLOCK, &sigs, NULL);
for (int j=0; j<5; ++j)
{
printf("(unblock) working ....\n");
sleep (1);
}
exit(0);
}
提前感谢任何见解。
阻止 信号与忽略 信号不同。如果一个信号被发送到一个进程,而该信号被该进程阻塞,那么它会一直挂起,直到信号被解除阻塞或进程终止。
这正是您所观察到的。您将 SIGINT
和 SIGQUIT
传递给您的进程,同时它们被阻止。一个解封后立即下发,在进入第二个循环前结束进程
未指定(第一个)实际交付的是哪个,但如果其中一个注册了处理程序,那么它不会终止进程,那么两者都可能被交付,甚至是处理程序第一个收到会被第二个收到打断。
但是,多个相同的常规信号不会排队。例如,无论您在该信号被阻止时发送了多少 SIGQUIT
,当该信号被解除阻止时,等待发送的不会超过一个。
添加到 John Bollinger 的回答中,正如他建议的那样,您在这里想要做的是 忽略 信号,而不仅仅是阻止它们。您可以为此使用 sigaction
,将 SIGINT
和 SIGQUIT
的处理程序设置为 SIG_IGN
(忽略),然后将其设置回 SIG_DFL
(默认处理程序) .
这是一个简单的例子:
#define _POSIX_C_SOURCE 1
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
int main(void) {
int i;
struct sigaction sa = { .sa_handler = SIG_IGN };
if (sigaction(SIGINT, &sa, NULL) == -1) {
perror("sigaction(SIGINT, SIG_IGN) failed");
return 1;
}
if (sigaction(SIGQUIT, &sa, NULL) == -1) {
perror("sigaction(SIGQUIT, SIG_IGN) failed");
return 1;
}
for (i = 0; i < 5; ++i) {
printf("(ignore) working ....\n");
sleep(1);
}
printf("The work is done, now you can ...\n");
sa.sa_handler = SIG_DFL;
if (sigaction(SIGINT, &sa, NULL) == -1) {
perror("sigaction(SIGINT, SIG_DFL) failed");
return 1;
}
if (sigaction(SIGQUIT, &sa, NULL) == -1) {
perror("sigaction(SIGQUIT, SIG_DFL) failed");
return 1;
}
for (i = 0; i < 5; ++i) {
printf("(un-ignore) working ....\n");
sleep(1);
}
return 0;
}
上面的例子很简单,但请注意,在一般情况下,您应该使用 sigaction
的第三个参数来保存您正在修改的信号的当前 struct sigaction
,以便您可以稍后将其恢复而不是将其重置为 SIG_DFL
.
我正在通过 sigaction
学习 C 中信号的使用。在做我自己的练习时,我试图先阻止信号(SIGINT 和 SIGQUIT),然后再解除阻止。
在我的终端输出中,在信号被阻塞的 for 循环中,如果我试图按下 Ctrl+C 或 Ctrl+,它仍然打印出如下语句,但是在它解除阻塞之后,它是没有打印出第二个 for 循环中的内容。
(block) working ....
(block) working ....
^C(block) working ....
(block) working ....
^\(block) working ....
The work is done, now you can ...
但是,如果我在第一个 for 循环的程序执行期间没有尝试按 Ctrl+C 或 Ctrl+\,那么第二个 for 循环将被打印出来。
(block) working ....
(block) working ....
(block) working ....
(block) working ....
(block) working ....
The work is done, now you can ...
(unblock) working ....
(unblock) working ....
(unblock) working ....
(unblock) working ....
(unblock) working ....
我希望达到的预期结果如下:
(block) working ....
(block) working ....
^C(block) working ....
(block) working ....
^\(block) working ....
The work is done, now you can ...
(unblock) working ....
^C
其中我可以尝试在第一个 for 循环中按多次 Ctrl+C 或 Ctrl+\ 次,然后在进入第二个 for 循环时按任一信号将终止命令。
这是我的代码:
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
int i;
sigset_t sigs, sigs2;
sigemptyset(&sigs);
sigaddset(&sigs, SIGINT);
sigaddset(&sigs, SIGQUIT);
sigprocmask(SIG_SETMASK, &sigs, NULL); // tried with SIGBLOCK, same issues
for (i=0; i<5; ++i)
{
printf("(block) working ....\n");
sleep (1);
}
printf("The work is done, now you can ...\n");
// unblock signals
sigprocmask(SIG_UNBLOCK, &sigs, NULL);
for (int j=0; j<5; ++j)
{
printf("(unblock) working ....\n");
sleep (1);
}
exit(0);
}
提前感谢任何见解。
阻止 信号与忽略 信号不同。如果一个信号被发送到一个进程,而该信号被该进程阻塞,那么它会一直挂起,直到信号被解除阻塞或进程终止。
这正是您所观察到的。您将 SIGINT
和 SIGQUIT
传递给您的进程,同时它们被阻止。一个解封后立即下发,在进入第二个循环前结束进程
未指定(第一个)实际交付的是哪个,但如果其中一个注册了处理程序,那么它不会终止进程,那么两者都可能被交付,甚至是处理程序第一个收到会被第二个收到打断。
但是,多个相同的常规信号不会排队。例如,无论您在该信号被阻止时发送了多少 SIGQUIT
,当该信号被解除阻止时,等待发送的不会超过一个。
添加到 John Bollinger 的回答中,正如他建议的那样,您在这里想要做的是 忽略 信号,而不仅仅是阻止它们。您可以为此使用 sigaction
,将 SIGINT
和 SIGQUIT
的处理程序设置为 SIG_IGN
(忽略),然后将其设置回 SIG_DFL
(默认处理程序) .
这是一个简单的例子:
#define _POSIX_C_SOURCE 1
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
int main(void) {
int i;
struct sigaction sa = { .sa_handler = SIG_IGN };
if (sigaction(SIGINT, &sa, NULL) == -1) {
perror("sigaction(SIGINT, SIG_IGN) failed");
return 1;
}
if (sigaction(SIGQUIT, &sa, NULL) == -1) {
perror("sigaction(SIGQUIT, SIG_IGN) failed");
return 1;
}
for (i = 0; i < 5; ++i) {
printf("(ignore) working ....\n");
sleep(1);
}
printf("The work is done, now you can ...\n");
sa.sa_handler = SIG_DFL;
if (sigaction(SIGINT, &sa, NULL) == -1) {
perror("sigaction(SIGINT, SIG_DFL) failed");
return 1;
}
if (sigaction(SIGQUIT, &sa, NULL) == -1) {
perror("sigaction(SIGQUIT, SIG_DFL) failed");
return 1;
}
for (i = 0; i < 5; ++i) {
printf("(un-ignore) working ....\n");
sleep(1);
}
return 0;
}
上面的例子很简单,但请注意,在一般情况下,您应该使用 sigaction
的第三个参数来保存您正在修改的信号的当前 struct sigaction
,以便您可以稍后将其恢复而不是将其重置为 SIG_DFL
.