From f13dc04bbbf1b663e6e431df9848a04d5ba2eb4b Mon Sep 17 00:00:00 2001 From: jpco Date: Wed, 27 Nov 2024 10:36:26 -0800 Subject: [PATCH 1/9] Externalize printstatus() as %print-status. Also add $&sigmessage primitive. --- eval.c | 2 +- initial.es | 23 +++++++++++++++++++++-- prim-io.c | 13 +++++++------ prim-sys.c | 29 +++++++++++++++++++++++++---- status.c | 23 ++++++++++------------- 5 files changed, 64 insertions(+), 26 deletions(-) diff --git a/eval.c b/eval.c index 8e36896b..43c6d2d3 100644 --- a/eval.c +++ b/eval.c @@ -41,7 +41,7 @@ extern List *forkexec(char *file, List *list, Boolean inchild) { sigint_newline = TRUE; } else SIGCHK(); - printstatus(0, status); + printstatus(pid, status); return mklist(mkterm(mkstatus(status), NULL), NULL); } diff --git a/initial.es b/initial.es index 70a5982d..638028b3 100644 --- a/initial.es +++ b/initial.es @@ -76,7 +76,6 @@ fn-newpgrp = $&newpgrp fn-result = $&result fn-throw = $&throw fn-umask = $&umask -fn-wait = $&wait fn-%read = $&read @@ -579,6 +578,26 @@ fn %pathsearch name { access -n $name -1e -xf $path } if {~ <=$&primitives execfailure} {fn-%exec-failure = $&execfailure} +# The %print-status hook is used to print any potentially interesting +# status from an exec()ed binary. + +fn %print-status pid did status { + if {~ $did signaled} { + let (msg = <={if {$print-status-pid} {result $pid^': '} {result ''}}) { + msg = $msg^<={$&sigmessage $status} + if {~ $status *+core} { + msg = $msg^'--core dumped' + } + echo >[1=2] $msg + } + } +} + +print-status-pid = false + +fn wait { + local (print-status-pid = true) $&wait $* +} # # Read-eval-print loops @@ -756,7 +775,7 @@ max-eval-depth = 640 # is does. fn-%dispatch is really only important to the current # interpreter loop. -noexport = noexport pid signals apid bqstatus fn-%dispatch path home matchexpr +noexport = noexport pid signals apid bqstatus fn-%dispatch path home matchexpr print-status-pid # diff --git a/prim-io.c b/prim-io.c index 9cd35b4a..a8d293a3 100644 --- a/prim-io.c +++ b/prim-io.c @@ -234,9 +234,10 @@ PRIM(pipe) { Ref(List *, result, NULL); do { + int pid = pids[--n]; Term *t; - int status = ewaitfor(pids[--n]); - printstatus(0, status); + int status = ewaitfor(pid); + printstatus(pid, status); t = mkstr(mkstatus(status)); result = mklist(t, result); } while (0 < n); @@ -280,7 +281,7 @@ PRIM(readfrom) { close(p[0]); status = ewaitfor(pid); - printstatus(0, status); + printstatus(pid, status); varpop(&push); RefEnd3(cmd, input, var); RefReturn(lp); @@ -320,7 +321,7 @@ PRIM(writeto) { close(p[1]); status = ewaitfor(pid); - printstatus(0, status); + printstatus(pid, status); varpop(&push); RefEnd3(cmd, output, var); RefReturn(lp); @@ -365,11 +366,11 @@ PRIM(backquote) { } close(p[1]); - gcdisable(); lp = bqinput(sep, p[0]); close(p[0]); status = ewaitfor(pid); - printstatus(0, status); + printstatus(pid, status); + gcdisable(); lp = mklist(mkstr(mkstatus(status)), lp); gcenable(); list = lp; diff --git a/prim-sys.c b/prim-sys.c index 0506df8a..a52b59b5 100644 --- a/prim-sys.c +++ b/prim-sys.c @@ -56,7 +56,7 @@ PRIM(fork) { esexit(exitstatus(eval(list, NULL, evalflags | eval_inchild))); status = ewaitfor(pid); SIGCHK(); - printstatus(0, status); + printstatus(pid, status); return mklist(mkstr(mkstatus(status)), NULL); } @@ -128,6 +128,26 @@ PRIM(setsignals) { return mksiglist(); } +PRIM(sigmessage) { + int sig; + char *s, *p; + if (list == NULL || list->next != NULL) + fail("$&sigmessage", "usage: $&sigmessage signal"); + s = getstr(list->term); + if ((p = strchr(s, '+')) != NULL) { + if (streq(p, "+core")) + *p = '\0'; + else + p = NULL; + } + sig = signumber(s); + if (p != NULL) + *p = '+'; + if (sig < 0) + fail("$&sigmessage", "unknown signal: %s", s); + return mklist(mkstr(sigmessage(sig)), NULL); +} + /* * limit builtin -- this is too much code for what it gives you */ @@ -306,7 +326,7 @@ PRIM(time) { status = ewait(pid, FALSE, &r); t1 = time(NULL); SIGCHK(); - printstatus(0, status); + printstatus(pid, status); eprint( "%6ldr %5ld.%ldu %5ld.%lds\t%L\n", @@ -342,7 +362,7 @@ PRIM(time) { status = ewaitfor(pid); t1 = times(&tms); SIGCHK(); - printstatus(0, status); + printstatus(pid, status); tms.tms_cutime += ticks / 20; tms.tms_cstime += ticks / 20; @@ -358,7 +378,7 @@ PRIM(time) { } status = ewaitfor(pid); SIGCHK(); - printstatus(0, status); + printstatus(pid, status); RefEnd(lp); return mklist(mkstr(mkstatus(status)), NULL); @@ -439,6 +459,7 @@ extern Dict *initprims_sys(Dict *primdict) { X(fork); X(run); X(setsignals); + X(sigmessage); #if BSD_LIMITS X(limit); #endif diff --git a/status.c b/status.c index 13dd47ed..c72c552b 100644 --- a/status.c +++ b/status.c @@ -65,18 +65,15 @@ extern char *mkstatus(int status) { /* printstatus -- print the status if we should */ extern void printstatus(int pid, int status) { - if (WIFSIGNALED(status)) { - const char *msg = sigmessage(WTERMSIG(status)), *tail = ""; - if (WCOREDUMP(status)) { - tail = "--core dumped"; - if (*msg == '\0') - tail += (sizeof "--") - 1; - } - if (*msg != '\0' || *tail != '\0') { - if (pid == 0) - eprint("%s%s\n", msg, tail); - else - eprint("%d: %s%s\n", pid, msg, tail); - } + Ref(List *, fn, varlookup("fn-%print-status", NULL)); + Ref(List *, list, NULL); + if (fn != NULL) { + gcdisable(); + list = mklist(mkstr(mkstatus(status)), NULL); + list = mklist(mkstr((WIFSIGNALED(status) ? "signaled" : "exited")), list); + list = mklist(mkstr(str("%d", pid)), list); + gcenable(); + eval(append(fn, list), NULL, 0); } + RefEnd2(list, fn); } From a91d2643afcba012fa97b6226b33ff36d8f85024 Mon Sep 17 00:00:00 2001 From: jpco Date: Fri, 29 Nov 2024 11:05:24 -0800 Subject: [PATCH 2/9] Don't print anything on sigint or sigpipe --- initial.es | 2 +- mksignal | 11 +++-------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/initial.es b/initial.es index 638028b3..a8e50d19 100644 --- a/initial.es +++ b/initial.es @@ -582,7 +582,7 @@ if {~ <=$&primitives execfailure} {fn-%exec-failure = $&execfailure} # status from an exec()ed binary. fn %print-status pid did status { - if {~ $did signaled} { + if {~ $did signaled && !~ $status (sigint sigpipe)} { let (msg = <={if {$print-status-pid} {result $pid^': '} {result ''}}) { msg = $msg^<={$&sigmessage $status} if {~ $status *+core} { diff --git a/mksignal b/mksignal index cab97cb5..870733b8 100755 --- a/mksignal +++ b/mksignal @@ -34,12 +34,14 @@ sed -n ' mesg["SIGHUP"] = "hangup" mesg["SIGILL"] = "illegal instruction" mesg["SIGINFO"] = "information request" + mesg["SIGINT"] = "interrupt" mesg["SIGIO"] = "input/output possible" mesg["SIGIOT"] = "IOT instruction" mesg["SIGKILL"] = "killed" mesg["SIGLOST"] = "resource lost" mesg["SIGLWP"] = "lightweight process library signal" mesg["SIGMIGRATE"] = "migrate process" + mesg["SIGPIPE"] = "broken pipe" mesg["SIGPOLL"] = "pollable event occurred" mesg["SIGPROF"] = "profiling timer alarm" mesg["SIGPWR"] = "power failure" @@ -82,13 +84,6 @@ sed -n ' mesg["SIGVIRT"] = "virtual time alarm" mesg["SIGWINDOW"] = "window size changed" - - # set nomesg["SIGNAME"] to suppress message printing - - nomesg["SIGINT"] = 1 - nomesg["SIGPIPE"] = 1 - - # set ignore["SIGNAME"] to explicitly ignore a named signal (usually, this # is just for things that look like signals but really are not) @@ -117,7 +112,7 @@ sed -n ' sig[$1] == 0 && ignore[$1] == 0 { sig[$1] = ++nsig signame[nsig] = $1 - if (mesg[$1] == "" && nomesg[$1] == 0) { + if (mesg[$1] == "") { str = $3 for (i = 4; i <= NF; i++) str = str " " $i From 118efc7f55057737be1b5a3007a4c406d76814fd Mon Sep 17 00:00:00 2001 From: jpco Date: Sat, 30 Nov 2024 08:58:20 -0800 Subject: [PATCH 3/9] Add -n option to $&wait, corresponding with WNOHANG --- es.h | 4 ++-- prim-sys.c | 2 +- proc.c | 45 +++++++++++++++++++++++++++++++-------------- 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/es.h b/es.h index ea218575..4fd4cd63 100644 --- a/es.h +++ b/es.h @@ -226,8 +226,8 @@ extern int efork(Boolean parent, Boolean background); extern pid_t spgrp(pid_t pgid); extern int tctakepgrp(void); extern void initpgrp(void); -extern int ewait(int pid, Boolean interruptible, void *rusage); -#define ewaitfor(pid) ewait(pid, FALSE, NULL) +extern int ewait(int pid, int opts, void *rusage); +#define ewaitfor(pid) ewait(pid, 0, NULL) #if JOB_PROTECT extern void tcreturnpgrp(void); diff --git a/prim-sys.c b/prim-sys.c index a52b59b5..38942d34 100644 --- a/prim-sys.c +++ b/prim-sys.c @@ -323,7 +323,7 @@ PRIM(time) { pid = efork(TRUE, FALSE); if (pid == 0) esexit(exitstatus(eval(lp, NULL, evalflags | eval_inchild))); - status = ewait(pid, FALSE, &r); + status = ewait(pid, 0, &r); t1 = time(NULL); SIGCHK(); printstatus(pid, status); diff --git a/proc.c b/proc.c index c12da2e6..4e3e328e 100644 --- a/proc.c +++ b/proc.c @@ -9,6 +9,9 @@ #include #endif +#define EWINTERRUPTIBLE 1 +#define EWNOHANG 2 + Boolean hasforked = FALSE; typedef struct Proc Proc; @@ -137,7 +140,7 @@ static void timesub(struct timeval *a, struct timeval *b, struct timeval *res) { #endif /* dowait -- a waitpid wrapper that gets rusage and interfaces with signals */ -static int dowait(int pid, int *statusp, void UNUSED *rusagep) { +static int dowait(int pid, int opts, int *statusp, void UNUSED *rusagep) { int n; #if HAVE_GETRUSAGE static struct rusage ru_saved; @@ -147,7 +150,7 @@ static int dowait(int pid, int *statusp, void UNUSED *rusagep) { if (!setjmp(slowlabel)) { slow = TRUE; n = interrupted ? -2 : - waitpid(pid, statusp, 0); + waitpid(pid, statusp, (opts & EWNOHANG ? WNOHANG : 0)); #if HAVE_GETRUSAGE if (rusagep != NULL) { struct rusage *rusage = (struct rusage *)rusagep; @@ -185,21 +188,26 @@ static Proc *reap(int pid) { } /* ewait -- wait for a specific process to die, or any process if pid == -1 */ -extern int ewait(int pidarg, Boolean interruptible, void *rusage) { +extern int ewait(int pidarg, int opts, void *rusage) { int deadpid, status; Proc *proc; - while ((deadpid = dowait(pidarg, &status, rusage)) == -1) { + while ((deadpid = dowait(pidarg, (opts & EWNOHANG), &status, rusage)) == -1) { if (errno == ECHILD && pidarg > 0) fail("es:ewait", "wait: %d is not a child of this shell", pidarg); - else if (errno != EINTR) + else if (errno == ECHILD && (opts & EWNOHANG) > 0) { + deadpid = 0; + break; + } else if (errno != EINTR) fail("es:ewait", "wait: %s", esstrerror(errno)); - if (interruptible) + if (opts & EWINTERRUPTIBLE) SIGCHK(); } - proc = reap(deadpid); #if JOB_PROTECT tctakepgrp(); #endif + if (deadpid == 0) /* dowait(EWNOHANG) returned nothing */ + return -1; /* FIXME: replace this with a better value! */ + proc = reap(deadpid); if (proc->background) printstatus(proc->pid, status); efree(proc); @@ -221,20 +229,29 @@ PRIM(apids) { } PRIM(wait) { - int pid; - if (list == NULL) - pid = -1; - else if (list->next == NULL) { + int status, pid = -1, opts = EWINTERRUPTIBLE; + Ref(List *, lp, list); + if (lp != NULL && streq(getstr(lp->term), "-n")) { + opts = opts | EWNOHANG; + lp = lp->next; + } + if (lp != NULL) { pid = atoi(getstr(list->term)); if (pid <= 0) { fail("$&wait", "wait: %d: bad pid", pid); NOTREACHED; } - } else { - fail("$&wait", "usage: wait [pid]"); + lp = lp->next; + } + if (lp != NULL) { + fail("$&wait", "usage: wait [-n] [pid]"); NOTREACHED; } - return mklist(mkstr(mkstatus(ewait(pid, TRUE, NULL))), NULL); + RefEnd(lp); + status = ewait(pid, opts, NULL); + if (status == -1) /* FIXME: this will be a better value soon */ + return NULL; + return mklist(mkstr(mkstatus(status)), NULL); } extern Dict *initprims_proc(Dict *primdict) { From 7b423b69dea7c6bc082188f87eeaf82deb2c9035 Mon Sep 17 00:00:00 2001 From: jpco Date: Sat, 30 Nov 2024 09:35:43 -0800 Subject: [PATCH 4/9] Use $&sigmessage in %interactive-loop --- initial.es | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/initial.es b/initial.es index a8e50d19..fe785b39 100644 --- a/initial.es +++ b/initial.es @@ -661,7 +661,7 @@ fn %interactive-loop { $fn-%dispatch false } {~ $e signal} { if {!~ $type sigint sigterm sigquit} { - echo >[1=2] caught unexpected signal: $type + echo >[1=2] caught unexpected signal: $type: <={$&sigmessage $type} } } { echo >[1=2] uncaught exception: $e $type $msg From fff454e3163a5047d805bebb35d2b772e586ca62 Mon Sep 17 00:00:00 2001 From: jpco Date: Sat, 30 Nov 2024 10:19:44 -0800 Subject: [PATCH 5/9] Call printstatus() from ewait() and remove proc->background field --- es.h | 2 +- eval.c | 3 +-- prim-io.c | 16 ++++++---------- prim-sys.c | 14 +++++--------- proc.c | 20 ++++++++------------ 5 files changed, 21 insertions(+), 34 deletions(-) diff --git a/es.h b/es.h index 4fd4cd63..4913d278 100644 --- a/es.h +++ b/es.h @@ -222,7 +222,7 @@ extern char *checkexecutable(char *file); /* proc.c */ extern Boolean hasforked; -extern int efork(Boolean parent, Boolean background); +extern int efork(Boolean parent); extern pid_t spgrp(pid_t pgid); extern int tctakepgrp(void); extern void initpgrp(void); diff --git a/eval.c b/eval.c index 43c6d2d3..f55a6f88 100644 --- a/eval.c +++ b/eval.c @@ -28,7 +28,7 @@ extern List *forkexec(char *file, List *list, Boolean inchild) { Vector *env; gcdisable(); env = mkenv(); - pid = efork(!inchild, FALSE); + pid = efork(!inchild); if (pid == 0) { execve(file, vectorize(list)->vector, env->vector); failexec(file, list); @@ -41,7 +41,6 @@ extern List *forkexec(char *file, List *list, Boolean inchild) { sigint_newline = TRUE; } else SIGCHK(); - printstatus(pid, status); return mklist(mkterm(mkstatus(status), NULL), NULL); } diff --git a/prim-io.c b/prim-io.c index a8d293a3..83c52935 100644 --- a/prim-io.c +++ b/prim-io.c @@ -141,7 +141,7 @@ static int pipefork(int p[2], int *extra) { registerfd(extra, FALSE); ExceptionHandler - pid = efork(TRUE, FALSE); + pid = efork(TRUE); CatchExceptionIf (pid != 0, e) unregisterfd(&p[0]); unregisterfd(&p[1]); @@ -205,7 +205,7 @@ PRIM(pipe) { for (;; list = list->next) { int p[2], pid; - pid = (list->next == NULL) ? efork(TRUE, FALSE) : pipefork(p, &inpipe); + pid = (list->next == NULL) ? efork(TRUE) : pipefork(p, &inpipe); if (pid == 0) { /* child */ if (inpipe != -1) { @@ -237,7 +237,6 @@ PRIM(pipe) { int pid = pids[--n]; Term *t; int status = ewaitfor(pid); - printstatus(pid, status); t = mkstr(mkstatus(status)); result = mklist(t, result); } while (0 < n); @@ -248,7 +247,7 @@ PRIM(pipe) { #if HAVE_DEV_FD PRIM(readfrom) { - int pid, p[2], status; + int pid, p[2]; Push push; caller = "$&readfrom"; @@ -280,15 +279,14 @@ PRIM(readfrom) { EndExceptionHandler close(p[0]); - status = ewaitfor(pid); - printstatus(pid, status); + ewaitfor(pid); varpop(&push); RefEnd3(cmd, input, var); RefReturn(lp); } PRIM(writeto) { - int pid, p[2], status; + int pid, p[2]; Push push; caller = "$&writeto"; @@ -320,8 +318,7 @@ PRIM(writeto) { EndExceptionHandler close(p[1]); - status = ewaitfor(pid); - printstatus(pid, status); + ewaitfor(pid); varpop(&push); RefEnd3(cmd, output, var); RefReturn(lp); @@ -369,7 +366,6 @@ PRIM(backquote) { lp = bqinput(sep, p[0]); close(p[0]); status = ewaitfor(pid); - printstatus(pid, status); gcdisable(); lp = mklist(mkstr(mkstatus(status)), lp); gcenable(); diff --git a/prim-sys.c b/prim-sys.c index 38942d34..409d4008 100644 --- a/prim-sys.c +++ b/prim-sys.c @@ -36,7 +36,7 @@ PRIM(newpgrp) { } PRIM(background) { - int pid = efork(TRUE, TRUE); + int pid = efork(TRUE); if (pid == 0) { #if JOB_PROTECT /* job control safe version: put it in a new pgroup, if interactive. */ @@ -51,12 +51,11 @@ PRIM(background) { PRIM(fork) { int pid, status; - pid = efork(TRUE, FALSE); + pid = efork(TRUE); if (pid == 0) esexit(exitstatus(eval(list, NULL, evalflags | eval_inchild))); status = ewaitfor(pid); SIGCHK(); - printstatus(pid, status); return mklist(mkstr(mkstatus(status)), NULL); } @@ -320,13 +319,12 @@ PRIM(time) { gc(); /* do a garbage collection first to ensure reproducible results */ t0 = time(NULL); - pid = efork(TRUE, FALSE); + pid = efork(TRUE); if (pid == 0) esexit(exitstatus(eval(lp, NULL, evalflags | eval_inchild))); status = ewait(pid, 0, &r); t1 = time(NULL); SIGCHK(); - printstatus(pid, status); eprint( "%6ldr %5ld.%ldu %5ld.%lds\t%L\n", @@ -345,7 +343,7 @@ PRIM(time) { Ref(List *, lp, list); gc(); /* do a garbage collection first to ensure reproducible results */ - pid = efork(TRUE, FALSE); + pid = efork(TRUE); if (pid == 0) { clock_t t0, t1; struct tms tms; @@ -355,14 +353,13 @@ PRIM(time) { ticks = sysconf(_SC_CLK_TCK); t0 = times(&tms); - pid = efork(TRUE, FALSE); + pid = efork(TRUE); if (pid == 0) esexit(exitstatus(eval(lp, NULL, evalflags | eval_inchild))); status = ewaitfor(pid); t1 = times(&tms); SIGCHK(); - printstatus(pid, status); tms.tms_cutime += ticks / 20; tms.tms_cstime += ticks / 20; @@ -378,7 +375,6 @@ PRIM(time) { } status = ewaitfor(pid); SIGCHK(); - printstatus(pid, status); RefEnd(lp); return mklist(mkstr(mkstatus(status)), NULL); diff --git a/proc.c b/proc.c index 4e3e328e..6f560b95 100644 --- a/proc.c +++ b/proc.c @@ -17,7 +17,6 @@ Boolean hasforked = FALSE; typedef struct Proc Proc; struct Proc { int pid; - Boolean background; Proc *next, *prev; }; @@ -30,22 +29,21 @@ static pid_t tcpgid0; #endif /* mkproc -- create a Proc structure */ -extern Proc *mkproc(int pid, Boolean background) { +extern Proc *mkproc(int pid) { Proc *proc = ealloc(sizeof (Proc)); proc->next = proclist; proc->pid = pid; - proc->background = background; proc->prev = NULL; return proc; } /* efork -- fork (if necessary) and clean up as appropriate */ -extern int efork(Boolean parent, Boolean background) { +extern int efork(Boolean parent) { if (parent) { int pid = fork(); switch (pid) { default: { /* parent */ - Proc *proc = mkproc(pid, background); + Proc *proc = mkproc(pid); if (proclist != NULL) proclist->prev = proc; proclist = proc; @@ -208,8 +206,7 @@ extern int ewait(int pidarg, int opts, void *rusage) { if (deadpid == 0) /* dowait(EWNOHANG) returned nothing */ return -1; /* FIXME: replace this with a better value! */ proc = reap(deadpid); - if (proc->background) - printstatus(proc->pid, status); + printstatus(proc->pid, status); efree(proc); return status; } @@ -219,11 +216,10 @@ extern int ewait(int pidarg, int opts, void *rusage) { PRIM(apids) { Proc *p; Ref(List *, lp, NULL); - for (p = proclist; p != NULL; p = p->next) - if (p->background) { - Term *t = mkstr(str("%d", p->pid)); - lp = mklist(t, lp); - } + for (p = proclist; p != NULL; p = p->next) { + Term *t = mkstr(str("%d", p->pid)); + lp = mklist(t, lp); + } /* TODO: sort the return value, but by number? */ RefReturn(lp); } From 6a96d1a9b39a71f5ae75b57facffd8700f4fb11c Mon Sep 17 00:00:00 2001 From: jpco Date: Sat, 30 Nov 2024 18:15:50 -0800 Subject: [PATCH 6/9] %print-status => %echo-status --- initial.es | 10 +++++----- status.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/initial.es b/initial.es index fe785b39..05ef5d04 100644 --- a/initial.es +++ b/initial.es @@ -578,12 +578,12 @@ fn %pathsearch name { access -n $name -1e -xf $path } if {~ <=$&primitives execfailure} {fn-%exec-failure = $&execfailure} -# The %print-status hook is used to print any potentially interesting +# The %echo-status hook is used to print any potentially interesting # status from an exec()ed binary. -fn %print-status pid did status { +fn %echo-status pid did status { if {~ $did signaled && !~ $status (sigint sigpipe)} { - let (msg = <={if {$print-status-pid} {result $pid^': '} {result ''}}) { + let (msg = <={if {$echo-status-pid} {result $pid^': '} {result ''}}) { msg = $msg^<={$&sigmessage $status} if {~ $status *+core} { msg = $msg^'--core dumped' @@ -593,10 +593,10 @@ fn %print-status pid did status { } } -print-status-pid = false +echo-status-pid = false fn wait { - local (print-status-pid = true) $&wait $* + local (echo-status-pid = true) $&wait $* } # diff --git a/status.c b/status.c index c72c552b..2ddca3ce 100644 --- a/status.c +++ b/status.c @@ -65,7 +65,7 @@ extern char *mkstatus(int status) { /* printstatus -- print the status if we should */ extern void printstatus(int pid, int status) { - Ref(List *, fn, varlookup("fn-%print-status", NULL)); + Ref(List *, fn, varlookup("fn-%echo-status", NULL)); Ref(List *, list, NULL); if (fn != NULL) { gcdisable(); From b2609421e1e056fa1fbb0512fbcd4bc0547f5b6f Mon Sep 17 00:00:00 2001 From: jpco Date: Sat, 30 Nov 2024 21:35:26 -0800 Subject: [PATCH 7/9] Add new stuff to man page --- doc/es.1 | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/doc/es.1 b/doc/es.1 index 99690bd4..d8692ce3 100644 --- a/doc/es.1 +++ b/doc/es.1 @@ -1856,7 +1856,7 @@ as input to and executes its contents. The options are a subset of the invocation options for the shell (see below). .TP -.Cr "access \fR[\fP-n \fIname\fP\fR]\fP \fR[\fP-1e\fR]\fP \fR[\fP-rwx\fR]\fP \fR[\fP-fdcblsp\fR]\fP \fIpath ...\fP" +.Cr "access \fR[\fP-n \fIname\fP\fR]\fP \fR[\fP-1e\fR]\fP \fR[\fP-rwx\fR]\fP \fR[\fP-fdcblsp\fR]\fP \fIpath ...\fP" Tests if the named paths are accessible according to the options presented. Normally, .Cr access @@ -2192,7 +2192,7 @@ are specified, .Cr \-e is used. .TP -.Cr "wait \fI\fR[\fPpid\fR]" +.Cr "wait \fR[\fP-n\fR]\fP \fI\fR[\fPpid\fR]" Waits for the specified .IR pid , which must have been started by @@ -2200,6 +2200,11 @@ which must have been started by If no .I pid is specified, waits for any child process to exit. +If +.Cr \-n +is specified and the process(es) to be waited for is (are) not ready +at call time, returns immediately instead of blocking or throwing an +error. .TP .Cr "whatis \fIprogram ...\fP" For each named @@ -2293,6 +2298,19 @@ copied (via to file descriptor .IR newfd . .TP +.Cr "%echo-status \fIpid did status\fP" +Inspects the exit +.I status +of an exited (and waited-for) process +.IR pid , +where +.I did +indicates if the process +.Cr exited +or was +.Cr signaled , +and prints any interesting condition. +.TP .Cr "%eval-noprint \fIcmd\fP" Run the command. (Passed as the argument to @@ -2740,7 +2758,7 @@ variable, which signals to the library how much of the history file should be read into the in-memory history log. .PP -Several primitives are not directly associated with other function. +Several primitives are not directly associated with other functions. They are: .TP .Cr "$&collect" @@ -2750,7 +2768,7 @@ The garbage collector in runs rather frequently; there should be no reason for a user to issue this command. .TP -.Cr "$&noreturn \fIlambda args ...\fP" +.Cr "$&noreturn \fIlambda args ..." Call the .IR lambda , but in such a way that it does not catch the @@ -2765,6 +2783,11 @@ and .Cr "&&" ) can be implemented as lambdas rather than primitives. .TP +.Cr "$&sigmessage" +converts a signal name such as +.Cr sigint +to a short message describing the signal, used for error reporting. +.TP .Cr "$&primitives" Returns a list of the names of es primitives. .TP From a9b179c6f9529bdff118371175533845f18b21d2 Mon Sep 17 00:00:00 2001 From: jpco Date: Tue, 3 Dec 2024 11:10:59 -0800 Subject: [PATCH 8/9] Bugfix: allow `wait -n $pid` to actually work --- proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proc.c b/proc.c index 6f560b95..8ea78fda 100644 --- a/proc.c +++ b/proc.c @@ -232,7 +232,7 @@ PRIM(wait) { lp = lp->next; } if (lp != NULL) { - pid = atoi(getstr(list->term)); + pid = atoi(getstr(lp->term)); if (pid <= 0) { fail("$&wait", "wait: %d: bad pid", pid); NOTREACHED; From 29ce32ac0c77bf93a16c8fe7b5648d0f13ecb3d5 Mon Sep 17 00:00:00 2001 From: jpco Date: Mon, 3 Mar 2025 21:09:55 -0800 Subject: [PATCH 9/9] Cleanup --- proc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/proc.c b/proc.c index 253a4f2a..c60ed650 100644 --- a/proc.c +++ b/proc.c @@ -117,7 +117,7 @@ extern Noreturn esexit(int code) { } #endif -/* dowait -- a waitpid wrapper that gets rusage and interfaces with signals */ +/* dowait -- a waitpid wrapper that interfaces with signals */ static int dowait(int pid, int opts, int *statusp) { int n; interrupted = FALSE; @@ -171,8 +171,8 @@ extern int ewait(int pidarg, int opts) { #if JOB_PROTECT tctakepgrp(); #endif - if (deadpid == 0) /* dowait(EWNOHANG) returned nothing */ - return -1; /* FIXME: replace this with a better value! */ + if (deadpid == 0) /* dowait(EWNOHANG) returned nothing */ + return -1; proc = reap(deadpid); printstatus(proc->pid, status); efree(proc); @@ -213,7 +213,7 @@ PRIM(wait) { } RefEnd(lp); status = ewait(pid, opts); - if (status == -1) /* FIXME: this will be a better value soon */ + if (status == -1) /* ewait got no exited processes */ return NULL; return mklist(mkstr(mkstatus(status)), NULL); }