summaryrefslogtreecommitdiff
path: root/Src
diff options
context:
space:
mode:
Diffstat (limited to 'Src')
-rw-r--r--Src/Modules/zftp.c4
-rw-r--r--Src/Modules/zprof.c19
-rw-r--r--Src/compat.c12
-rw-r--r--Src/exec.c21
-rw-r--r--Src/hist.c6
-rw-r--r--Src/init.c7
-rw-r--r--Src/jobs.c78
-rw-r--r--Src/params.c38
-rw-r--r--Src/prompt.c2
-rw-r--r--Src/signals.c3
-rw-r--r--Src/utils.c25
-rw-r--r--Src/zsh.h4
12 files changed, 135 insertions, 84 deletions
diff --git a/Src/Modules/zftp.c b/Src/Modules/zftp.c
index b60e5bf31..230ad86f6 100644
--- a/Src/Modules/zftp.c
+++ b/Src/Modules/zftp.c
@@ -397,7 +397,7 @@ zfalarm(int tmout)
signal(SIGALRM, zfhandler);
oalremain = alarm(tmout);
if (oalremain)
- oaltime = time(NULL);
+ oaltime = zmonotime(NULL);
/*
* We'll leave sigtrapped, sigfuncs and TRAPXXX as they are; since the
* shell's handler doesn't get the signal, they don't matter.
@@ -431,7 +431,7 @@ zfunalarm(void)
* I love the way alarm() uses unsigned int while time_t
* is probably something completely different.
*/
- unsigned int tdiff = time(NULL) - oaltime;
+ time_t tdiff = zmonotime(NULL) - oaltime;
alarm(oalremain < tdiff ? 1 : oalremain - tdiff);
} else
alarm(0);
diff --git a/Src/Modules/zprof.c b/Src/Modules/zprof.c
index 171a15b90..f5a50effc 100644
--- a/Src/Modules/zprof.c
+++ b/Src/Modules/zprof.c
@@ -239,8 +239,7 @@ zprof_wrapper(Eprog prog, FuncWrap w, char *name)
struct sfunc sf, *sp;
Pfunc f = NULL;
Parc a = NULL;
- struct timeval tv;
- struct timezone dummy;
+ struct timespec ts;
double prev = 0, now;
char *name_for_lookups;
@@ -278,19 +277,19 @@ zprof_wrapper(Eprog prog, FuncWrap w, char *name)
stack = &sf;
f->calls++;
- tv.tv_sec = tv.tv_usec = 0;
- gettimeofday(&tv, &dummy);
- sf.beg = prev = ((((double) tv.tv_sec) * 1000.0) +
- (((double) tv.tv_usec) / 1000.0));
+ ts.tv_sec = ts.tv_nsec = 0;
+ zgettime_monotonic_if_available(&ts);
+ sf.beg = prev = ((((double) ts.tv_sec) * 1000.0) +
+ (((double) ts.tv_nsec) / 1000000.0));
}
runshfunc(prog, w, name);
if (active) {
if (zprof_module && !(zprof_module->node.flags & MOD_UNLOAD)) {
- tv.tv_sec = tv.tv_usec = 0;
- gettimeofday(&tv, &dummy);
+ ts.tv_sec = ts.tv_nsec = 0;
+ zgettime_monotonic_if_available(&ts);
- now = ((((double) tv.tv_sec) * 1000.0) +
- (((double) tv.tv_usec) / 1000.0));
+ now = ((((double) ts.tv_sec) * 1000.0) +
+ (((double) ts.tv_nsec) / 1000000.0));
f->self += now - sf.beg;
for (sp = sf.prev; sp && sp->p != f; sp = sp->prev);
if (!sp)
diff --git a/Src/compat.c b/Src/compat.c
index 8b31ad9f4..918d98e69 100644
--- a/Src/compat.c
+++ b/Src/compat.c
@@ -136,7 +136,19 @@ zgettime_monotonic_if_available(struct timespec *ts)
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
struct timespec dts;
+
+/*
+ * On at least some versions of macOS it appears that CLOCK_MONOTONIC is not
+ * actually monotonic -- there are reports that it can go backwards.
+ * CLOCK_MONOTONIC_RAW does not have this problem. On top of that, it is faster
+ * to read and it has nanosecond precision. We could use it on other systems
+ * too, but on Linux at least it seems that CLOCK_MONOTONIC is preferred
+ */
+#if defined(__APPLE__) && defined(CLOCK_MONOTONIC_RAW)
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &dts) < 0) {
+#else
if (clock_gettime(CLOCK_MONOTONIC, &dts) < 0) {
+#endif
zwarn("unable to retrieve CLOCK_MONOTONIC time: %e", errno);
ret--;
} else {
diff --git a/Src/exec.c b/Src/exec.c
index bc07e8c39..874ff41f7 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -348,10 +348,9 @@ setlimits(char *nam)
/**/
static pid_t
-zfork(struct timeval *tv)
+zfork(struct timespec *ts)
{
pid_t pid;
- struct timezone dummy_tz;
/*
* Is anybody willing to explain this test?
@@ -360,8 +359,8 @@ zfork(struct timeval *tv)
zerr("job table full");
return -1;
}
- if (tv)
- gettimeofday(tv, &dummy_tz);
+ if (ts)
+ zgettime_monotonic_if_available(ts);
/*
* Queueing signals is necessary on Linux because fork()
* manipulates mutexes, leading to deadlock in memory
@@ -460,7 +459,7 @@ zfork(struct timeval *tv)
int list_pipe = 0, simple_pline = 0;
static pid_t list_pipe_pid;
-static struct timeval list_pipe_start;
+static struct timespec list_pipe_start;
static int nowait, pline_level = 0;
static int list_pipe_child = 0, list_pipe_job;
static char list_pipe_text[JOBTEXTSIZE];
@@ -1863,7 +1862,7 @@ execpline(Estate state, wordcode slcode, int how, int last1)
(jobtab[list_pipe_job].stat & STAT_STOPPED)))) {
pid_t pid = 0;
int synch[2];
- struct timeval bgtime;
+ struct timespec bgtime;
/*
* A pipeline with the shell handling the right
@@ -2284,7 +2283,7 @@ closemn(struct multio **mfds, int fd, int type)
char buf[TCBUFSIZE];
int len, i;
pid_t pid;
- struct timeval bgtime;
+ struct timespec bgtime;
/*
* We need to block SIGCHLD in case the process
@@ -2829,7 +2828,7 @@ execcmd_fork(Estate state, int how, int type, Wordcode varspc,
pid_t pid;
int synch[2], flags;
struct entersubsh_ret esret;
- struct timeval bgtime;
+ struct timespec bgtime;
child_block();
esret.gleader = -1;
@@ -2947,7 +2946,7 @@ execcmd_exec(Estate state, Execcmd_params eparams,
* for the "time" keyword
*/
child_times_t shti, chti;
- struct timeval then;
+ struct timespec then;
if (how & Z_TIMED)
shelltime(&shti, &chti, &then, 0);
@@ -5060,7 +5059,7 @@ getproc(char *cmd, char **eptr)
int out = *cmd == Inang;
char *pnam;
pid_t pid;
- struct timeval bgtime;
+ struct timespec bgtime;
#ifndef PATH_DEV_FD
int fd;
@@ -5149,7 +5148,7 @@ getpipe(char *cmd, int nullexec)
Eprog prog;
int pipes[2], out = *cmd == Inang;
pid_t pid;
- struct timeval bgtime;
+ struct timespec bgtime;
char *ends;
if (!(prog = parsecmd(cmd, &ends)))
diff --git a/Src/hist.c b/Src/hist.c
index 1a00c30ed..d0960a284 100644
--- a/Src/hist.c
+++ b/Src/hist.c
@@ -2891,9 +2891,9 @@ flockhistfile(char *fn, int keep_trying)
/*
* Timeout is ten seconds.
*/
- end_time = time(NULL) + (time_t)10;
+ end_time = zmonotime(NULL) + (time_t)10;
while (fcntl(flock_fd, F_SETLKW, &lck) == -1) {
- if (!keep_trying || time(NULL) >= end_time ||
+ if (!keep_trying || zmonotime(NULL) >= end_time ||
/*
* Randomise wait to minimise clashes with shells exiting at
* the same time.
@@ -3137,7 +3137,7 @@ static int lockhistct;
static int
checklocktime(char *lockfile, long *sleep_usp, time_t then)
{
- time_t now = time(NULL);
+ time_t now = zmonotime(NULL);
if (now + 10 < then) {
/* File is more than 10 seconds in the future? */
diff --git a/Src/init.c b/Src/init.c
index 61f759ded..378aee348 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -1022,7 +1022,6 @@ setupvals(char *cmd, char *runscript, char *zsh_name)
#ifdef USE_GETPWUID
struct passwd *pswd;
#endif
- struct timezone dummy_tz;
char *ptr;
int i, j;
#if defined(SITEFPATH_DIR) || defined(FPATH_DIR) || defined (ADDITIONAL_FPATH) || defined(FIXED_FPATH_DIR)
@@ -1109,8 +1108,8 @@ setupvals(char *cmd, char *runscript, char *zsh_name)
hatchar = '^';
termflags = TERM_UNKNOWN;
curjob = prevjob = coprocin = coprocout = -1;
- gettimeofday(&shtimer, &dummy_tz); /* init $SECONDS */
- srand((unsigned int)(shtimer.tv_sec + shtimer.tv_usec)); /* seed $RANDOM */
+ zgettime_monotonic_if_available(&shtimer); /* init $SECONDS */
+ srand((unsigned int)(shtimer.tv_sec + shtimer.tv_nsec)); /* seed $RANDOM */
/* Set default path */
path = (char **) zalloc(sizeof(*path) * 5);
@@ -1297,7 +1296,7 @@ setupvals(char *cmd, char *runscript, char *zsh_name)
#endif
breaks = loops = 0;
- lastmailcheck = time(NULL);
+ lastmailcheck = zmonotime(NULL);
locallevel = sourcelevel = 0;
sfcontext = SFC_NONE;
trap_return = 0;
diff --git a/Src/jobs.c b/Src/jobs.c
index 39c664388..ad14f6312 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -136,7 +136,7 @@ int numpipestats, pipestats[MAX_PIPESTATS];
/**/
static struct timeval *
-dtime(struct timeval *dt, struct timeval *t1, struct timeval *t2)
+dtime_tv(struct timeval *dt, struct timeval *t1, struct timeval *t2)
{
dt->tv_sec = t2->tv_sec - t1->tv_sec;
dt->tv_usec = t2->tv_usec - t1->tv_usec;
@@ -147,6 +147,21 @@ dtime(struct timeval *dt, struct timeval *t1, struct timeval *t2)
return dt;
}
+/* As above, but with timespecs */
+
+/**/
+static struct timespec *
+dtime_ts(struct timespec *dt, struct timespec *t1, struct timespec *t2)
+{
+ dt->tv_sec = t2->tv_sec - t1->tv_sec;
+ dt->tv_nsec = t2->tv_nsec - t1->tv_nsec;
+ if (dt->tv_nsec < 0) {
+ dt->tv_nsec += 1000000000.0;
+ dt->tv_sec -= 1.0;
+ }
+ return dt;
+}
+
/* change job table entry from stopped to running */
/**/
@@ -349,7 +364,6 @@ get_usage(void)
void
update_process(Process pn, int status)
{
- struct timezone dummy_tz;
#ifdef HAVE_GETRUSAGE
struct timeval childs = child_usage.ru_stime;
struct timeval childu = child_usage.ru_utime;
@@ -360,12 +374,12 @@ update_process(Process pn, int status)
/* get time-accounting info */
get_usage();
- gettimeofday(&pn->endtime, &dummy_tz); /* record time process exited */
+ zgettime_monotonic_if_available(&pn->endtime); /* record time process exited */
pn->status = status; /* save the status returned by WAIT */
#ifdef HAVE_GETRUSAGE
- dtime(&pn->ti.ru_stime, &childs, &child_usage.ru_stime);
- dtime(&pn->ti.ru_utime, &childu, &child_usage.ru_utime);
+ dtime_tv(&pn->ti.ru_stime, &childs, &child_usage.ru_stime);
+ dtime_tv(&pn->ti.ru_utime, &childu, &child_usage.ru_utime);
#else
pn->ti.st = shtms.tms_cstime - childs; /* compute process system space time */
pn->ti.ut = shtms.tms_cutime - childu; /* compute process user space time */
@@ -753,7 +767,7 @@ printhhmmss(double secs)
}
static void
-printtime(struct timeval *real, child_times_t *ti, char *desc)
+printtime(struct timespec *real, child_times_t *ti, char *desc)
{
char *s;
double elapsed_time, user_time, system_time;
@@ -774,21 +788,21 @@ printtime(struct timeval *real, child_times_t *ti, char *desc)
}
/* go ahead and compute these, since almost every TIMEFMT will have them */
- elapsed_time = real->tv_sec + real->tv_usec / 1000000.0;
+ elapsed_time = real->tv_sec + real->tv_nsec / 1000000000.0;
#ifdef HAVE_GETRUSAGE
user_time = ti->ru_utime.tv_sec + ti->ru_utime.tv_usec / 1000000.0;
system_time = ti->ru_stime.tv_sec + ti->ru_stime.tv_usec / 1000000.0;
total_time = user_time + system_time;
percent = 100.0 * total_time
- / (real->tv_sec + real->tv_usec / 1000000.0);
+ / (real->tv_sec + real->tv_nsec / 1000000000.0);
#else
{
long clktck = get_clktck();
user_time = ti->ut / (double) clktck;
system_time = ti->st / (double) clktck;
percent = 100.0 * (ti->ut + ti->st)
- / (clktck * real->tv_sec + clktck * real->tv_usec / 1000000.0);
+ / (clktck * real->tv_sec + clktck * real->tv_nsec / 1000000000.0);
}
#endif
@@ -844,6 +858,23 @@ printtime(struct timeval *real, child_times_t *ti, char *desc)
break;
}
break;
+ case 'n':
+ switch (*++s) {
+ case 'E':
+ fprintf(stderr, "%0.fns", elapsed_time * 1000000000.0);
+ break;
+ case 'U':
+ fprintf(stderr, "%0.fns", user_time * 1000000000.0);
+ break;
+ case 'S':
+ fprintf(stderr, "%0.fns", system_time * 1000000000.0);
+ break;
+ default:
+ fprintf(stderr, "%%n");
+ s--;
+ break;
+ }
+ break;
case '*':
switch (*++s) {
case 'E':
@@ -991,12 +1022,12 @@ static void
dumptime(Job jn)
{
Process pn;
- struct timeval dtimeval;
+ struct timespec dtimespec;
if (!jn->procs)
return;
for (pn = jn->procs; pn; pn = pn->next)
- printtime(dtime(&dtimeval, &pn->bgtime, &pn->endtime), &pn->ti,
+ printtime(dtime_ts(&dtimespec, &pn->bgtime, &pn->endtime), &pn->ti,
pn->text);
}
@@ -1506,7 +1537,7 @@ deletejob(Job jn, int disowning)
/**/
void
-addproc(pid_t pid, char *text, int aux, struct timeval *bgtime,
+addproc(pid_t pid, char *text, int aux, struct timespec *bgtime,
int gleader, int list_pipe_job_used)
{
Process pn, *pnlist;
@@ -1894,16 +1925,15 @@ spawnjob(void)
/**/
void
-shelltime(child_times_t *shell, child_times_t *kids, struct timeval *then, int delta)
+shelltime(child_times_t *shell, child_times_t *kids, struct timespec *then, int delta)
{
- struct timezone dummy_tz;
- struct timeval dtimeval, now;
+ struct timespec dtimespec, now;
child_times_t ti;
#ifndef HAVE_GETRUSAGE
struct tms buf;
#endif
- gettimeofday(&now, &dummy_tz);
+ zgettime_monotonic_if_available(&now);
#ifdef HAVE_GETRUSAGE
getrusage(RUSAGE_SELF, &ti);
@@ -1916,8 +1946,8 @@ shelltime(child_times_t *shell, child_times_t *kids, struct timeval *then, int d
if (shell) {
if (delta) {
#ifdef HAVE_GETRUSAGE
- dtime(&ti.ru_utime, &shell->ru_utime, &ti.ru_utime);
- dtime(&ti.ru_stime, &shell->ru_stime, &ti.ru_stime);
+ dtime_tv(&ti.ru_utime, &shell->ru_utime, &ti.ru_utime);
+ dtime_tv(&ti.ru_stime, &shell->ru_stime, &ti.ru_stime);
#else
ti.ut -= shell->ut;
ti.st -= shell->st;
@@ -1926,15 +1956,15 @@ shelltime(child_times_t *shell, child_times_t *kids, struct timeval *then, int d
*shell = ti;
}
if (delta)
- dtime(&dtimeval, then, &now);
+ dtime_ts(&dtimespec, then, &now);
else {
if (then)
*then = now;
- dtime(&dtimeval, &shtimer, &now);
+ dtime_ts(&dtimespec, &shtimer, &now);
}
if (!delta == !shell)
- printtime(&dtimeval, &ti, "shell");
+ printtime(&dtimespec, &ti, "shell");
#ifdef HAVE_GETRUSAGE
getrusage(RUSAGE_CHILDREN, &ti);
@@ -1945,8 +1975,8 @@ shelltime(child_times_t *shell, child_times_t *kids, struct timeval *then, int d
if (kids) {
if (delta) {
#ifdef HAVE_GETRUSAGE
- dtime(&ti.ru_utime, &kids->ru_utime, &ti.ru_utime);
- dtime(&ti.ru_stime, &kids->ru_stime, &ti.ru_stime);
+ dtime_tv(&ti.ru_utime, &kids->ru_utime, &ti.ru_utime);
+ dtime_tv(&ti.ru_stime, &kids->ru_stime, &ti.ru_stime);
#else
ti.ut -= shell->ut;
ti.st -= shell->st;
@@ -1955,7 +1985,7 @@ shelltime(child_times_t *shell, child_times_t *kids, struct timeval *then, int d
*kids = ti;
}
if (!delta == !kids)
- printtime(&dtimeval, &ti, "children");
+ printtime(&dtimespec, &ti, "children");
}
/* see if jobs need printing */
diff --git a/Src/params.c b/Src/params.c
index 6f137585b..d1c06b893 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -137,11 +137,11 @@ unsigned char hatchar, hashchar;
unsigned char keyboardhackchar = '\0';
/* $SECONDS = now.tv_sec - shtimer.tv_sec
- * + (now.tv_usec - shtimer.tv_usec) / 1000000.0
+ * + (now.tv_nsec - shtimer.tv_nsec) / 1000000000.0
* (rounded to an integer if the parameter is not set to float) */
/**/
-struct timeval shtimer;
+struct timespec shtimer;
/* 0 if this $TERM setup is usable, otherwise it contains TERM_* flags */
@@ -4496,13 +4496,12 @@ randomsetfn(UNUSED(Param pm), zlong v)
zlong
intsecondsgetfn(UNUSED(Param pm))
{
- struct timeval now;
- struct timezone dummy_tz;
+ struct timespec now;
- gettimeofday(&now, &dummy_tz);
+ zgettime_monotonic_if_available(&now);
return (zlong)(now.tv_sec - shtimer.tv_sec -
- (now.tv_usec < shtimer.tv_usec ? 1 : 0));
+ (now.tv_nsec < shtimer.tv_nsec ? 1 : 0));
}
/* Function to set value of special parameter `SECONDS' */
@@ -4511,48 +4510,47 @@ intsecondsgetfn(UNUSED(Param pm))
void
intsecondssetfn(UNUSED(Param pm), zlong x)
{
- struct timeval now;
- struct timezone dummy_tz;
+ struct timespec now;
zlong diff;
- gettimeofday(&now, &dummy_tz);
+ zgettime_monotonic_if_available(&now);
+
diff = (zlong)now.tv_sec - x;
shtimer.tv_sec = diff;
if ((zlong)shtimer.tv_sec != diff)
zwarn("SECONDS truncated on assignment");
- shtimer.tv_usec = now.tv_usec;
+ shtimer.tv_nsec = now.tv_nsec;
}
/**/
double
floatsecondsgetfn(UNUSED(Param pm))
{
- struct timeval now;
- struct timezone dummy_tz;
+ struct timespec now;
- gettimeofday(&now, &dummy_tz);
+ zgettime_monotonic_if_available(&now);
return (double)(now.tv_sec - shtimer.tv_sec) +
- (double)(now.tv_usec - shtimer.tv_usec) / 1000000.0;
+ (double)(now.tv_nsec - shtimer.tv_nsec) / 1000000000.0;
}
/**/
void
floatsecondssetfn(UNUSED(Param pm), double x)
{
- struct timeval now;
- struct timezone dummy_tz;
+ struct timespec now;
+
+ zgettime_monotonic_if_available(&now);
- gettimeofday(&now, &dummy_tz);
shtimer.tv_sec = now.tv_sec - (zlong)x;
- shtimer.tv_usec = now.tv_usec - (zlong)((x - (zlong)x) * 1000000.0);
+ shtimer.tv_nsec = now.tv_nsec - (zlong)((x - (zlong)x) * 1000000000.0);
}
/**/
double
getrawseconds(void)
{
- return (double)shtimer.tv_sec + (double)shtimer.tv_usec / 1000000.0;
+ return (double)shtimer.tv_sec + (double)shtimer.tv_nsec / 1000000000.0;
}
/**/
@@ -4560,7 +4558,7 @@ void
setrawseconds(double x)
{
shtimer.tv_sec = (zlong)x;
- shtimer.tv_usec = (zlong)((x - (zlong)x) * 1000000.0);
+ shtimer.tv_nsec = (zlong)((x - (zlong)x) * 1000000000.0);
}
/**/
diff --git a/Src/prompt.c b/Src/prompt.c
index e10b05215..f36aba9d3 100644
--- a/Src/prompt.c
+++ b/Src/prompt.c
@@ -469,7 +469,7 @@ putpromptchar(int doprint, int endchar)
test = 1;
break;
case 'S':
- if (time(NULL) - shtimer.tv_sec >= arg)
+ if (zmonotime(NULL) - shtimer.tv_sec >= arg)
test = 1;
break;
case 'v':
diff --git a/Src/signals.c b/Src/signals.c
index 86f1a49f6..de42f302d 100644
--- a/Src/signals.c
+++ b/Src/signals.c
@@ -342,8 +342,7 @@ wait_for_processes(void)
zwarn("job can't be suspended");
} else {
#if defined(HAVE_WAIT3) && defined(HAVE_GETRUSAGE)
- struct timezone dummy_tz;
- gettimeofday(&pn->endtime, &dummy_tz);
+ zgettime_monotonic_if_available(&pn->endtime);
#ifdef WIFCONTINUED
if (WIFCONTINUED(status))
pn->status = SP_RUNNING;
diff --git a/Src/utils.c b/Src/utils.c
index ce4e875fd..5c91dfcda 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -1570,14 +1570,14 @@ preprompt(void)
/* If 1) the parameter PERIOD exists, 2) a hook function for *
* "periodic" exists, 3) it's been greater than PERIOD since we *
* executed any such hook, then execute it now. */
- if (period && ((zlong)time(NULL) > (zlong)lastperiodic + period) &&
+ if (period && ((zlong)zmonotime(NULL) > (zlong)lastperiodic + period) &&
!callhookfunc("periodic", NULL, 1, NULL))
- lastperiodic = time(NULL);
+ lastperiodic = zmonotime(NULL);
if (errflag)
return;
/* Check mail */
- currentmailcheck = time(NULL);
+ currentmailcheck = zmonotime(NULL);
if (mailcheck &&
(zlong) difftime(currentmailcheck, lastmailcheck) > mailcheck) {
char *mailfile;
@@ -2761,6 +2761,19 @@ timespec_diff_us(const struct timespec *t1, const struct timespec *t2)
return (reverse ? LONG_MIN : LONG_MAX);
}
+/* Like time(), but uses the monotonic clock */
+
+/**/
+mod_export int
+zmonotime(time_t *tloc)
+{
+ struct timespec ts;
+ zgettime_monotonic_if_available(&ts);
+ if (tloc)
+ *tloc = ts.tv_sec;
+ return ts.tv_sec;
+}
+
/*
* Sleep for the given number of microseconds --- must be within
* range of a long at the moment, but this is only used for
@@ -2794,7 +2807,9 @@ zsleep(long us)
/**
* Sleep for time (fairly) randomly up to max_us microseconds.
- * Don't let the wallclock time extend beyond end_time.
+ * Don't let the time extend beyond end_time. end_time is compared to
+ * the current *monotonic* clock time, so do NOT base it on e.g. time(2);
+ * use zmonotime() or zgettime_monotonic_if_available().
* Return 1 if that seemed to work, else 0.
*
* For best results max_us should be a multiple of 2**16 or large
@@ -2806,7 +2821,7 @@ int
zsleep_random(long max_us, time_t end_time)
{
long r;
- time_t now = time(NULL);
+ time_t now = zmonotime(NULL);
/*
* Randomish backoff. Doesn't need to be fundamentally
diff --git a/Src/zsh.h b/Src/zsh.h
index 090abf8f5..85b5c9bdc 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -1115,8 +1115,8 @@ struct process {
char text[JOBTEXTSIZE]; /* text to print when 'jobs' is run */
int status; /* return code from waitpid/wait3() */
child_times_t ti;
- struct timeval bgtime; /* time job was spawned */
- struct timeval endtime; /* time job exited */
+ struct timespec bgtime; /* time job was spawned */
+ struct timespec endtime; /* time job exited */
};
struct execstack {