1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00
cde/src/cmd/ksh93/bltins/sleep.c
Lev Kujawski e2d54b7169
sleep: guarantee sleeping specified time at minimum (#174)
With this patch, the Korn shell can now guarantee that calls to
sleep on systems using the select or poll method always result in
the system clock advancing by that much time, assuming no
interruptions. This compensates for deficiencies in certain
systems, including SCO UnixWare.

Discussion: https://github.com/ksh93/ksh/pull/174

src/lib/libast/tm/tvsleep.c:
- Ensure that at least the time requested to sleep has elapsed
  for the select and poll methods.
- Simplify the logic of calculating the time remaining to
  sleep and handle the case of an argument of greater than
  10e9 nanoseconds being passed to tvsleep.

src/cmd/ksh93/bltins/sleep.c:
- Eliminate the check for EINTR to handle other cases wherein
  we have not slept enough.

src/cmd/ksh93/tests/variables.sh:
- Improve the diagnostic message when the sleep test fails.
- Revise the SECONDS function test to expect that we always
  sleep for at least the time specified.

src/cmd/ksh93/tests/functions.h:
- Redirect ps stderr to /dev/null. UnixWare ps prints an error
  message about not being able to find the controlling terminal
  when shtests output is piped, but we are only using ps to find
  the PID.
2021-02-14 07:27:04 +00:00

148 lines
3.8 KiB
C

/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1982-2012 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* http://www.eclipse.org/org/documents/epl-v10.html *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* David Korn <dgk@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* sleep delay
*
* David Korn
* AT&T Labs
*
*/
#include "defs.h"
#include <error.h>
#include <errno.h>
#include <tmx.h>
#include "builtins.h"
#include "FEATURE/time"
#include "FEATURE/poll"
#ifdef _NEXT_SOURCE
# define sleep _ast_sleep
#endif /* _NEXT_SOURCE */
#ifdef _lib_poll_notimer
# undef _lib_poll
#endif /* _lib_poll_notimer */
int b_sleep(register int argc,char *argv[],Shbltin_t *context)
{
register char *cp;
register double d=0;
register Shell_t *shp = context->shp;
int sflag=0;
time_t tloc = 0;
char *last;
if(!(shp->sigflag[SIGALRM]&(SH_SIGFAULT|SH_SIGOFF)))
sh_sigtrap(SIGALRM);
while((argc = optget(argv,sh_optsleep))) switch(argc)
{
case 's':
sflag=1;
break;
case ':':
errormsg(SH_DICT,2, "%s", opt_info.arg);
break;
case '?':
errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
break;
}
if(error_info.errors)
errormsg(SH_DICT, ERROR_usage(2), "%s", optusage(NULL));
argv += opt_info.index;
if(cp = *argv)
{
d = strtod(cp, &last);
if(*last)
{
Time_t now,ns;
char* pp;
now = TMX_NOW;
if(*cp == 'P' || *cp == 'p')
ns = tmxdate(cp, &last, now);
else if(*last=='.' && shp->decomma && d==(unsigned long)d)
{
*(pp=last) = ',';
if(!strchr(cp,'.'))
d = strtod(cp,&last);
*pp = '.';
if(*last==0)
goto skip;
}
else if(*last!='.' && *last!=',')
{
if(pp = sfprints("exact %s", cp))
ns = tmxdate(pp, &last, now);
if(*last && (pp = sfprints("p%s", cp)))
ns = tmxdate(pp, &last, now);
}
if(*last)
errormsg(SH_DICT,ERROR_exit(1),e_number,*argv);
d = ns - now;
d /= TMX_RESOLUTION;
}
skip:
if(argv[1])
errormsg(SH_DICT,ERROR_exit(1),e_oneoperand);
}
else if(!sflag)
errormsg(SH_DICT,ERROR_exit(1),e_oneoperand);
if(d > .10)
{
time(&tloc);
tloc += (time_t)(d+.5);
}
if(sflag && d==0)
pause();
else while(1)
{
time_t now;
errno = 0;
shp->lastsig=0;
sh_delay(d,sflag);
if(sflag || tloc==0 || errno!=EINTR || shp->lastsig)
break;
sh_sigcheck(shp);
if(tloc < (now=time(NIL(time_t*))))
break;
d = (double)(tloc-now);
if(shp->sigflag[SIGALRM]&SH_SIGTRAP)
sh_timetraps(shp);
}
return(0);
}
/*
* delay execution for time <t>
*/
void sh_delay(double t, int sflag)
{
Shell_t *shp = sh_getinterp();
int n = (int)t;
Tv_t ts, tx;
ts.tv_sec = n;
ts.tv_nsec = 1000000000 * (t - (double)n);
while(tvsleep(&ts, &tx) < 0)
{
if ((shp->trapnote & (SH_SIGSET | SH_SIGTRAP)) || sflag)
return;
ts = tx;
}
}