【发布时间】:2021-02-22 13:03:15
【问题描述】:
当一个进程的输出通过管道传输到另一个进程时,我正在尝试实现一个进程的正常关闭。我正在通过管道输出来测试下面的代码:./a.out | less 并在出现提示时按q。我看到的是信号处理程序的调用,而不是sigwait() 的预期完成(这里添加它只是为了显示正在发生的事情)。
#include <csignal>
#include <chrono>
#include <iostream>
#include <thread>
#include <signal.h>
int handlerSig {0};
void signalHandler(int s)
{
handlerSig = s;
std::cerr << "handlerSig: " << handlerSig << std::endl;
}
int main()
{
for (int i = 1; i < 32; ++i)
{
std::signal(i, signalHandler);
}
bool run {true};
std::thread thread {[&]
{
while (run)
{
std::cout << "ping" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds {500});
}
}};
sigset_t waitSet;
sigemptyset(&waitSet);
sigaddset(&waitSet, SIGINT);
sigaddset(&waitSet, SIGPIPE);
sigaddset(&waitSet, SIGTERM);
pthread_sigmask(SIG_BLOCK, &waitSet, nullptr);
int waitSig {0};
sigwait(&waitSet, &waitSig);
run = false;
thread.join();
std::cerr << "waitSig: " << waitSig << std::endl;
}
我在 WSL2 和 CentOS 机器上得到了一致的结果,我更愿意专注于在那里解决这个问题。在 WSL1 下运行时,除非我删除 pthread_sigmask(SIG_BLOCK...),否则 SIGINT 和 SIGTERM 都不会导致 sigwait() 完成,但这似乎与我对应该如何使用 sigwait() 的理解相矛盾。
【问题讨论】:
-
std::cerr << ...在信号处理程序中是不安全的。您只能从信号处理程序中安全地进行异步信号安全调用,并且使用std::cerr和类似的方法不是异步信号安全的。