From b64156e15fc72e8bfcd1149fbdb43a0561f4233e Mon Sep 17 00:00:00 2001 From: jpco Date: Sun, 8 Dec 2024 09:35:54 -0800 Subject: [PATCH 1/4] Reset readline screen size each call. --- input.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/input.c b/input.c index 65306c4..f187766 100644 --- a/input.c +++ b/input.c @@ -245,6 +245,8 @@ static char *callreadline(char *prompt0) { rl_reset_terminal(NULL); resetterminal = FALSE; } + if (RL_ISSTATE(RL_STATE_INITIALIZED)) + rl_reset_screen_size(); interrupted = FALSE; if (!setjmp(slowlabel)) { slow = TRUE; From a6f823f661726c72a213d9efe166f1464e6e4050 Mon Sep 17 00:00:00 2001 From: jpco Date: Sun, 8 Dec 2024 09:47:43 -0800 Subject: [PATCH 2/4] Fix $&time by always collecting rusage --- proc.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/proc.c b/proc.c index c12da2e..6e4ebe6 100644 --- a/proc.c +++ b/proc.c @@ -148,19 +148,19 @@ static int dowait(int pid, int *statusp, void UNUSED *rusagep) { slow = TRUE; n = interrupted ? -2 : waitpid(pid, statusp, 0); -#if HAVE_GETRUSAGE - if (rusagep != NULL) { - struct rusage *rusage = (struct rusage *)rusagep; - if (getrusage(RUSAGE_CHILDREN, &ru_new) == -1) - fail("es:ewait", "getrusage: %s", esstrerror(errno)); - timesub(&ru_new.ru_utime, &ru_saved.ru_utime, &rusage->ru_utime); - timesub(&ru_new.ru_stime, &ru_saved.ru_stime, &rusage->ru_stime); - ru_saved = ru_new; - } -#endif } else n = -2; slow = FALSE; +#if HAVE_GETRUSAGE + if (getrusage(RUSAGE_CHILDREN, &ru_new) == -1) + fail("es:ewait", "getrusage: %s", esstrerror(errno)); + if (rusagep != NULL) { + struct rusage *rusage = (struct rusage *)rusagep; + timesub(&ru_new.ru_utime, &ru_saved.ru_utime, &rusage->ru_utime); + timesub(&ru_new.ru_stime, &ru_saved.ru_stime, &rusage->ru_stime); + } + ru_saved = ru_new; +#endif if (n == -2) { errno = EINTR; n = -1; From f5c6d505b49f9fcd1d4ee6e61ed9325094b3252d Mon Sep 17 00:00:00 2001 From: jpco Date: Sun, 8 Dec 2024 10:28:21 -0800 Subject: [PATCH 3/4] Move getrusage() calls from dowait() to $&time --- es.h | 4 ++-- prim-sys.c | 30 ++++++++++++++++++++++++++---- proc.c | 44 +++++--------------------------------------- 3 files changed, 33 insertions(+), 45 deletions(-) diff --git a/es.h b/es.h index ea21857..472e88e 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, Boolean interruptible); +#define ewaitfor(pid) ewait(pid, FALSE) #if JOB_PROTECT extern void tcreturnpgrp(void); diff --git a/prim-sys.c b/prim-sys.c index 0506df8..caa8293 100644 --- a/prim-sys.c +++ b/prim-sys.c @@ -289,30 +289,52 @@ PRIM(limit) { #endif /* BSD_LIMITS */ #if BUILTIN_TIME +#if HAVE_GETRUSAGE +/* This function is provided as timersub(3) on some systems, but it's simple enough + * to do ourselves. */ +static void timesub(struct timeval *a, struct timeval *b, struct timeval *res) { + res->tv_sec = a->tv_sec - b->tv_sec; + res->tv_usec = a->tv_usec - b->tv_usec; + if (res->tv_usec < 0) { + res->tv_sec -= 1; + res->tv_usec += 1000000; + } +} +#endif + PRIM(time) { #if HAVE_GETRUSAGE int pid, status; time_t t0, t1; - struct rusage r; + struct rusage ru_prev, ru_new, ru_diff; Ref(List *, lp, list); + if (getrusage(RUSAGE_CHILDREN, &ru_prev) == -1) + fail("es:ewait", "getrusage: %s", esstrerror(errno)); + gc(); /* do a garbage collection first to ensure reproducible results */ t0 = time(NULL); pid = efork(TRUE, FALSE); if (pid == 0) esexit(exitstatus(eval(lp, NULL, evalflags | eval_inchild))); - status = ewait(pid, FALSE, &r); + status = ewait(pid, FALSE); t1 = time(NULL); SIGCHK(); printstatus(0, status); + if (getrusage(RUSAGE_CHILDREN, &ru_new) == -1) + fail("es:ewait", "getrusage: %s", esstrerror(errno)); + + timesub(&ru_new.ru_utime, &ru_prev.ru_utime, &ru_diff.ru_utime); + timesub(&ru_new.ru_stime, &ru_prev.ru_stime, &ru_diff.ru_stime); + eprint( "%6ldr %5ld.%ldu %5ld.%lds\t%L\n", t1 - t0, - r.ru_utime.tv_sec, (long) (r.ru_utime.tv_usec / 100000), - r.ru_stime.tv_sec, (long) (r.ru_stime.tv_usec / 100000), + ru_diff.ru_utime.tv_sec, (long) (ru_diff.ru_utime.tv_usec / 100000), + ru_diff.ru_stime.tv_sec, (long) (ru_diff.ru_stime.tv_usec / 100000), lp, " " ); diff --git a/proc.c b/proc.c index 6e4ebe6..d8c9fac 100644 --- a/proc.c +++ b/proc.c @@ -2,13 +2,6 @@ #include "es.h" -/* TODO: the rusage code for the time builtin really needs to be cleaned up */ - -#if HAVE_GETRUSAGE -#include -#include -#endif - Boolean hasforked = FALSE; typedef struct Proc Proc; @@ -123,26 +116,9 @@ extern Noreturn esexit(int code) { } #endif -#if HAVE_GETRUSAGE -/* This function is provided as timersub(3) on some systems, but it's simple enough - * to do ourselves. */ -static void timesub(struct timeval *a, struct timeval *b, struct timeval *res) { - res->tv_sec = a->tv_sec - b->tv_sec; - res->tv_usec = a->tv_usec - b->tv_usec; - if (res->tv_usec < 0) { - res->tv_sec -= 1; - res->tv_usec += 1000000; - } -} -#endif - -/* dowait -- a waitpid wrapper that gets rusage and interfaces with signals */ -static int dowait(int pid, int *statusp, void UNUSED *rusagep) { +/* dowait -- a waitpid wrapper that interfaces with signals */ +static int dowait(int pid, int *statusp) { int n; -#if HAVE_GETRUSAGE - static struct rusage ru_saved; - struct rusage ru_new; -#endif interrupted = FALSE; if (!setjmp(slowlabel)) { slow = TRUE; @@ -151,16 +127,6 @@ static int dowait(int pid, int *statusp, void UNUSED *rusagep) { } else n = -2; slow = FALSE; -#if HAVE_GETRUSAGE - if (getrusage(RUSAGE_CHILDREN, &ru_new) == -1) - fail("es:ewait", "getrusage: %s", esstrerror(errno)); - if (rusagep != NULL) { - struct rusage *rusage = (struct rusage *)rusagep; - timesub(&ru_new.ru_utime, &ru_saved.ru_utime, &rusage->ru_utime); - timesub(&ru_new.ru_stime, &ru_saved.ru_stime, &rusage->ru_stime); - } - ru_saved = ru_new; -#endif if (n == -2) { errno = EINTR; n = -1; @@ -185,10 +151,10 @@ 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, Boolean interruptible) { int deadpid, status; Proc *proc; - while ((deadpid = dowait(pidarg, &status, rusage)) == -1) { + while ((deadpid = dowait(pidarg, &status)) == -1) { if (errno == ECHILD && pidarg > 0) fail("es:ewait", "wait: %d is not a child of this shell", pidarg); else if (errno != EINTR) @@ -234,7 +200,7 @@ PRIM(wait) { fail("$&wait", "usage: wait [pid]"); NOTREACHED; } - return mklist(mkstr(mkstatus(ewait(pid, TRUE, NULL))), NULL); + return mklist(mkstr(mkstatus(ewait(pid, TRUE))), NULL); } extern Dict *initprims_proc(Dict *primdict) { From 9aacd80a853ebd0f572ae03e7e8e5d02b9d23b77 Mon Sep 17 00:00:00 2001 From: jpco Date: Mon, 9 Dec 2024 21:13:23 -0800 Subject: [PATCH 4/4] Error handling for getrusage() is not very useful --- prim-sys.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/prim-sys.c b/prim-sys.c index caa8293..c0b4f98 100644 --- a/prim-sys.c +++ b/prim-sys.c @@ -311,9 +311,7 @@ PRIM(time) { Ref(List *, lp, list); - if (getrusage(RUSAGE_CHILDREN, &ru_prev) == -1) - fail("es:ewait", "getrusage: %s", esstrerror(errno)); - + getrusage(RUSAGE_CHILDREN, &ru_prev); gc(); /* do a garbage collection first to ensure reproducible results */ t0 = time(NULL); pid = efork(TRUE, FALSE); @@ -324,9 +322,7 @@ PRIM(time) { SIGCHK(); printstatus(0, status); - if (getrusage(RUSAGE_CHILDREN, &ru_new) == -1) - fail("es:ewait", "getrusage: %s", esstrerror(errno)); - + getrusage(RUSAGE_CHILDREN, &ru_new); timesub(&ru_new.ru_utime, &ru_prev.ru_utime, &ru_diff.ru_utime); timesub(&ru_new.ru_stime, &ru_prev.ru_stime, &ru_diff.ru_stime);