gpt4 book ai didi

任何信号上的 C++ 轮询错误

转载 作者:太空宇宙 更新时间:2023-11-04 15:42:13 24 4
gpt4 key购买 nike

我的信号 SIGTERM 和 SIGINT 信号处理程序在接收其中任何一个时都会导致轮询错误。我不确定它为什么这样做,而且我想我没有意识到我错过了某些 sigaction 行为。

while(!signalHandler.gotExitSignal()) {
switch (poll(&ufds[0], NUM_FDS, POLL_TIMEOUT)) {
case -1: {
throw std::runtime_error("poll error (-1)"); /* ABORT */
}
.
.

我的 signalHandler 是一个包含 sigaction 处理的类。

struct sigaction killAction, termAction;

memset(&killAction, 0, sizeof(struct sigaction));
killAction.sa_handler = SignalHandler::ExitHandler;
sigemptyset(&killAction.sa_mask);
killAction.sa_flags = 0;
if(sigaction(SIGTERM, &killAction, NULL) < 0)
throw SignalException("sigaction failed for killAction");

memset(&termAction, 0, sizeof(struct sigaction));
termAction.sa_handler = SignalHandler::ExitHandler;
sigemptyset(&termAction.sa_mask);
termAction.sa_flags = 0;
if(sigaction(SIGTERM, &termAction, NULL) < 0)
throw SignalException("sigaction failed for termAction");

所以我给出的片段循环的预期行为应该是:

  1. while(!signalHandler.gotExitSignal()) {
  2. 开关(轮询(&ufds[0],NUM_FDS,POLL_TIMEOUT)){
  3. 轮询后做一些清理工作
  4. 转到 1
  5. while(!signalHandler.gotExitSignal()) {
  6. 打断
  7. 开关(轮询(&ufds[0],NUM_FDS,POLL_TIMEOUT)){
  8. 轮询后做一些清理工作
  9. 转到 1
  10. 打破循环

发生了什么:

  1. while(!signalHandler.gotExitSignal()) {
  2. 开关(轮询(&ufds[0],NUM_FDS,POLL_TIMEOUT)){
  3. 轮询后做一些清理工作
  4. 转到 1
  5. while(!signalHandler.gotExitSignal()) {
  6. 打断
  7. throw std::runtime_error("轮询错误 (-1)");

我尝试了一个场景,在轮询切换之后我睡了 2 秒然后终止了程序 - 它在循环条件下优雅地退出。当我轮询然后收到信号时,问题就存在了。我不使用 SIGHUP 信号,该信号用于告诉程序重新加载其配置,但我为 SIGHUP 设置了一个信号进行测试,它像我的其他信号一样以轮询错误终止了我的程序。但是我不能让我的程序因任何信号而崩溃,我想知道我是否忘记了什么。

最佳答案

这是预料之中的。在 poll() 中阻塞并且信号到达时,poll 将失败并且 errno 将设置为 EINTR。对于大多数系统调用,您将获得相同的行为。

您可以而且应该检测到这一点(您现在也可以更快地跳出轮询循环,因为 poll() 将返回当捕获到信号时。)

while(!signalHandler.gotExitSignal()) {
switch (poll(&ufds[0], NUM_FDS, POLL_TIMEOUT)) {
case -1: {
if (errno == EINTR) {
continue;
}
throw std::runtime_error("poll error (-1)"); /* ABORT */
}

您很可能还想为 sigaction 设置 SA_RESTART 标志。

 killAction.sa_flags = SA_RESTART;

这将导致大多数系统调用在捕获到信号时不返回错误。阅读 sigaction() 的联机帮助页以获取更多信息,并阅读 man 7 signal 中的“信号处理程序中断系统调用和库函数”部分。 .

值得注意的是,无论设置 SA_RESTART 标志,poll() 仍将被信号中断(立即返回错误)。

关于任何信号上的 C++ 轮询错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21313780/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com