面对SIGTERM信号处理程序的问题

Facing issue with signal handlers for SIGTERM

本文关键字:问题 程序 信号处理 SIGTERM 面对      更新时间:2023-10-16

我的应用程序已经配置了SIGTERM处理程序。例:

Signal(SIGTERM, &signalHandler);

我想在关闭之前做一些处理,我不能在现有的信号处理程序中做改变。为了进行处理,我放置了一个这样的钩子将处理程序配置为

signal(SIGTERM, &mySignalHandler);

mySignalHandler在完成处理后调用signalHandler,使系统即使在钩子之后也不受影响。

现在,考虑到mySignalHandler将被调用,它在kill $pid一次时工作。但如果我做两次或更多次。signalHandler被调用。据我所知,在这种情况下应该执行SIG_DFL

有谁知道这是为什么吗?

我使用的是" Red Hat Enterprise Linux AS release 4 (Nahant Update 8) "

[EDIT]:面对测试程序的奇怪行为

#undef _GNU_SOURCE
using namespace std;
volatile sig_atomic_t signalHandlerVar_ = false;
volatile sig_atomic_t signalHandlerSecondVar_ = false;
extern "C" void signalHandler(int)
{
    signalHandlerVar_ = true;
}
extern "C" void signalHandlerSecond(int value)
{
    signalHandlerSecondVar_ = true;
}
void* threadFunc(void*)
{
    while(1)
    {
        if(signalHandlerVar_)
        {
            cout<<"signalHandler_ "<<signalHandlerVar_<<endl;
            signalHandlerVar_ = false;
        }
        if(signalHandlerSecondVar_)
        {
            cout<<"signalHandlerSecond_ "<<signalHandlerSecondVar_<<endl;
            signalHandlerSecondVar_ = false;
        }
    }
    return NULL;
}
int main()
{
    ::signal(SIGTERM, &signalHandler);
    ::signal(SIGTERM, &signalHandlerSecond);
    pthread_t thread;
    if(pthread_create(&thread, NULL, &threadFunc, NULL))
    {
        cout<<"pthread create failed"<<endl;
        return 1;
    }
    pthread_join(thread, NULL);
}

这里我面临的问题,每杀死$pid它调用signalHandlerSecond。因为我正在使用#undef _GNU_SOURCE并尝试#undef _BSD_SOURCE。但是它应该重置为SIG_DFL。

谁能建议我哪里做错了?

From signal

signal()的行为在不同的UNIX版本中是不同的在不同的Linux版本中是不同的。避免它使用:使用sigaction(2)代替。参见下面的可移植性。

…如果信号signum被传递给进程,那么其中一个以下情况:

-…
-…-如果处置设置为函数,则首先<strong处置被重置为SIG_DFL,或者信号被阻塞>(参见可移植性如下),然后带参数调用处理程序征。如果处理程序的调用导致信号失效阻塞,然后信号从返回时被解除阻塞处理程序。

在Linux上,这取决于你如何编译你的源代码。由于您的程序没有从任何以下kill终止,我怀疑它使用了后面可移植性

中描述的BSD语义。

Linux上的情况如下:

  * The kernel's signal() system call provides System V semantics.
  * By default, in glibc 2 and later, the signal() wrapper function
     does not invoke the kernel system call.  Instead, it calls
     sigaction(2) using flags that supply BSD semantics.  This default
     behavior is provided as long as the _BSD_SOURCE feature test macro
     is defined.  By default, _BSD_SOURCE is defined; it is also
     implicitly defined if one defines _GNU_SOURCE, and can of course be
     explicitly defined.
    On glibc 2 and later, if the _BSD_SOURCE feature test macro is not
     defined, then signal() provides System V semantics.  (The default
     implicit definition of _BSD_SOURCE is not provided if one invokes
     gcc(1) in one of its standard modes (-std=xxx or -ansi) or defines
     various other feature test macros such as _POSIX_SOURCE,
     _XOPEN_SOURCE, or _SVID_SOURCE; see feature_test_macros(7).)

要强制System V行为,您需要定义_POSIX_SOURCE, _XOPEN_SOURCE_SVID_SOURCE中的一个,例如

gcc -D_SVID_SOURCE -Wall -g -pthread test.c

这似乎在g++中不起作用。当使用

进行编译时
g++ -D_SVID_SOURCE -Wall -g -pthread test.cpp

你仍然得到BSD的行为。添加-v

g++ -v -D_SVID_SOURCE -Wall -g -pthread test.cpp

显示

/usr/lib/gcc/x86_64-linux-gnu/4.6/cc1plus -quiet -v -imultilib。- multitiarch x86_64-linux-gnu -D_GNU_SOURCE -D_REENTRANT -D _SVID_SOURCE test.cpp -quiet -dumpbase test.cpp -mtune=generic -march=x86-64 -auxbase a -g -Wall -version -fstack-protector -o/tmp/cc3mpi02 .s

在使用gcc编译时不存在。您可以使用附加的-U_GNU_SOURCE

来抑制它。
g++ -U_GNU_SOURCE -D_SVID_SOURCE -Wall -g -pthread test.cpp

最后,这给了我们System V行为,这意味着信号处理程序在第一次信号传递后重置为SIG_DFL

在mySignalHandler()函数的末尾,您必须再次调用signal():

第一次(在代码中的任何地方):

signal(SIGTERM, &mySignalHandler);

然后在你的函数中:

void mySignalHandler() {
    //your code here
    signal(SIGTERM, &mySignalHandler);
}
像这样,下次SIGTERM被捕获时,程序将进入mySignalHandler()

希望对你有帮助。