0

I am facing an issue where the text from my stdin is not visible from on my terminal. My program does the following

Sets a SIGALRM handler which exits a program when there is no input from the user after certain duration.

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

In main function :

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

However, after my program exits, I cannot see what I type on my terminal. But the commands work fine.

running system("reset") solves the issue for now. But I need a cleaner solution. I have tried int rl_reset_line_state () and int rl_reset_terminal (char *terminal_name) but they dont seem to work.

-1

Modern shells tend to restore the terminal state after the exit of a program; older or less capable shells may not, as you observe. The usual approach as seen in APUE and other texts is to save a copy of the terminal state using tcgetattr, then restore that state when the program exits:

#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);
}
0

First, libreadline is installing its own signal handlers for ALRM, INT, etc. and will exit just fine (after restoring the termios/stty settings) upon receiving such a signal.

You can check by running/stracing a simple program like this:

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

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

So you could just get rid of your signal handler.

Second, you should never call exit(3) from a signal handler. exit(3), unlike the _exit(2) system call, is not signal safe, mainly because it has to run the handlers registered with atexit(3). For instance, just think what happens if the exit(3) is invoked while another exit(3) is already running through those handlers.

If instead of using readline(3) you're using your own code which puts the terminal into raw mode, etc, you should always save the state of the terminal upon starting and upon receiving a SIGCONT signal, and restore it before exiting and upon receiving a SIGTSTP signal. Not just on starting/exiting as seen in a lot of examples. And if you're using cursor addressing, you should also turn on/off the ca_mode with the smcup / rmcup escapes when saving/restoring the termios settings.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.