当信号()呼叫重置为sig_dfl时,为什么用户定义的信号处理程序一次又一次地执行?

发布于 2025-01-31 03:53:51 字数 152 浏览 4 评论 0原文

显然,signal()将重置为sig_dfl(默认值),这就是为什么在第一次导致默认行为发生后立即到达同一类型的另一个信号的原因。我的问题是:为什么只有在第二个信号立即发生时才会发生这件事?不管第二个信号是否立即考虑到信号已重置,是否应该发生?我很困惑。请澄清。

Apparently, signal() resets to SIG_DFL (default) which is why another another signal of the same type arriving immediately after the first causes default behaviour to occur. My question is: why does this thing happen only if the second signal occurs immediately? Shouldn't it happen regardless of whether the second signal is immediate or not considering that the signal has been reset? I am mighty confused. Please clarify.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夜光 2025-02-07 03:53:52

函数在C标准中仔细措辞以允许多种行为,主要是因为创建标准时,现有的Signal> Signal()的实现提供了多种行为。
nofollow noreferrer“> sigard> signal> signal> )遵循C标准,但对信号处理程序中的动作的限制更少。

C标准说:

  #include< signal.h>
    void(*信号(int sig,void(*func)(int)))(int);
 

描述

2 信号函数选择随后处理信号号SIG的三种方式之一。如果func的值是sig_dfl,则将发生该信号的默认处理。如果func的值是sig_ign,则将忽略该信号。否则,func应指出该信号发生时要调用的函数。由于信号或(递归)该调用所调用的任何其他功能(标准库中的功能除外), 251)称为信号处理程序。< 251)。 P>

3当信号发生并且func指向一个函数时,实现定义是signal的等效词(sig,sig_dfl);被执行还是实现防止某些实现定义的信号集(至少包括sig)发生,直到当前信号处理完成为止;在sigill的情况下,实现可能会定义不采取任何措施。然后执行(*func);的等效。如果以及何时返回函数,如果SIG的值为sigfpesigillsigsegv,或任何其他实现定义的值对应于计算例外,行为不确定;否则,该程序将在中断时恢复执行。

4如果呼叫中止提高函数的结果,则信号处理程序不得调用rish函数。

5如果信号出现在调用中止提高函数之外,则如果信号处理程序涉及具有静态或静态的任何对象,则该行为是不确定的。线程存储持续时间不是无锁的原子对象,而不是通过将值分配为vistile sig_atomic_t的对象,或者信号处理程序在标准库中调用任何功能,而不是> abort function, the _Exit function, the quick_exit function, or the signal function with the first argument equal to the signal number corresponding发出引起处理程序调用的信号。此外,如果呼叫信号函数会导致sig_err返回,则errno的值不确定。 252)< /sup>

6在程序启动时,相当于

 信号(sig,sig_ign);
 

可以以实现定义的方式选择的某些信号执行;等效于

 信号(sig,sig_dfl);
 

是针对实现定义的所有其他信号执行的。

7在多线程程序中使用此功能会导致不确定的行为。实现的行为应像没有库函数调用信号函数一样。

信号处理程序的经典结构假定系统将信号处理重置为sig_dfl,并小心地将信号处理程序作为处理程序中的第一个操作:

static void handler(int signum)
{
    signal(signum, handler);
    // Other actions
}

但是,有一个很小的时间窗口。信号处理是默认值,因此,如果在此期间(简短)间隔中到达第二个信号,则该程序可能会停止。这就是为什么“在第一次导致默认行为发生后立即到达的同一类型的另一个信号”。并且由于如图所示写处理程序,因此只有一个小间隔在此默认信号处理生效。如果处理程序未重置信号处理,那么第二个信号到达时也没关系。

如果您想控制信号处理,请使用POSIX
sigaction(sigaction()。它具有支持signal()的所有行为的选项,并提供更好的控制。默认情况下,它不会将信号处理重置为sig_dfl;它避免了脆弱性的窗口。

The specification of §7.14.1.1 The signal function in the C standard is carefully worded to allow quite a variety of behaviours, mainly because when the standard was created, existing implementations of signal() provided a wide variety of behaviours.
The POSIX specification for signal() follows the C standard, but places fewer restrictions on the actions in the signal handler.

The C standard says:

     #include <signal.h>
    void (*signal(int sig, void (*func)(int)))(int);

Description

2 The signal function chooses one of three ways in which receipt of the signal number sig is to be subsequently handled. If the value of func is SIG_DFL, default handling for that signal will occur. If the value of func is SIG_IGN, the signal will be ignored. Otherwise, func shall point to a function to be called when that signal occurs. An invocation of such a function because of a signal, or (recursively) of any further functions called by that invocation (other than functions in the standard library),251) is called a signal handler.

3 When a signal occurs and func points to a function, it is implementation-defined whether the equivalent of signal(sig, SIG_DFL); is executed or the implementation prevents some implementation-defined set of signals (at least including sig) from occurring until the current signal handling has completed; in the case of SIGILL, the implementation may alternatively define that no action is taken. Then the equivalent of (*func)(sig); is executed. If and when the function returns, if the value of sig is SIGFPE, SIGILL, SIGSEGV, or any other implementation-defined value corresponding to a computational exception, the behavior is undefined; otherwise the program will resume execution at the point it was interrupted.

4 If the signal occurs as the result of calling the abort or raise function, the signal handler shall not call the raise function.

5 If the signal occurs other than as the result of calling the abort or raise function, the behavior is undefined if the signal handler refers to any object with static or thread storage duration that is not a lock-free atomic object other than by assigning a value to an object declared as volatile sig_atomic_t, or the signal handler calls any function in the standard library other than the abort function, the _Exit function, the quick_exit function, or the signal function with the first argument equal to the signal number corresponding to the signal that caused the invocation of the handler. Furthermore, if such a call to the signal function results in a SIG_ERR return, the value of errno is indeterminate.252)

6 At program startup, the equivalent of

    signal(sig, SIG_IGN);

may be executed for some signals selected in an implementation-defined manner; the equivalent of

    signal(sig, SIG_DFL);

is executed for all other signals defined by the implementation.

7 Use of this function in a multi-threaded program results in undefined behavior. The implementation shall behave as if no library function calls the signal function.

The classic structure for a signal handler assumed that the system would reset the signal handling to SIG_DFL and carefully restored the signal handler as the first action in the handler:

static void handler(int signum)
{
    signal(signum, handler);
    // Other actions
}

However, there is a small window of time during which the signal handling is the default, so if a second signal arrives during that (short) interval, the program may be stopped. That's why "another another signal of the same type arriving immediately after the first causes default behaviour to occur". And because the handler is written as shown, there is only a small interval during which the default signal handling is in effect. If the handler does not reset the signal handling, then it doesn't matter when the second signal arrives.

If you want control over the signal handling, use POSIX
sigaction(). It has options to support all the behaviours of signal() and provides much better control. By default, it does not reset the signal handling to SIG_DFL; it avoids that window of vulnerability.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文