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

如何让readline响应SIGINT信号退出?设置rl_done无效问题排查

问题:Ctrl-C无法通过设置rl_done中断readline

我尝试实现按下Ctrl-C时让readline退出,原本以为设置rl_done变量就能达成目标,但实际并未生效。按下Ctrl-C后信号已被接收,且rl_done已设为1,但readline仍未退出,相关代码如下:

char    **continue_input(char **input, char *str)
{
    char    *line;
    char    *temp;

    ignore_signals();
    init_signals(CONTINUE_INPUT);
    printf("start readline%c-----------%c", 10, 10);fflush(stdout); //debug
    line = readline(str);
    printf("readline ended%c-----------%c", 10, 10);fflush(stdout); //debug
    if (rl_done == 1)
    {
        rl_done = 0;
        return (NULL);
    }
    if (!line)
    {
        ignore_signals();
        init_signals(FALSE);
        return (NULL);
    }
    temp = ft_strjoin(*input, "\n");
    free(*input);
    *input = ft_strjoin(temp, line);
    free(line);
    free(temp);
    if (!input)
        exit(EXIT_FAILURE);
    ignore_signals();
    init_signals(FALSE);
    return (input);
}

void    continue_input_signal_handler(int sig)
{
    if (sig == SIGINT)
    {
        printf("setting rl_done to 1%c-----------%c", 10, 10);fflush(stdout); //debug
        rl_done = 1;
    }
    else if (sig == SIGTERM)
    {
        exit(EXIT_SUCCESS);
    }
}

解决方案

仅设置rl_done不足以中断readline的阻塞状态。readline等待输入时处于系统调用(如read())的阻塞状态,信号触发后系统调用会返回,但readline内部会重新进入等待逻辑,不会立刻检查rl_done的值。要让readline真正退出,需要在信号处理函数中主动触发readline的状态更新:

  1. 修改信号处理函数:添加readline专用的终端状态函数,强制中断等待并刷新显示:
#include <unistd.h> // 用于write

void    continue_input_signal_handler(int sig)
{
    if (sig == SIGINT)
    {
        rl_done = 1;
        // 告诉readline切换到新行
        rl_on_new_line();
        // 清除当前输入行并刷新终端
        rl_replace_line("", 0);
        rl_redisplay();
        // 输出换行,让提示符出现在新行(用write保证异步安全)
        write(STDOUT_FILENO, "\n", 1);
    }
    else if (sig == SIGTERM)
    {
        exit(EXIT_SUCCESS);
    }
}
  1. 禁用readline默认信号处理:在调用readline()前设置rl_catch_signals = 0;,避免readline自带的SIGINT处理覆盖自定义逻辑:
    在continue_input函数中,调用readline(str)前添加:
rl_catch_signals = 0;
  1. 注意异步安全:信号处理函数中尽量避免使用printf这类非异步安全函数,改用write更稳妥,防止出现终端输出混乱的问题。

这样修改后,按下Ctrl-C时,readline会立刻退出阻塞状态,readline()函数返回,后续检查rl_done的逻辑就能正常触发,返回NULL实现退出。

内容的提问来源于stack exchange,提问作者Clément

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 13:53:11