生成.sig linux,在Linux上显式调用SIG_DFL / SIG_IGN处理程序

提问

我已阻止,然后通过以下代码等待信号:

sigset_t set;

sigfillset(&set); // all signals

sigprocmask(SIG_SETMASK, &set, NULL); // block all signals

siginfo_t info;

int signum = sigwaitinfo(&set, &info); // wait for next signal

struct sigaction act;

sigaction(signum, NULL, &act); // get the current handler for the signal

act.sa_handler(signum); // invoke it

最后一行生成分段错误,因为处理程序设置为SIG_DFL(定义为0).如果设置为SIG_DFL或SIG_IGN,如何手动调用默认处理程序?另请注意,SIG_IGN定义为1.

最佳答案

正如您所发现的那样,您本身无法调用SIG_DFL和SIG_IGN.但是,您可以或多或少地模仿他们的行为.

简而言之,模仿正常的信号配置将是:

>用户定义的sa_handler非常容易

>对于SIG_IGN来说已经足够了,需要注意的是在CHLD的情况下你需要waitpid()

>直截了当但令人不愉快的SIG_DFL,重新提升让内核发挥其魔力.

这样做你想要的吗?

#include

#include

/* Manually dispose of a signal, mimicking the behavior of current

* signal dispositions as best we can. We won't cause EINTR, for

* instance.

*

* FIXME: save and restore errno around the SIG_DFL logic and

* SIG_IGN/CHLD logic.

*/

void dispatch_signal(const int signo) {

int stop = 0;

sigset_t oset;

struct sigaction curact;

sigaction(signo, NULL, &curact);

/* SIG_IGN => noop or soak up child term/stop signals (for CHLD) */

if (SIG_IGN == curact.sa_handler) {

if (SIGCHLD == signo) {

int status;

while (waitpid(-1, &status, WNOHANG|WUNTRACED) > 0) {;}

}

return;

}

/* user defined => invoke it */

if (SIG_DFL != curact.sa_handler) {

curact.sa_handler(signo);

return;

}

/* SIG_DFL => let kernel handle it (mostly).

*

* We handle noop signals ourselves -- "Ign" and "Cont", which we

* can never intercept while stopped.

*/

if (SIGURG == signo || SIGWINCH == signo || SIGCONT == signo) return;

/* Unblock CONT if this is a "Stop" signal, so that we may later be

* woken up.

*/

stop = (SIGTSTP == signo || SIGTTIN == signo || SIGTTOU == signo);

if (stop) {

sigset_t sig_cont;

sigemptyset(&sig_cont);

sigaddset(&sig_cont, SIGCONT);

sigprocmask(SIG_UNBLOCK, &sig_cont, &oset);

}

/* Re-raise, letting the kernel do the work:

* - Set exit codes and corefiles for "Term" and "Core"

* - Halt us and signal WUNTRACED'ing parents for "Stop"

* - Do the right thing if we forgot to handle any special

* signals or signals yet to be introduced

*/

kill(getpid(), signo);

/* Re-block CONT, if needed */

if (stop) sigprocmask(SIG_SETMASK, &oset, NULL);

}

UPDATE

(回应OP的优秀问题)

1: does this slot in after the sigwaitinfo?

是.就像是:

... block signals ...

signo = sigwaitinfo(&set, &info);

dispatch_signal(signo);

2: Why not raise those signals handled by SIG_IGN, they’ll be ignored anyway

用户空间中的noop比三个系统调用(重新提升,取消屏蔽,重新屏蔽)更有效.此外,CHLD在SIG_IGNored时具有特殊的语义.

3: Why treat SIGCHLD specially?

但是,因为“natural” CHLD signals carry information about

the terminated process(至少是PID,状态和真实的UID)我改变了它.

用户生成的CHLD信号不具有相同的语义,在我的测试中,

IGNoring它们不会导致2.6自动恢复其SIGCHLD的排队僵尸

被“错过了”.所以,我自己做.

4: Why are “stop” related signals unblocking CONT. Will not invoking the default handler for CONT unstop the process?

如果我们停止(不执行)并且CONT被阻止,我们将永远不会收到

发信号唤醒我们!

5: Why not call raise instead of the kill line you’ve given?

个人喜好; raise()也会起作用.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值