diff options
author | gshapiro <gshapiro@FreeBSD.org> | 2001-05-28 17:08:52 +0000 |
---|---|---|
committer | gshapiro <gshapiro@FreeBSD.org> | 2001-05-28 17:08:52 +0000 |
commit | 5338b6ff5f88e435da457fd0ec979a333012a0ef (patch) | |
tree | a5a76aa374529c5644a8991fe62c81f6b9b89964 /contrib/sendmail/src/clock.c | |
parent | 8d82727087db5182be90a20f20175cc720c5d1e5 (diff) | |
download | FreeBSD-src-5338b6ff5f88e435da457fd0ec979a333012a0ef.zip FreeBSD-src-5338b6ff5f88e435da457fd0ec979a333012a0ef.tar.gz |
Import sendmail 8.11.4
Diffstat (limited to 'contrib/sendmail/src/clock.c')
-rw-r--r-- | contrib/sendmail/src/clock.c | 226 |
1 files changed, 202 insertions, 24 deletions
diff --git a/contrib/sendmail/src/clock.c b/contrib/sendmail/src/clock.c index 8788291..bf5ef1c 100644 --- a/contrib/sendmail/src/clock.c +++ b/contrib/sendmail/src/clock.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -12,7 +12,7 @@ */ #ifndef lint -static char id[] = "@(#)$Id: clock.c,v 8.52.18.3 2000/09/17 17:04:26 gshapiro Exp $"; +static char id[] = "@(#)$Id: clock.c,v 8.52.18.14 2001/05/17 18:12:28 gshapiro Exp $"; #endif /* ! lint */ #include <sendmail.h> @@ -21,6 +21,7 @@ static char id[] = "@(#)$Id: clock.c,v 8.52.18.3 2000/09/17 17:04:26 gshapiro Ex # define sigmask(s) (1 << ((s) - 1)) #endif /* ! sigmask */ +static SIGFUNC_DECL tick __P((int)); static void endsleep __P((void)); @@ -42,7 +43,8 @@ static void endsleep __P((void)); ** none. */ -EVENT *FreeEventList; /* list of free events */ +static EVENT *volatile EventQueue; /* head of event queue */ +static EVENT *volatile FreeEventList; /* list of free events */ EVENT * setevent(intvl, func, arg) @@ -50,10 +52,7 @@ setevent(intvl, func, arg) void (*func)(); int arg; { - register EVENT **evp; register EVENT *ev; - auto time_t now; - int wasblocked; if (intvl <= 0) { @@ -61,33 +60,88 @@ setevent(intvl, func, arg) return NULL; } + ENTER_CRITICAL(); + if (FreeEventList == NULL) + { + FreeEventList = (EVENT *) xalloc(sizeof *FreeEventList); + FreeEventList->ev_link = NULL; + } + LEAVE_CRITICAL(); + + ev = sigsafe_setevent(intvl, func, arg); + + if (tTd(5, 5)) + dprintf("setevent: intvl=%ld, for=%ld, func=%lx, arg=%d, ev=%lx\n", + (long) intvl, (long) (curtime() + intvl), + (u_long) func, arg, + ev == NULL ? 0 : (u_long) ev); + + return ev; +} + +/* +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. +*/ + +EVENT * +sigsafe_setevent(intvl, func, arg) + time_t intvl; + void (*func)(); + int arg; +{ + register EVENT **evp; + register EVENT *ev; + auto time_t now; + int wasblocked; + + if (intvl <= 0) + return NULL; + wasblocked = blocksignal(SIGALRM); now = curtime(); /* search event queue for correct position */ - for (evp = &EventQueue; (ev = *evp) != NULL; evp = &ev->ev_link) + for (evp = (EVENT **) (&EventQueue); + (ev = *evp) != NULL; + evp = &ev->ev_link) { if (ev->ev_time >= now + intvl) break; } - /* insert new event */ - ev = FreeEventList; - if (ev == NULL) - ev = (EVENT *) xalloc(sizeof *ev); + ENTER_CRITICAL(); + if (FreeEventList == NULL) + { + /* + ** This shouldn't happen. If called from setevent(), + ** we have just malloced a FreeEventList entry. If + ** called from a signal handler, it should have been + ** from an existing event which tick() just added to the + ** FreeEventList. + */ + + LEAVE_CRITICAL(); + return NULL; + } else + { + ev = FreeEventList; FreeEventList = ev->ev_link; + } + LEAVE_CRITICAL(); + + /* insert new event */ ev->ev_time = now + intvl; ev->ev_func = func; ev->ev_arg = arg; ev->ev_pid = getpid(); + ENTER_CRITICAL(); ev->ev_link = *evp; *evp = ev; - - if (tTd(5, 5)) - dprintf("setevent: intvl=%ld, for=%ld, func=%lx, arg=%d, ev=%lx\n", - (long) intvl, (long)(now + intvl), (u_long) func, - arg, (u_long) ev); + LEAVE_CRITICAL(); (void) setsignal(SIGALRM, tick); intvl = EventQueue->ev_time - now; @@ -123,7 +177,9 @@ clrevent(ev) /* find the parent event */ wasblocked = blocksignal(SIGALRM); - for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link) + for (evp = (EVENT **) (&EventQueue); + *evp != NULL; + evp = &(*evp)->ev_link) { if (*evp == ev) break; @@ -132,9 +188,11 @@ clrevent(ev) /* now remove it */ if (*evp != NULL) { + ENTER_CRITICAL(); *evp = ev->ev_link; ev->ev_link = FreeEventList; FreeEventList = ev; + LEAVE_CRITICAL(); } /* restore clocks and pick up anything spare */ @@ -178,9 +236,11 @@ clear_events() for (ev = EventQueue; ev->ev_link != NULL; ev = ev->ev_link) continue; + ENTER_CRITICAL(); ev->ev_link = FreeEventList; FreeEventList = EventQueue; EventQueue = NULL; + LEAVE_CRITICAL(); /* restore clocks and pick up anything spare */ if (wasblocked == 0) @@ -201,6 +261,10 @@ clear_events() ** ** Side Effects: ** calls the next function in EventQueue. +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. */ /* ARGSUSED */ @@ -210,27 +274,67 @@ tick(sig) { register time_t now; register EVENT *ev; - int mypid = getpid(); + pid_t mypid; int save_errno = errno; (void) alarm(0); - now = curtime(); + FIX_SYSV_SIGNAL(sig, tick); + + errno = save_errno; + CHECK_CRITICAL(sig); + + mypid = getpid(); + while (PendingSignal != 0) + { + int sigbit; + int sig; + + if (bitset(PEND_SIGHUP, PendingSignal)) + { + sigbit = PEND_SIGHUP; + sig = SIGHUP; + } + else if (bitset(PEND_SIGINT, PendingSignal)) + { + sigbit = PEND_SIGINT; + sig = SIGINT; + } + else if (bitset(PEND_SIGTERM, PendingSignal)) + { + sigbit = PEND_SIGTERM; + sig = SIGTERM; + } + else if (bitset(PEND_SIGUSR1, PendingSignal)) + { + sigbit = PEND_SIGUSR1; + sig = SIGUSR1; + } + else + { + /* If we get here, we are in trouble */ + abort(); + } + PendingSignal &= ~sigbit; + kill(mypid, sig); + } + + now = curtime(); if (tTd(5, 4)) dprintf("tick: now=%ld\n", (long) now); - /* reset signal in case System V semantics */ - (void) setsignal(SIGALRM, tick); while ((ev = EventQueue) != NULL && (ev->ev_time <= now || ev->ev_pid != mypid)) { void (*f)(); int arg; - int pid; + pid_t pid; /* process the event on the top of the queue */ + ENTER_CRITICAL(); ev = EventQueue; EventQueue = EventQueue->ev_link; + LEAVE_CRITICAL(); if (tTd(5, 6)) dprintf("tick: ev=%lx, func=%lx, arg=%d, pid=%d\n", (u_long) ev, (u_long) ev->ev_func, @@ -240,9 +344,11 @@ tick(sig) f = ev->ev_func; arg = ev->ev_arg; pid = ev->ev_pid; + ENTER_CRITICAL(); ev->ev_link = FreeEventList; FreeEventList = ev; - if (pid != getpid()) + LEAVE_CRITICAL(); + if (pid != mypid) continue; if (EventQueue != NULL) { @@ -264,6 +370,72 @@ tick(sig) return SIGFUNC_RETURN; } /* +** PEND_SIGNAL -- Add a signal to the pending signal list +** +** Parameters: +** sig -- signal to add +** +** Returns: +** none. +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. +*/ + +void +pend_signal(sig) + int sig; +{ + int sigbit; + int save_errno = errno; + + /* + ** Don't want to interrupt something critical, hence delay + ** the alarm for one second. Hopefully, by then we + ** will be out of the critical section. If not, then + ** we will just delay again. The events to be run will + ** still all be run, maybe just a little bit late. + */ + + switch (sig) + { + case SIGHUP: + sigbit = PEND_SIGHUP; + break; + + case SIGINT: + sigbit = PEND_SIGINT; + break; + + case SIGTERM: + sigbit = PEND_SIGTERM; + break; + + case SIGUSR1: + sigbit = PEND_SIGUSR1; + break; + + case SIGALRM: + /* don't have to pend these */ + sigbit = 0; + break; + + default: + /* If we get here, we are in trouble */ + abort(); + + /* NOTREACHED */ + break; + } + + if (sigbit != 0) + PendingSignal |= sigbit; + (void) setsignal(SIGALRM, tick); + (void) alarm(1); + errno = save_errno; +} +/* ** SLEEP -- a version of sleep that works with this stuff ** ** Because sleep uses the alarm facility, I must reimplement @@ -281,7 +453,7 @@ tick(sig) */ -static bool SleepDone; +static bool volatile SleepDone; #ifndef SLEEP_T # define SLEEP_T unsigned int @@ -308,5 +480,11 @@ sleep(intvl) static void endsleep() { + /* + ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD + ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE + ** DOING. + */ + SleepDone = TRUE; } |