【问题标题】:SIGINT lost when output redirected; how to detect termination in program?输出重定向时 SIGINT 丢失;如何检测程序中的终止?
【发布时间】:2012-10-28 18:06:11
【问题描述】:

我编写了检测 SIGINT 的控制台程序,所以当用户按下 Ctrl+C 时,程序会执行一些操作并终止。

但是当我用管道将此程序重定向到任何其他程序时,例如: ./my_program | tee xxx SIGINT 永远不会出现在我的处理程序中。尽管这个程序终止。 处理 SIGTERM 没有任何效果。 SIGTERM 也不会出现在 Ctrl+C 之后。

如何检测到程序在所有情况下都被 Ctrl+c 中止?


我的 SIGINT 和 SIGPIPE 测试用例:

    #include <csignal>
#include <cstdio>

bool break_request=false;
bool term_request=false;

extern "C" void break_handler(int)
{
    break_request=true;
    printf("Ctrl+C detected\n");
}

extern "C" void term_handler(int)
{
    term_request=true;
    printf("pipe detected\n");
}

int main()
{
    signal(SIGINT,break_handler);
    signal(SIGPIPE,term_handler);

    while(true)
    {
        if(break_request)
        {
            printf("break request handled\n");
            break;
        }

        if(term_request)
        {
            printf("pipe request handled\n");
            break;
        }
    }

    printf("terminating\n");
}

【问题讨论】:

  • 嗯,Ctrl-C 只会发出最后一个程序的信号,即tee。充其量,my_program 会得到一个 SIGPIPE,因为管道的读取端已关闭。
  • 如果我没记错的话,如果管道另一边的程序死了,你可能会得到SIGPIPE。尝试将其设置为SIG_IGN 或以相同方式处理。
  • 传统上,中断将被发送到管道中的所有程序。我不确定信号应该去向的定义是否/何时发生了变化,但是我遇到了一些简单的脚本在我想要它们时没有死的问题——这既令人惊讶又(非常)烦人。我使用的是ksh 而不是bash;我还没有计算出这个因素有多大。

标签: c linux sigint


【解决方案1】:

您的printf 输出正在下降。请改用fprintf(stderr, "...")

【讨论】:

  • 但我不会强制执行 SIGPIPE 事件。我想在任何情况下处理终止(尽管程序目前是否有任何要打印的内容)
  • 不,输出表明信号处理程序捕获了管道中丢失的信号。 Ctrl-c 真的被抓住了。试试看。
  • 知道了!你很棒!所以解决方案是不要在 SIGINT 之后使用标准输出。非常感谢
【解决方案2】:

如果您的程序在管道中使用,如果在另一端没有阅读器的情况下写入,它将得到SIGPIPE

只需安装一个SIGPIPE 处理程序。

【讨论】:

  • 失败。 SIGPIPE 处理程序也从未调用过:(
  • 失败可能是因为程序此时没有尝试输出任何内容。但是程序在 Ctrl+C 后立即终止
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-06
  • 1970-01-01
  • 1970-01-01
  • 2010-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多