【问题标题】:my printf isnt showing up when handling sigaction until i exit [duplicate]处理 sigaction 时我的 printf 没有出现,直到我退出 [重复]
【发布时间】:2020-04-06 01:43:41
【问题描述】:

我是 Unix 中的信号新手,这个练习的目的是禁用 SIGINT 来停止程序并改用 SIGQUIT,当我按下 ctrl-c 时它成功地忽略了 SIGINT 但直到我按下 printf 才显示Ctrl-/ 用于SIGQUIT,所有消息同时出现。

示例:如果我按 ctrl-c 4 次然后按 ctrl-/: 只有在按下 ctrl-\ 后,我才会收到 4 条消息,说我按下了 Ctrl-c 然后退出你发送了 SIGQUIT 信号。

如果我只按 ctrl-c 我什么也得不到,但至少它被忽略了

struct sigaction action;

void hand(int sig)
{
    switch(sig){
    case SIGINT:
        printf("You have presed ctrl-c");
        break;
    case SIGQUIT:
        printf("Quittin you sent a SIGQUIT signal");
        exit(SIGQUIT);
        break;
    default:
        printf("WRONG SIGNAL");
        exit(-1);
        break;
    }
}

int main()
{       
    action.sa_handler=hand;
    printf("Ctrl-C disabled, press Ctrl-/ to quit...\n");
    sigaction(SIGINT,&action,NULL);
    sigaction(SIGQUIT,&action,NULL);
    while(1){
        sleep(1);
    }
}

【问题讨论】:

  • 请正确格式化您的代码。
  • printf("You have presed ctrl-c"); --> printf("You have presed ctrl-c\n"); 顺便说一句,您必须避免在信号处理程序中使用 printf
  • @LPs 谢谢!它有效,但为什么呢?
  • 是的,谢谢! @ChrisTurner
  • 因为它是标准输出被缓冲。所以\n 将切换到“新行”

标签: c unix signals


【解决方案1】:

这里有两个问题。首先,printf 默认情况下是行缓冲的,并且您没有打印换行符,因此输出缓冲区可能不会在您期望的时候被刷新。其次,printf 函数不是异步信号安全的,这意味着在信号处理程序中调用它是未定义的行为。

更改您的信号处理程序以设置标志而不是打印,然后在循环中检查该标志并打印(在字符串末尾带有\n)如果已设置。

【讨论】:

    【解决方案2】:

    除了@dbush answer,您还可以在信号处理程序中使用write,它是async-signal-safe,并且没有缓冲延迟其输出。

    例子:

    static char const msg[] = "You have presed ctrl-c\n";
    write(STDOUT_FILENO, msg, sizeof msg - 1);
    

    【讨论】:

      猜你喜欢
      • 2020-10-05
      • 2021-12-29
      • 1970-01-01
      • 2018-05-16
      • 2021-08-05
      • 2018-11-28
      • 1970-01-01
      • 1970-01-01
      • 2021-02-16
      相关资源
      最近更新 更多