From owner-cvs-lib Sun May 18 02:41:49 1997 Return-Path: Received: (from root@localhost) by hub.freebsd.org (8.8.5/8.8.5) id CAA22337 for cvs-lib-outgoing; Sun, 18 May 1997 02:41:49 -0700 (PDT) Received: from spinner.DIALix.COM (spinner.dialix.com [192.203.228.67]) by hub.freebsd.org (8.8.5/8.8.5) with ESMTP id CAA22329; Sun, 18 May 1997 02:41:19 -0700 (PDT) Received: from spinner.DIALix.COM (localhost.dialix.com.au [127.0.0.1]) by spinner.DIALix.COM with ESMTP id RAA06430; Sun, 18 May 1997 17:40:28 +0800 (WST) Message-Id: <199705180940.RAA06430@spinner.DIALix.COM> X-Mailer: exmh version 2.0gamma 1/27/96 To: =?KOI8-R?B?4c7E0sXKIP7F0s7P1w==?= cc: Bruce Evans , peter@FreeBSD.ORG, cvs-all@FreeBSD.ORG, cvs-committers@FreeBSD.ORG, cvs-lib@FreeBSD.ORG Subject: Re: cvs commit: src/lib/libc/gen sleep.c In-reply-to: Your message of "Sun, 18 May 1997 13:04:48 +0400." Date: Sun, 18 May 1997 17:40:27 +0800 From: Peter Wemm Sender: owner-cvs-lib@FreeBSD.ORG X-Loop: FreeBSD.org Precedence: bulk =?KOI8-R?B?4c7E0sXKIP7F0s7P1w==?= wrote: > On Sun, 18 May 1997, Peter Wemm wrote: > > > My current version is compatable with this, *except* that it doesn't seem > > convenient to mask SIGALRM while preparing to call nanosleep(). Doing a > > longjump out of the signal handler seems like overkill... > > > > I'm using this at present: > > Good news, this variant works with Apache, lets commit it. I'm not sure why this happens, but I suspect it's because we are eating the signal and not letting the apache timeout() function get called - it does longjumps and a whole heap of other stuff. With using the old sleep code, the apache SIGALRM handler was blocked, but the original nanosleep version was allowing the apache timeout() to be called as an interrupt within sleep(3). This is probably a bad assumption on apache's behalf if it depends on sleep() overriding it's SIGALRM handler... > BTW, I see race condition when SIGALRM comes inside sleep() code > before nanosleep() call. It can be blocked before, but how to unblock it > inside nanosleep()? The only way I can think of to get out of this is to use a longjmp from the signal handler and restore the signal masks.... *shudder*... eg, something roughly like this: static struct jmpbuf slpjmp; static void sleephandler() { longjump(&slpjmp, 1); } unsigned int sleep(seconds) unsigned int seconds; { struct timespec time_to_sleep; struct timespec time_remaining; struct sigvec vec, ovec; if (seconds != 0) { time_to_sleep.tv_sec = seconds; time_to_sleep.tv_nsec = 0; .. mask SIGALRM .. setvec(vec, sleephandler); (void) sigvec(SIGALRM, &vec, &ovec); if (setjmp(&jmpbuf) == 0) { .. unmask SIGALRM .. nanosleep(&time_to_sleep, &time_remaining); (void) sigvec(SIGALRM, &ovec, (struct sigvec *)0); seconds = time_remaining.tv_sec; if (time_remaining.tv_nsec > 0) seconds++; /* round up */ } else { .. calculate elapsed time .. } (void) sigvec(SIGALRM, &ovec, (struct sigvec *)0); .. unmask SIGALRM .. } return (seconds); } .. but this has several problems.. 1: it's starting to get messy with lots of syscalls. 2: it doesn't deal with an aborted nanosleep() due to SIGALRM. It'd have to calculate the elapsed time itself by calling gettimeofday or clock_gettime() before and after. It'd also suffer from time adjustments and contribute to the mess. I'm not sure how apache would deal with loosing a SIGALRM which isn't going to reset it's alarm() handler... But I don't think that what the new version is doing is any worse than the old code.. On the other hand, perhaps we could change the nanosleep syscall so that it takes a mask argument and handle the differences in the libc wrapper and have sleep(3) do this: sigprocmask(SIG_BLOCK, ..SIGALRM.., &oset); ... setsignal(SIGALRM, sleephandler); ... nanosleep_mask(&time, &remaining, &oset); ... and have nanosleep(ts1, ts2) be implemented as nanosleep_mask(ts1, ts2, NULL); > -- > Andrey A. Chernov > > http://www.nagual.pp.ru/~ache/ Cheers, -Peter