From 31993c30406060182653334dbd715f13ae3de15a Mon Sep 17 00:00:00 2001 From: Jack Conger Date: Wed, 17 Jun 2026 10:28:15 -0700 Subject: [PATCH 1/2] Redo SIGINT newlines - Remove sig_special, sigint_newline, and the `.signal' syntax for $signals - Ignore SIGINT entirely if our child did not exit with a SIGINT status - Print \n in %interactive-loop when catching SIG^(INT TSTP QUIT) --- es.h | 4 ++-- eval.c | 9 +++------ initial.es | 4 +++- prim-sys.c | 1 - signal.c | 29 +++++++++-------------------- test/tests/trip.es | 8 ++++---- 6 files changed, 21 insertions(+), 34 deletions(-) diff --git a/es.h b/es.h index f3936293..be0ac2c7 100644 --- a/es.h +++ b/es.h @@ -341,7 +341,7 @@ extern char *sigmessage(int sig); #define SIGCHK() sigchk() typedef enum { - sig_nochange, sig_catch, sig_default, sig_ignore, sig_noop, sig_special + sig_nochange, sig_catch, sig_default, sig_ignore, sig_noop } Sigeffect; extern Sigeffect esignal(int sig, Sigeffect effect); extern void setsigeffects(const Sigeffect effects[]); @@ -350,13 +350,13 @@ extern List *mksiglist(void); extern void initsignals(Boolean interactive, Boolean allowdumps); extern Atomic slow; extern sigjmp_buf slowlabel; -extern Boolean sigint_newline; extern void sigchk(void); extern Boolean issilentsignal(List *e); extern void exitonsignal(List *e); extern void setsigdefaults(void); extern void blocksignals(void); extern void unblocksignals(void); +extern void clearsignal(int sig); /* open.c */ diff --git a/eval.c b/eval.c index cbb44dc9..483bb130 100644 --- a/eval.c +++ b/eval.c @@ -36,12 +36,9 @@ extern List *forkexec(char *file, List *list, Boolean inchild) { } gcenable(); status = ewaitfor(pid); - if ((status & 0xff) == 0) { - sigint_newline = FALSE; - SIGCHK(); - sigint_newline = TRUE; - } else - SIGCHK(); + if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGINT) + clearsignal(SIGINT); + SIGCHK(); printstatus(0, status); return mklist(mkterm(mkstatus(status), NULL), NULL); } diff --git a/initial.es b/initial.es index b8e422b3..77290d39 100644 --- a/initial.es +++ b/initial.es @@ -704,7 +704,9 @@ fn %interactive-loop { echo >[1=2] $msg $fn-%dispatch false } {~ $e signal} { - if {!~ $type sigint sigterm sigquit} { + if {~ $type sigint sigtstp sigquit} { + echo # this is the newline for (^C ^Z ^\) + } {!~ $type sigterm} { echo >[1=2] caught unexpected signal: $type } } { diff --git a/prim-sys.c b/prim-sys.c index 29c20064..de29f56e 100644 --- a/prim-sys.c +++ b/prim-sys.c @@ -114,7 +114,6 @@ PRIM(setsignals) { switch (*s) { case '-': effect = sig_ignore; s++; break; case '/': effect = sig_noop; s++; break; - case '.': effect = sig_special; s++; break; } sig = signumber(s); if (sig < 0) diff --git a/signal.c b/signal.c index 6abd0f50..00abfe05 100644 --- a/signal.c +++ b/signal.c @@ -5,8 +5,6 @@ typedef void (*Sighandler)(int); -Boolean sigint_newline = TRUE; - static Atomic sigcount; static Atomic caught[NSIG]; static Sigeffect sigeffect[NSIG]; @@ -124,12 +122,6 @@ extern Sigeffect esignal(int sig, Sigeffect effect) { return old; } break; - case sig_special: - if (sig != SIGINT) { - eprint("$&setsignals: special handler not defined for %s\n", signame(sig)); - return old; - } - FALLTHROUGH; case sig_catch: if (setsignal(sig, catcher) == SIG_ERR) { eprint("$&setsignals: cannot catch %s\n", signame(sig)); @@ -196,7 +188,7 @@ extern void initsignals(Boolean interactive, Boolean allowdumps) { } if (interactive || sigeffect[SIGINT] == sig_default) - esignal(SIGINT, sig_special); + esignal(SIGINT, sig_catch); if (!allowdumps) { if (interactive) esignal(SIGTERM, sig_noop); @@ -214,7 +206,7 @@ extern void setsigdefaults(void) { int sig; for (sig = 1; sig < NSIG; sig++) { Sigeffect e = sigeffect[sig]; - if (e == sig_catch || e == sig_noop || e == sig_special) + if (e == sig_catch || e == sig_noop) esignal(sig, sig_default); } } @@ -247,6 +239,13 @@ extern void exitonsignal(List *exception) { esignal(sig, e); } +extern void clearsignal(int sig) { + if (caught[sig]) { + caught[sig] = FALSE; + --sigcount; + } +} + extern List *mksiglist(void) { int sig = NSIG; Sigeffect effects[NSIG]; @@ -260,7 +259,6 @@ extern List *mksiglist(void) { case sig_catch: prefix = '\0'; break; case sig_ignore: prefix = '-'; break; case sig_noop: prefix = '/'; break; - case sig_special: prefix = '.'; break; } Ref(char *, name, signame(sig)); if (prefix != '\0') @@ -322,15 +320,6 @@ extern void sigchk(void) { while (gcisblocked()) gcenable(); throw(e); - case sig_special: - assert(sig == SIGINT); - /* this is the newline you see when you hit ^C while typing a command */ - if (sigint_newline) - eprint("\n"); - sigint_newline = TRUE; - while (gcisblocked()) - gcenable(); - throw(e); case sig_noop: break; default: diff --git a/test/tests/trip.es b/test/tests/trip.es index 7a155138..85a4fd57 100644 --- a/test/tests/trip.es +++ b/test/tests/trip.es @@ -160,7 +160,7 @@ never succeeded } test 'signals in exception catchers' { - local (signals = sigint) { + local (signals = sigterm) { let ( was-blocked = false thrown = () @@ -169,7 +169,7 @@ test 'signals in exception catchers' { thrown = $* } { catch @ e { - kill -INT $pid + kill -TERM $pid was-blocked = true } { throw exception @@ -182,7 +182,7 @@ test 'signals in exception catchers' { catch @ { thrown = $* } { - catch @ e {kill -INT $pid} {throw exception} + catch @ e {kill -TERM $pid} {throw exception} } assert {~ $thrown(1) signal} second signal is caught } @@ -190,7 +190,7 @@ test 'signals in exception catchers' { catch @ { thrown = $* } { - catch @ e {kill -INT $pid; throw exception} {throw exception} + catch @ e {kill -TERM $pid; throw exception} {throw exception} } assert {~ $thrown(1) signal} signal exception has precedence within catcher } From da3a5c299916f6473a9622b751f4fd7d8f19d097 Mon Sep 17 00:00:00 2001 From: Jack Conger Date: Wed, 17 Jun 2026 12:37:52 -0700 Subject: [PATCH 2/2] Remove .sigint from man page --- doc/es.1 | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/doc/es.1 b/doc/es.1 index e87d5e1c..3d1a70be 100644 --- a/doc/es.1 +++ b/doc/es.1 @@ -1773,18 +1773,11 @@ A signal prefixed by a slash .Rc ( / ) is ignored in the current shell, but retains default behavior in child processes. -In addition, the signal -.Cr sigint -may be preceded by the prefix -.Rc ( . ) -to indicate that normal shell interrupt processing -(i.e., the printing of an extra newline) -occurs. By default .I es starts up with the values .Ds -.Cr ".sigint /sigquit /sigterm" +.Cr "sigint /sigquit /sigterm" .De .TP \&