程序从读取行退出后,标准输入中的文本不可见

程序从读取行退出后,标准输入中的文本不可见

我面临一个问题,即我的终端上看不到来自标准输入的文本。我的程序执行以下操作

设置一个 SIGALRM 处理程序,当用户在一定时间后没有输入时,该处理程序将退出程序。

void sigalrm_handler(int arg)
{   
    exit(0);
} 

在主要功能中:

{
...
alarm(100);
line = readline(line = readline(prompt);)
...
}

但是,在我的程序退出后,我看不到我在终端上输入的内容。但命令工作正常。

运行 system("reset")暂时解决了这个问题。但我需要一个更清洁的解决方案。我已经尝试过 int rl_reset_line_state ()int rl_reset_terminal (char *terminal_name)但它们似乎不起作用。

答案1

现代 shell 倾向于在程序退出后恢复终端状态;正如您所观察到的,旧的或能力较差的炮弹可能不会。 APUE 和其他文本中常见的方法是使用 保存终端状态的副本tcgetattr,然后在程序退出时恢复该状态:

#include <sys/time.h>

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>

#include <readline/readline.h>
#include <readline/history.h>

struct itimerval Alarm_Timer;
struct termios Original_Termios;
int Need_Reset;

void sigalrm_handler(int arg)
{
    if (Need_Reset)
        tcsetattr(STDIN_FILENO, TCSANOW, &Original_Termios);
    exit(0);
}

int main(void)
{
    char *line;

    tcgetattr(STDIN_FILENO, &Original_Termios);
    Need_Reset = 1;

    signal(SIGALRM, sigalrm_handler);
    Alarm_Timer.it_value.tv_sec = 3;
    setitimer(ITIMER_REAL, &Alarm_Timer, NULL);

    line = readline("* ");

    if (Need_Reset)
        tcsetattr(STDIN_FILENO, TCSANOW, &Original_Termios);

    exit(0);
}

答案2

首先,正在为、等libreadline安装自己的信号处理程序,并且在收到此类信号后将正常退出(恢复 termios/stty 设置后)。ALRMINT

您可以通过运行/跟踪一个简单的程序来进行检查,如下所示:

#include <readline/readline.h>
#include <unistd.h>

int main(void){
        alarm(3); readline("foo> ");
}

所以你可以摆脱你的信号处理程序。

其次,你应该绝不exit(3)从信号处理程序调用。exit(3)_exit(2)系统调用不同的是不是信号安全,主要是因为它必须运行注册的处理程序atexit(3)。例如,想象一下,如果在另一个处理程序已经在运行这些处理程序exit(3)时调用该处理程序,会发生什么情况。exit(3)

如果您使用自己的代码而不是readline(3)使用将终端置于原始模式等,则应始终在启动时保存终端的状态收到SIGCONT信号后,退出前恢复收到信号后SIGTSTP。不仅仅是像很多例子中那样在启动/退出时。如果您使用光标寻址,则在保存/恢复 termios 设置时还应该使用 /ca_mode转义符打开smcup/关闭。rmcup

相关内容