从 cin 读取的进程上的 HUP 信号

Posted

技术标签:

【中文标题】从 cin 读取的进程上的 HUP 信号【英文标题】:HUP Signal on a process reading from cin 【发布时间】:2020-05-05 10:45:08 【问题描述】:

我有一个可执行文件,它总是在循环中从 std::cin 读取输入,我也有一个 SIGHUP 处理程序。

#include <iostream>
#include <signal.h>

void hupHandler(int)

    std::cout << "Handled sighup" << std::endl;


int main(int, char*[])

    struct sigaction sigHupHandler;
    sigHupHandler.sa_handler = hupHandler;
    sigemptyset(&sigHupHandler.sa_mask);
    sigHupHandler.sa_flags = 0;
    sigaction(SIGHUP, &sigHupHandler, nullptr);

    while(true)
    
        std::string input;
        std::getline(std::cin, input);
        std::cout << "Read input \"" << input << "\"" << std::endl;
    

    std::cout << "Child Exiting" << std::endl;

    return 0;

当我在终端上启动可执行文件并使用 kill -HUP 发送 SIGHUP 时,我看到它处理了 SIGHUP 但之后我看到了以下内容的无限打印 -

$ ./child 
Handled sighup
Read input ""
Read input ""
Read input ""
Read input ""
Read input ""
Read input ""
Read input ""
Read input ""
Read input ""
Read input ""
Read input ""
Read input ""
Read input ""
Read input ""
Read input ""
Read input ""
Read input ""

有人可以向我解释一下这种行为吗?我实际上需要有一个在后台运行的进程并不断监听它的标准输入(另一个进程提供给它的标准输入)。如果它已被 SIGHUP,我还需要它来重新加载配置。我注意到,只要我 HUP 它就会进入读取空行的循环。所以我写了这个实用程序来测试,我看到了同样的行为。任何帮助将不胜感激,谢谢!

【问题讨论】:

也许考虑使用signalfd 代替SIGHUP。然后,您可以使用适当的select/poll/epollSTDIN_FILENO 一起监视该文件描述符。 【参考方案1】:

你不能在信号处理程序中做任何你想做的事情。信号处理程序可以随时中断程序。包括当它在 C++ 库函数或类中做某事的时候,并且 C++ 库函数、模板等都不是可重入的,就像那样。您几乎不能在信号处理程序中使用任何 C++ 库代码,当然也不能使用 std::cout。你甚至不能做任何事情newdelete。这是第一个问题。

您也不能使用 C 库函数。它们也不是可重入的。您在信号处理程序中唯一可以做的就是使用操作系统调用,例如打开/关闭/读取/写入等。 (基本上是手册页的第 2 节),直接。

因此,显示的代码是未定义的行为,您不能期望它以任何方式、形状、物质或形式可靠地工作,只要您的信号处理程序执行它的工作。

此外,当进程本身处于系统调用的中间时(取决于特定的系统调用),捕获的信号会导致特定的 errnoEINTR 失败。这在您的 signal(7) 手册页中有描述,您应该阅读该手册。 C++ 库很可能会将其解释为从文件读取的任何其他错误,并将流设置为失败状态,这看起来就像您所看到的行为。你也必须自己处理。

【讨论】:

感谢您的信息。是的 - 中断后,如果设置了 fail() 或 eof() 标志,我必须清除 std::cin,它现在可以工作了!

以上是关于从 cin 读取的进程上的 HUP 信号的主要内容,如果未能解决你的问题,请参考以下文章

disown 忽略hup信号,使后台运行

hup 信号

kill -HUP pid

linux12shell编程 -->信号控制

kill -HUP pid

kill -HUP pid 更改配置后不重新启动服务,动态更新配置文件