gpt4 book ai didi

c - sigsetjmp() 和 siglongjmp() : The mask signals are not the same on call to sigsetjmp() and return of siglongjmp()

转载 作者:太空宇宙 更新时间:2023-11-03 23:23:11 25 4
gpt4 key购买 nike

根据手册页:

如果您想以可移植的方式保存和恢复信号掩码,请使用 sigsetjmp()siglongjmp()

sigsetjmp() 类似于setjmp()。当且仅当 savesigs 为非零时,进程的当前信号掩码保存在 env 中并将 如果稍后使用此 env 执行 siglongjmp(3),则恢复。

但是在我的程序中上面的陈述不正确或者我遗漏了什么?当 sigsetjmp 被调用时和当 siglongjmp 返回时掩码信号是不一样的。我在整个代码中都写了评论来详细解释这个问题。我的问题是为什么会这样?

提前致谢

#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

sigjmp_buf env;

static void handler(int signo)
{
printf("\ncatched signal: %d\n", signo);
siglongjmp(env,1);
}

int main(void)
{
struct sigaction action;

action.sa_flags = 0;
action.sa_handler = handler;

if( (sigemptyset(&action.sa_mask) == -1) || (sigaction(SIGINT, &action, NULL) == -1) )
{
perror("Failed to set!");
return 1;
}

printf("this is process %ld\n", (long)getpid());

//here I add the SIGSEGV to mask signals i.e action.sa_mask
sigaddset(&action.sa_mask,SIGSEGV);
sigaction(0, &action, NULL);
sigaction(0, 0 , &action);
printf("\nsigismember(&action.sa_mask, SIGSEGV)? 1 : 0 -> %d\n", sigismember(&action.sa_mask, SIGSEGV)? 1 : 0);
//and yes it is member of mask signals i.e action.sa_mask

if(sigsetjmp(env,1)) //"first time" it saves state of registers and mask signals and as return value is 0 it does not go inside
{
//when it comes here due to siglongjmp() the signal masks must be restored
printf("Return to main loop due to ^c\n");

//so again SIGSEGV must be member of mask signal i.e action.sa_mask as it was removed only after sigsetjmp was called
sigaction(0 , 0 , &action);
printf("sigismember(&action.sa_mask, SIGSEGV)? 1 : 0 -> %d\n", sigismember(&action.sa_mask, SIGSEGV)? 1 : 0);
//but it shows it is NOT member of mask signal i.e action.sa_mask. why???
}

//here I delete the SIGSEGV from mask signals i.e action.sa_mask
sigdelset(&action.sa_mask,SIGSEGV);
sigaction(0, &action, NULL);
sigaction(0, 0 , &action);

printf("\nsigismember(&action.sa_mask, SIGSEGV)? 1 : 0 -> %d\n\n", sigismember(&action.sa_mask, SIGSEGV)? 1 : 0);

for(;;);
}

输出:

    majid@K53SC:~/Desktop$ ./a.out
this is process 6335

sigismember(&action.sa_mask, SIGSEGV)? 1 : 0 -> 1

sigismember(&action.sa_mask, SIGSEGV)? 1 : 0 -> 0

^C
catched signal: 2
Return to main loop due to ^c
sigismember(&action.sa_mask, SIGSEGV)? 1 : 0 -> 0

sigismember(&action.sa_mask, SIGSEGV)? 1 : 0 -> 0

^C
catched signal: 2
Return to main loop due to ^c
sigismember(&action.sa_mask, SIGSEGV)? 1 : 0 -> 0
sigismember(&action.sa_mask, SIGSEGV)? 1 : 0 -> 0

编辑

我发布了一个正确的程序来展示sigsetjmp()siglongjmp()的概念以及信号如何mask 被恢复,它是根据 Mr. Jean-Baptiste Yunès 在答案部分给出的答案输出的,因此可能对其他人有帮助:

#include <setjmp.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

sigjmp_buf env;

void handler(int signo)
{
printf("\nCaught signal: %s", strsignal(signo));
siglongjmp(env,1);
}

int main(void)
{
sigset_t pmask;

if( (sigemptyset(&pmask) == -1) || (signal(SIGINT, handler)== SIG_ERR) )
{
perror("Failed to set!");
return 1;
}

sigprocmask(SIG_SETMASK, &pmask, NULL); //set the process signal mask to pmask

sigprocmask(0, NULL, &pmask); //check the process mask in pmask
printf("\nsigismember(&pmask, SIGSEGV)? 1 : 0 -> %d", sigismember(&pmask, SIGSEGV)? 1 : 0);


if(sigsetjmp(env,1)!=0) //save process environment context and signal mask
printf("\nReturn from signal handler to main loop\nProcess signal mask is restored by siglongjmp()!\n");

else
printf("\nProcess signal mask is saved by sigsetjmp()!\n");

printf("\n**** This is process %ld ****", (long)getpid());
sigprocmask(0, NULL, &pmask); //ckeck the process mask to mask
printf("\nsigismember(&pmask, SIGSEGV)? 1 : 0 -> %d", sigismember(&pmask, SIGSEGV)? 1 : 0);

printf("\nChanging process signal mask");
sigaddset(&pmask,SIGSEGV);
sigprocmask(SIG_SETMASK, &pmask, NULL);

sigprocmask(0, NULL, &pmask); //ckeck the process mask to mask
printf("\nsigismember(&pmask, SIGSEGV)? 1 : 0 -> %d\n\n", sigismember(&pmask, SIGSEGV)? 1 : 0);

pause();
}

输出

majid@K53SC:~/Desktop$ gcc P45.c
majid@K53SC:~/Desktop$ ./a.out

sigismember(&pmask, SIGSEGV)? 1 : 0 -> 0
Process signal mask is saved by sigsetjmp()!

**** This is process 23099 ****
sigismember(&pmask, SIGSEGV)? 1 : 0 -> 0
Changing process signal mask
sigismember(&pmask, SIGSEGV)? 1 : 0 -> 1

^C
Caught signal: Interrupt
Return from signal handler to main loop
Process signal mask is restored by siglongjmp()!

**** This is process 23099 ****
sigismember(&pmask, SIGSEGV)? 1 : 0 -> 0
Changing process signal mask
sigismember(&pmask, SIGSEGV)? 1 : 0 -> 1

最佳答案

这是因为您没有打印正确的信息。您只需打印 action.sa_mask 这是正确的行为,因为您通过从中删除 SIGSEGV 来更改它。

你想要的是通过sigprocmask打印可用的进程掩码,这是sigsetjmp/siglongjmp保存的值。

-----编辑----------------------------

来自 sigprocmask 手册(GNU):

The collection of signals that are currently blocked is called the signal mask. Each process has its own signal mask. When you create a new process (see Creating a Process), it inherits its parent’s mask. You can block or unblock signals with total flexibility by modifying the signal mask.

此掩码是通过 siglongjmp 调用恢复的掩码。

来自 sigaction 手册 (GNU) 关于 sa_mask 字段:

This specifies a set of signals to be blocked while the handler runs. Blocking is explained in Blocking for Handler. Note that the signal that was delivered is automatically blocked by default before its handler is started; this is true regardless of the value in sa_mask. If you want that signal not to be blocked within its handler, you must write code in the handler to unblock it.

因此,使用 sigaction 不会修改进程掩码,但会修改它当处理程序将在某个信号传递时执行

关于c - sigsetjmp() 和 siglongjmp() : The mask signals are not the same on call to sigsetjmp() and return of siglongjmp(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33975433/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com