From 2bc65ec7897ef5f7c025664f90b29c03eac6a4b5 Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Tue, 7 Mar 2000 15:12:56 +0000 Subject: Factor out the pause code. svn path=/trunk/; revision=2811 --- fetchmail.c | 174 +++++------------------------------------------------------- 1 file changed, 12 insertions(+), 162 deletions(-) (limited to 'fetchmail.c') diff --git a/fetchmail.c b/fetchmail.c index 24dfc00a..95430c08 100644 --- a/fetchmail.c +++ b/fetchmail.c @@ -6,7 +6,6 @@ #include "config.h" #include -#include #if defined(STDC_HEADERS) #include #endif @@ -16,7 +15,6 @@ #include #include #include -#include #if defined(HAVE_SYSLOG) #include #endif @@ -25,15 +23,11 @@ #include #endif #include -#include #include #include #ifdef HAVE_SETRLIMIT #include #endif /* HAVE_SETRLIMIT */ -#ifdef HAVE_SYS_WAIT_H -#include -#endif /* HAVE_SYS_WAIT_H */ #include #ifdef HAVE_GETHOSTBYNAME @@ -73,7 +67,6 @@ char *home; /* invoking user's home directory */ char *program_name; /* the name to prefix error messages with */ flag configdump; /* dump control blocks for configurator */ const char *fetchmailhost; /* either `localhost' or the host's FQDN */ -volatile int lastsig; /* last signal received */ #if NET_SECURITY void *request = NULL; @@ -90,34 +83,6 @@ static time_t parsetime; /* time of last parse */ static void terminate_run(int); static void terminate_poll(int); -#ifdef SLEEP_WITH_ALARM -/* - * The function of this variable is to remove the window during which a - * SIGALRM can hose the code (ALARM is triggered *before* pause() is called). - * This is a bit of a kluge; the real right thing would use sigprocmask(), - * sigsuspend(). This workaround lets the interval timer trigger the first - * alarm after the required interval and will then generate alarms all 5 - * seconds, until it is certain, that the critical section (ie., the window) - * is left. - */ -#if defined(STDC_HEADERS) -static sig_atomic_t alarm_latch = FALSE; -#else -/* assume int can be written in one atomic operation on non ANSI-C systems */ -static int alarm_latch = FALSE; -#endif - -RETSIGTYPE gotsigalrm(sig) -int sig; -{ - signal(sig, gotsigalrm); - lastsig = sig; - alarm_latch = TRUE; -} -#endif /* SLEEP_WITH_ALARM */ - -RETSIGTYPE donothing(int sig) {signal(sig, donothing); lastsig = sig;} - #ifdef HAVE_ON_EXIT static void unlockit(int n, void *p) #else @@ -129,19 +94,6 @@ static void unlockit(void) unlink(lockfile); } -#ifdef __EMX__ -/* Various EMX-specific definitions */ -int itimerflag; -void itimerthread(void* dummy) { - if (outlevel >= O_VERBOSE) - report(stderr, _("fetchmail: thread sleeping for %d sec.\n"), poll_interval); - while(1) { - _sleep2(poll_interval*1000); - kill((getpid()), SIGALRM); - } -} -#endif - #ifdef __FreeBSD__ /* drop SGID kmem privileage until we need it */ static void dropprivs(void) @@ -163,103 +115,6 @@ static void dropprivs(void) } #endif -static flag idle(int seconds) -/* time for a pause in the action; return TRUE if awakened by signal */ -{ -#ifndef __EMX__ -#ifdef SLEEP_WITH_ALARM /* not normally on */ - /* - * We can't use sleep(3) here because we need an alarm(3) - * equivalent in order to implement server nonresponse timeout. - * We'll just assume setitimer(2) is available since fetchmail - * has to have a BSDoid socket layer to work at all. - */ - /* - * This code stopped working under glibc-2, apparently due - * to the change in signal(2) semantics. (The siginterrupt - * line, added later, should fix this problem.) John Stracke - * wrote: - * - * The problem seems to be that, after hitting the interval - * timer while talking to the server, the process no longer - * responds to SIGALRM. I put in printf()s to see when it - * reached the pause() for the poll interval, and I checked - * the return from setitimer(), and everything seemed to be - * working fine, except that the pause() just ignored SIGALRM. - * I thought maybe the itimer wasn't being fired, so I hit - * it with a SIGALRM from the command line, and it ignored - * that, too. SIGUSR1 woke it up just fine, and it proceeded - * to repoll--but, when the dummy server didn't respond, it - * never timed out, and SIGALRM wouldn't make it. - * - * (continued below...) - */ - struct itimerval ntimeout; - - ntimeout.it_interval.tv_sec = 5; /* repeat alarm every 5 secs */ - ntimeout.it_interval.tv_usec = 0; - ntimeout.it_value.tv_sec = seconds; - ntimeout.it_value.tv_usec = 0; - - siginterrupt(SIGALRM, 1); - alarm_latch = FALSE; - signal(SIGALRM, gotsigalrm); /* first trap signals */ - setitimer(ITIMER_REAL,&ntimeout,NULL); /* then start timer */ - /* there is a very small window between the next two lines */ - /* which could result in a deadlock. But this will now be */ - /* caught by periodical alarms (see it_interval) */ - if (!alarm_latch) - pause(); - /* stop timer */ - ntimeout.it_interval.tv_sec = ntimeout.it_interval.tv_usec = 0; - ntimeout.it_value.tv_sec = ntimeout.it_value.tv_usec = 0; - setitimer(ITIMER_REAL,&ntimeout,NULL); /* now stop timer */ - signal(SIGALRM, SIG_IGN); -#else - /* - * So the workaround I used is to make it sleep by using - * select() instead of setitimer()/pause(). select() is - * perfectly happy being called with a timeout and - * no file descriptors; it just sleeps until it hits the - * timeout. The only concern I had was that it might - * implement its timeout with SIGALRM--there are some - * Unices where this is done, because select() is a library - * function--but apparently not. - */ - struct timeval timeout; - - timeout.tv_sec = run.poll_interval; - timeout.tv_usec = 0; - do { - lastsig = 0; - select(0,0,0,0, &timeout); - } while (lastsig == SIGCHLD); -#endif -#else /* EMX */ - alarm_latch = FALSE; - signal(SIGALRM, gotsigalrm); - _beginthread(itimerthread, NULL, 32768, NULL); - /* see similar code above */ - if (!alarm_latch) - pause(); - signal(SIGALRM, SIG_IGN); -#endif /* ! EMX */ - if (lastsig == SIGUSR1 - || ((run.poll_interval && !getuid()) && lastsig == SIGHUP)) - { -#ifdef SYS_SIGLIST_DECLARED - report(stdout, - _("awakened by %s\n"), sys_siglist[lastsig]); -#else - report(stdout, - _("awakened by signal %d\n"), lastsig); -#endif - return(TRUE); - } - - return(FALSE); -} - int main(int argc, char **argv) { int st, bkgd = FALSE; @@ -842,6 +697,8 @@ int main(int argc, char **argv) */ if (run.poll_interval) { + int lastsig; + /* * Because passwords can expire, it may happen that *all* * hosts are now out of the loop due to authfail @@ -866,31 +723,24 @@ int main(int argc, char **argv) report(stdout, _("fetchmail: sleeping at %s\n"), rfc822timestamp()); - /* - * With this simple hack, we make it possible for a foreground - * fetchmail to wake up one in daemon mode. What we want is the - * side effect of interrupting any sleep that may be going on, - * forcing fetchmail to re-poll its hosts. The second line is - * for people who think all system daemons wake up on SIGHUP. - */ - signal(SIGUSR1, donothing); - if (!getuid()) - signal(SIGHUP, donothing); - /* * OK, now pause util it's time for the next poll cycle. * A TRUE return indicates we received a wakeup signal; * unwedge all servers in case the problem has been * manually repaired. */ - if (idle(run.poll_interval)) + if ((lastsig = idle(run.poll_interval))) + { +#ifdef SYS_SIGLIST_DECLARED + report(stdout, + _("awakened by %s\n"), sys_siglist[lastsig]); +#else + report(stdout, + _("awakened by signal %d\n"), lastsig); +#endif for (ctl = querylist; ctl; ctl = ctl->next) ctl->wedged = FALSE; - - /* now lock out interrupts again */ - signal(SIGUSR1, SIG_IGN); - if (!getuid()) - signal(SIGHUP, SIG_IGN); + } if (outlevel >= O_VERBOSE) report(stdout, _("awakened at %s\n"), rfc822timestamp()); -- cgit v1.2.3