Skip to main content

Module interrupt

Module interrupt 

Source
Expand description

Putting the terminal back when a signal ends proc.

watch turns the terminal’s raw mode on, switches to the alternate screen and hides the cursor; a confirmation prompt hides the cursor and turns off echo and line editing while it waits for a key. A normal end puts all of it back. A signal does not run any of that: the process just dies, and the shell is left typing nothing back and showing no cursor until stty sane.

While a Guard is alive, SIGINT, SIGTERM, SIGHUP and SIGQUIT (on Windows Ctrl-C, Ctrl-Break and a closing console) are caught, the terminal is put back, and proc ends by that same signal, so a shell reports 128 plus the signal number (130 for Ctrl-C, 143 for SIGTERM, 129 for SIGHUP, 131 for SIGQUIT) and knows a signal ended it: Ctrl-C stops a script’s loop. Windows has no signals, so there proc exits with 130. A signal is how a person ends a program, so it is not one of proc’s own exit codes, and nothing is printed.

The signal is not handled in the signal handler, which may not take a lock or allocate: signal-hook only records it, and a thread of ours that waits for it does the work. The thread is started by the first guard and then stays, so a signal after a guard is gone also ends proc this way (nothing is left to put back by then). While a guard is alive the calling thread blocks these signals, so they are always taken by that thread and never interrupt the one that is reading a key.

Ctrl+C typed into a prompt is not a signal (the terminal is in raw mode, so the key arrives as a character and the prompt reports it as an interrupted read): ctrl_c ends proc the same way.

Structs§

Guard
Keeps the terminal state in NEEDS for as long as it is alive

Functions§

ctrl_c
End proc as Ctrl+C does, status 130, after putting the terminal right. For a prompt that reports Ctrl+C as a key instead of the signal.
protect_prompt
From here until the guard is dropped, a signal shows the cursor and puts the line mode back to what it is now
protect_screen
From here until the guard is dropped, a signal puts the screen back: raw mode off, cursor shown, normal screen
restore_screen
Put the terminal back the way it was before watch: raw mode off, cursor shown, normal screen. Every step is tried, whatever an earlier one did.
unblocked_in_child
Start command’s child with no signal blocked. While a guard is alive this thread blocks the signals that end proc, and a child inherits the mask (the standard library keeps it), so an lsof that watch runs on a refresh could not be stopped by Ctrl-C, SIGTERM, SIGHUP or SIGQUIT.