Skip to content

Commit

Permalink
Merge pull request #153 from jpco/bugfixes
Browse files Browse the repository at this point in the history
Fixes for recently-introduced readline and `$&time` bugs
  • Loading branch information
jpco authored Dec 13, 2024
2 parents 95902bc + 9aacd80 commit 4bfee21
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 45 deletions.
4 changes: 2 additions & 2 deletions es.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions input.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
26 changes: 22 additions & 4 deletions prim-sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -289,30 +289,48 @@ 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);

getrusage(RUSAGE_CHILDREN, &ru_prev);
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);

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);

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, " "
);

Expand Down
44 changes: 5 additions & 39 deletions proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 <sys/time.h>
#include <sys/resource.h>
#endif

Boolean hasforked = FALSE;

typedef struct Proc Proc;
Expand Down Expand Up @@ -123,41 +116,14 @@ 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;
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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit 4bfee21

Please sign in to comment.