프로그램이 읽기 라인에서 종료된 후 표준 입력의 텍스트가 표시되지 않습니다.

프로그램이 읽기 라인에서 종료된 후 표준 입력의 텍스트가 표시되지 않습니다.

내 터미널에서 표준 입력의 텍스트가 표시되지 않는 문제에 직면했습니다. 내 프로그램은 다음을 수행합니다

일정 시간이 지나도 사용자 입력이 없을 때 프로그램을 종료하는 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

최신 쉘은 프로그램이 종료된 후 터미널 상태를 복원하는 경향이 있지만, 오래되었거나 성능이 떨어지는 쉘은 그렇지 않을 수 있습니다. 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 설정을 저장/복원할 때 /off ca_mode문자(on /off)도 사용해야 합니다 smcup.rmcup

관련 정보