You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言中getline()遇SIGINT后不等待输入的原因问询

关于SIGINT中断后getline行为的疑问

我写了一段极简代码,用来读取用户输入并处理SIGINT(Ctrl+C)信号,用sigaction实现。本来预期按下Ctrl+C后换行并显示$等待输入,代码居然意外达成了预期效果,但我有个疑问:操作系统处理完中断后,getline为何不恢复等待输入,而是直接继续执行?

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>

volatile sig_atomic_t sigint_received = 0;

static void handler(int signum)
{
    sigint_received = 1;
}


int main()
{
    struct sigaction sa;

    sa.sa_handler = handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    sigaction(SIGINT, &sa, NULL);

    char *line = NULL;
    size_t n = 100;
    line = malloc(n);

    while(1){
        if(sigint_received){
            sigint_received = 0;
            printf("\n");
        }

        printf("$ ");
        getline(&line, &n, stdin);

        if(!strcmp(line, "exit\n")){
            break;
        }
    }

    if(line){
        free(line);
    }

    return 0;
} 

这是因为当进程在调用getline这类阻塞式系统调用时收到信号,系统调用会被中断并返回错误(错误码为EINTR),而非继续阻塞等待输入。

你的代码没有检查getline的返回值,所以当SIGINT触发后,getline被中断直接返回-1,代码会跳过后续的判断逻辑,回到循环开头:检查sigint_received标志、换行、重新打印$,然后再次调用getline等待输入,刚好达成了你想要的效果。

如果要让代码更严谨,建议添加getline的返回值检查:

ssize_t ret = getline(&line, &n, stdin);
if (ret == -1) {
    // 若为信号中断导致的错误,直接继续循环即可
    if (errno == EINTR) {
        continue;
    }
    // 处理其他类型的错误
    perror("getline failed");
    break;
}

另外,你用volatile sig_atomic_t来存储信号标志的做法是正确的,这是信号处理函数中修改全局变量的标准方式,能避免编译器优化带来的问题。

内容的提问来源于stack exchange,提问作者haccks

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 10:17:21