Handle SIGTTIN and SIGTTOU on Unix-like OSs with X11 graphics.
That makes it possible to push ngspice into the background while plot windows are open: the windows remain responsive. Discussion on ngspice-users, starting 2023-09-01, title: "`quit` in Interactive Mode." Also restore terminal state when forcing exit with SIGINT (control-C).
This commit is contained in:
parent
588116af48
commit
41c61604c5
|
|
@ -615,9 +615,10 @@ getcommand(char *string)
|
||||||
#if !defined(HAVE_GNUREADLINE) && !defined(HAVE_BSDEDITLINE)
|
#if !defined(HAVE_GNUREADLINE) && !defined(HAVE_BSDEDITLINE)
|
||||||
/* set cp_altprompt for use by the lexer - see parser/lexical.c */
|
/* set cp_altprompt for use by the lexer - see parser/lexical.c */
|
||||||
cp_altprompt = get_alt_prompt();
|
cp_altprompt = get_alt_prompt();
|
||||||
|
#else
|
||||||
|
cp_cwait = TRUE;
|
||||||
#endif /* !defined(HAVE_GNUREADLINE) && !defined(HAVE_BSDEDITLINE) */
|
#endif /* !defined(HAVE_GNUREADLINE) && !defined(HAVE_BSDEDITLINE) */
|
||||||
|
|
||||||
cp_cwait = TRUE;
|
|
||||||
wlist = cp_parse(string);
|
wlist = cp_parse(string);
|
||||||
cp_cwait = FALSE;
|
cp_cwait = FALSE;
|
||||||
if (cp_debug) {
|
if (cp_debug) {
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,7 @@ ft_sigintr(void)
|
||||||
|
|
||||||
if (interrupt_counter >= 3) {
|
if (interrupt_counter >= 3) {
|
||||||
fprintf(cp_err, "\nKilling, since %d interrupts have been requested\n\n", interrupt_counter);
|
fprintf(cp_err, "\nKilling, since %d interrupts have been requested\n\n", interrupt_counter);
|
||||||
|
cp_ccon(FALSE);
|
||||||
controlled_exit(1);
|
controlled_exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -99,6 +100,7 @@ ft_sigintr(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* here we jump to the start of command processing in main() after resetting everything. */
|
/* here we jump to the start of command processing in main() after resetting everything. */
|
||||||
|
cp_background = FALSE;
|
||||||
LONGJMP(jbuf, 1);
|
LONGJMP(jbuf, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,6 +114,32 @@ sigfloat(int code)
|
||||||
LONGJMP(jbuf, 1);
|
LONGJMP(jbuf, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Shared handler for SIGTTIN and SIGTTOU. Restart event handling if caught
|
||||||
|
* attempting terminal IO as a background process.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool cp_background = FALSE;
|
||||||
|
|
||||||
|
#ifdef SIGTTIN
|
||||||
|
void
|
||||||
|
sigttio(void)
|
||||||
|
{
|
||||||
|
if (cp_cwait) {
|
||||||
|
/* Attempted command input/output on the terminal while in background.
|
||||||
|
* Set background flag and restart event loop.
|
||||||
|
*/
|
||||||
|
cp_background = TRUE;
|
||||||
|
LONGJMP(jbuf, 1);
|
||||||
|
} else {
|
||||||
|
/* Non-command terminal IO in background. That should never happen.
|
||||||
|
* Stop.
|
||||||
|
*/
|
||||||
|
|
||||||
|
(void) signal(SIGTSTP, SIG_DFL);
|
||||||
|
(void) kill(getpid(), SIGTSTP); /* This should stop us */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* This should give a new prompt if cshpar is waiting for input. */
|
/* This should give a new prompt if cshpar is waiting for input. */
|
||||||
|
|
||||||
|
|
@ -122,8 +150,10 @@ sigstop(void)
|
||||||
{
|
{
|
||||||
gr_clean();
|
gr_clean();
|
||||||
cp_ccon(FALSE);
|
cp_ccon(FALSE);
|
||||||
(void) signal(SIGTSTP, SIG_DFL);
|
if (!cp_background) {
|
||||||
(void) kill(getpid(), SIGTSTP); /* This should stop us */
|
(void) signal(SIGTSTP, SIG_DFL);
|
||||||
|
(void) kill(getpid(), SIGTSTP); /* This should stop us */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
void ft_sigintr(void);
|
void ft_sigintr(void);
|
||||||
void sigfloat(int code);
|
void sigfloat(int code);
|
||||||
|
void sigttio(void);
|
||||||
void sigstop(void);
|
void sigstop(void);
|
||||||
void sigcont(void);
|
void sigcont(void);
|
||||||
void sigill(void);
|
void sigill(void);
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,8 @@ extern wordlist *cp_parse(char *string);
|
||||||
|
|
||||||
/* control.c */
|
/* control.c */
|
||||||
|
|
||||||
extern bool cp_cwait;
|
extern bool cp_cwait; // Interactive and awaiting command input.
|
||||||
|
extern bool cp_background; // Running in background.
|
||||||
extern bool cp_dounixcom;
|
extern bool cp_dounixcom;
|
||||||
extern char *cp_csep;
|
extern char *cp_csep;
|
||||||
extern char * get_alt_prompt(void);
|
extern char * get_alt_prompt(void);
|
||||||
|
|
|
||||||
31
src/main.c
31
src/main.c
|
|
@ -681,10 +681,32 @@ app_rl_readlines(void)
|
||||||
history_set_pos(history_length);
|
history_set_pos(history_length);
|
||||||
|
|
||||||
if (SETJMP(jbuf, 1)) { /* Set location to jump to after handling SIGINT (ctrl-C) */
|
if (SETJMP(jbuf, 1)) { /* Set location to jump to after handling SIGINT (ctrl-C) */
|
||||||
ft_sigintr_cleanup();
|
if (!cp_background)
|
||||||
|
ft_sigintr_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
line = readline(prompt());
|
#if defined(SIGTTIN) && !defined(X_DISPLAY_MISSING)
|
||||||
|
if (cp_background) {
|
||||||
|
/* This process is running in the background, so reading from
|
||||||
|
* the terminal will fail. Instead, call the X11 input loop
|
||||||
|
* directly. It will process X11 events until terminal input
|
||||||
|
* is available, then return. If the process is still in background
|
||||||
|
* readline() will then cause another SIGTTIN and this loop
|
||||||
|
* will restart at SETJMP(). Such polling sees to be the only way
|
||||||
|
* to detect a return to the foreground.
|
||||||
|
*
|
||||||
|
* Global cp_cwait is set early so that SIGTTOU from output
|
||||||
|
* caused by clicking in a plot window will not stop the program.
|
||||||
|
*/
|
||||||
|
|
||||||
|
cp_cwait = TRUE;
|
||||||
|
app_event_func(); // Direct call to process X11 input.
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
cp_cwait = TRUE;
|
||||||
|
line = readline(cp_background ? NULL : prompt());
|
||||||
|
cp_cwait = FALSE;
|
||||||
|
cp_background = FALSE;
|
||||||
|
|
||||||
if (!line) {
|
if (!line) {
|
||||||
cp_evloop("quit");
|
cp_evloop("quit");
|
||||||
|
|
@ -706,7 +728,6 @@ app_rl_readlines(void)
|
||||||
}
|
}
|
||||||
tfree(expanded_line);
|
tfree(expanded_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
tfree(line);
|
tfree(line);
|
||||||
}
|
}
|
||||||
/* History gets written in ../fte/misccoms.c com_quit */
|
/* History gets written in ../fte/misccoms.c com_quit */
|
||||||
|
|
@ -1189,6 +1210,10 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
#ifdef SIGTSTP
|
#ifdef SIGTSTP
|
||||||
signal(SIGTSTP, (SIGNAL_FUNCTION) sigstop);
|
signal(SIGTSTP, (SIGNAL_FUNCTION) sigstop);
|
||||||
|
#endif
|
||||||
|
#ifdef SIGTTIN
|
||||||
|
signal(SIGTTIN, (SIGNAL_FUNCTION) sigttio);
|
||||||
|
signal(SIGTTOU, (SIGNAL_FUNCTION) sigttio);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue