关闭linux systemd时,会向我的应用程序发送多个sigterm信号 我已经设置了一个信号处理程序,如C++中所示,用于在Linux上运行的应用程序:

关闭linux systemd时,会向我的应用程序发送多个sigterm信号 我已经设置了一个信号处理程序,如C++中所示,用于在Linux上运行的应用程序:,c++,linux,systemd,C++,Linux,Systemd,设置信号处理程序以调用静态函数: // Setup the SIGNTERM signal handler for kill/pkill or systemd terminate if (signal(SIGTERM, manager_signal_handler) == SIG_ERR) { ERROR << "Failed to add signal SIGTERM to signal handler with error code: " << std::st

设置信号处理程序以调用静态函数:

// Setup the SIGNTERM signal handler for kill/pkill or systemd terminate
if (signal(SIGTERM, manager_signal_handler) == SIG_ERR)
{
    ERROR << "Failed to add signal SIGTERM to signal handler with error code: " << std::strerror(errno) << ENDL;
}
您可以看到脚本
start\u module.sh
是call-这就是运行我的应用程序的方法:
/my application&

因此,我的问题是: -为什么我得到的不是一个SIGTERM,而是如此接近? -我能做些什么来解决这种行为

我注意到我的应用程序接收到2个甚至3个相隔500毫秒的信号

这不是
systemd
的行为,您可能希望验证您的观察结果

有关详细信息,请参阅:

指定如何终止此单元的进程。对照组一个,过程,混合,无

如果设置为control group(控制组),则此单元的控制组中的所有剩余进程将在单元停止时终止(对于服务:在执行stop命令后,如使用ExecStop=)配置的)。如果设置为process,则仅终止主进程本身。如果设置为混合,则SIGTERM信号(见下文)发送至主进程,而后续SIGKILL信号(见下文)发送至装置控制组的所有剩余进程。如果设置为“无”,则不会终止任何进程。在这种情况下,只有stop命令将在机组停止时执行,否则不会终止任何进程。停止后仍处于活动状态的进程保留在其控制组中,控制组在停止后继续存在,除非其为空

进程将首先通过SIGTERM终止(除非要发送的信号通过KillSignal=)更改)。(可选)这之后紧接着SIGHUP(如果使用sendshighup=)启用)。然后,如果在延迟(通过TIMEOUTOPSEC=选项配置)后,进程仍保留,则终止请求将使用SIGKILL信号重复(除非通过SendSIGKILL=选项禁用)。有关更多信息,请参阅kill(2)

默认为控制组

我注意到我的应用程序接收到2个甚至3个相隔500毫秒的信号

这不是
systemd
的行为,您可能希望验证您的观察结果

有关详细信息,请参阅:

指定如何终止此单元的进程。对照组一个,过程,混合,无

如果设置为control group(控制组),则此单元的控制组中的所有剩余进程将在单元停止时终止(对于服务:在执行stop命令后,如使用ExecStop=)配置的)。如果设置为process,则仅终止主进程本身。如果设置为混合,则SIGTERM信号(见下文)发送至主进程,而后续SIGKILL信号(见下文)发送至装置控制组的所有剩余进程。如果设置为“无”,则不会终止任何进程。在这种情况下,只有stop命令将在机组停止时执行,否则不会终止任何进程。停止后仍处于活动状态的进程保留在其控制组中,控制组在停止后继续存在,除非其为空

进程将首先通过SIGTERM终止(除非要发送的信号通过KillSignal=)更改)。(可选)这之后紧接着SIGHUP(如果使用sendshighup=)启用)。然后,如果在延迟(通过TIMEOUTOPSEC=选项配置)后,进程仍保留,则终止请求将使用SIGKILL信号重复(除非通过SendSIGKILL=选项禁用)。有关更多信息,请参阅kill(2)

默认为控制组


与您的问题没有严格的关系,但是如果您的代码>错误< /C>或<代码>调试< /COD>是C++流或类似的,则不能在信号处理程序中使用它们。只有POSIX系统和C库函数可以在信号处理程序中使用,这不包括任何IO或内存分配的标准C和C++设施。由于在信号处理程序中几乎不可能执行任何有意义的操作,因此您只需发出一个
sig_atomic_t
标志,并让主程序处理关机。为什么不在启动SIGTERM函数之前设置一个标志呢。如果已经设置了标志,则让信号处理程序不执行任何操作。使用互斥锁保护标志,或使用
std::atomic
。systemd发送第一个关闭信号后,您的应用程序需要多长时间才能关闭?Sysemd有一种机制,它只是想确保你的应用程序在断电前关闭。(你可以设置一些设置来防止关机,除非你的应用程序停止,直到你的应用程序停止释放锁,防止关机。systemd发送信号检查没有任何问题,如果你已经开始关机过程,为什么你不能忽略它们?@super在信号处理程序中使用互斥锁是最好的在信号处理程序和“常规”代码之间获得死锁的方法。此外,
std::atomic
不是异步信号安全的,除非您使用的
给定的
std::atomic
是无锁的()==true
(我甚至不确定它是否有保证)“信号!!=线程,不要混淆他们的东西。使用<代码> SiggAsMixICIt并很高兴。你的应用程序是多线程的吗?与你的问题没有严格的关系,但是如果你的代码>错误< /C>或代码>调试< /COD>是C++流或类似的,你不能在你的信号处理器中使用它们。只有POSIX系统和C库FU。NCCTs可以在信号处理程序中使用,它不包含任何用于IO或内存分配的标准C和C++设施。因为在信号处理程序中几乎不可能做任何有意义的事情,所以您要做的就是提高<代码> SiggAsMixICIt标志,让主程序处理关闭。为什么不设置FL?在启动SIGTERM函数之前使用ag。如果已设置标志,则让
static dds_manager_base *p_this_dds_manager_base = nullptr;
static void dds_manager_signal_handler(int signum)
{
    if (p_this_manager_base)
    {
        DEBUG << "static manager_signal_handler calling: p_this_manager_base->signal_handler\n";
        p_this_manager_base->signal_handler(signum);
    }
    else
    {
        ERROR << "manager_signal_handler - manager pointer not set\n";
    }
}
void dds_manager_base::signal_handler(int signum)
{
    DEBUG << "dds_manager_base::signal_handler - received signal: " << signum << ENDL;
    // Termination actions - can take 5-10 seconds...
}
[Unit]
Description=Invoke script to start the corvus application
After = network.target mnt-appdata.mount

[Service]
Type=idle
ExecStart=/mnt/appdata/deploy/services/start_module.sh ${SYS_NUM} ${DDS_NUM}

[Install]
WantedBy=multi-user.target
   KillMode=