mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
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.
148 lines
3.8 KiB
C
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;
|
|
}
|
|
}
|