【问题标题】:How to stop reading from keyboard once a signal is handled?处理信号后如何停止从键盘读取?
【发布时间】:2017-04-05 21:16:30
【问题描述】:

我正在编写一个程序,其中 SIGINT 信号在第一次发送时被处理,但之后设置为默认值。所以,例如,我有这个:

static volatile int stop_terminating = 1;

void handler(int dummy) {
    stop_terminating = 0;
}

int main(){
    signal(SIGINT, handler);
    char input[256];
    while(1){
        if(stop_terminating == 0){
            // reset the action of the signal to default
            signal(SIGINT, SIG_DFL);
            printf("Message sent.\n");
            // increment counter so it doesn't enter this condition again
            stop_terminating++;
        }
        printf("User input:\n");
        fgets(input, sizeof(input), stdin);
        // In this stage, I wanna press CTRL+C and print a message, stopping the fgets
        // but what happens is: I press CTRL+C, the signal is catched, but fgets
        // is still asking for an input, and after I send something, the my message is printed
        // because it looped through the while(1) again.
    }
}

如何阻止 fgets 请求输入,只打印消息,然后再次请求输入?

【问题讨论】:

  • volatile 不足以进行多线程编程。使用原子。
  • 我实际上不知道该怎么做。我一直在努力达到这一点,我只知道部分事情。
  • @Olaf:信号不是线程。 volatile 就足够了。
  • @BenVoigt:我想知道为什么 sig_atomic_t 会提供额外的保证。有趣的是,这种类型 C11 的原子支持之前就已经存在了。注意:volatile 不保证原子访问。

标签: c linux signals fgets


【解决方案1】:

信号的 Linux 手册页说

信号处理程序中断系统调用和库函数

如果在阻止系统调用或库函数调用时调用信号处理程序,则:

  • 信号处理程序返回后自动重新开始调用;或

  • 调用失败,错误为EINTR

这两种行为中的哪一种取决于接口以及是否使用SA_RESTART 标志建立信号处理程序(请参阅sigaction(2))。

您可以将siginterrupt() 函数与signal() 一起使用,或者使用sigaction() 而不是signal() 来注册您的信号处理程序,以禁用在信号后重新启动read() 系统调用。

但请注意,C 库中的 fgets() 可能会多次调用 read() 直到找到换行符,因此您可能还需要切换到使用较低级别的函数而不是 stdio.h API。

【讨论】:

    【解决方案2】:

    如果你关闭标准输入 fgets 会立即返回,那么你可以尝试再次打开标准输入。这很奇怪,但可以作为一种解决方法

    【讨论】:

      【解决方案3】:

      当 fgets 到达 EOF 时,你会得到一个 NULL。从键盘上,通常使用 CTRL-D(Linux/Unix/MacOS X)或 CTRL-Z(DOS/Windows,我认为 MacOS 在 X 之前)发出信号

      【讨论】:

      • 这对信号处理没有帮助,这是问题的重点。
      • CTRL+D 实际上不是一个信号,所以在这种情况下这对我没有帮助。不过我已经解决了,还是谢谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-13
      • 1970-01-01
      • 2017-08-23
      • 1970-01-01
      • 1970-01-01
      • 2013-03-03
      相关资源
      最近更新 更多