From f6289f35a43ba5838d97ddf2ac9b96b196e68033 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 26 Oct 2005 14:07:10 +0000 Subject: made multithreading work under BSD --- NEWS | 3 +++ freebsd/Makefile | 2 +- syslogd.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 61 insertions(+), 10 deletions(-) diff --git a/NEWS b/NEWS index cde34906..3d220c21 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,6 @@ +- made multithreading work with BSD. Some signal-handling needed to be + restructured. Also, there might be a slight delay of up to 10 seconds + when huping and terminating rsyslogd under BSD --------------------------------------------------------------------------- Version 1.12.0 (RGer), 2005-10-26 - moved to a multi-threaded design. single-threading is still optionally diff --git a/freebsd/Makefile b/freebsd/Makefile index 810a4e44..22fd8883 100644 --- a/freebsd/Makefile +++ b/freebsd/Makefile @@ -35,7 +35,7 @@ FEATURE_RFC3195=0 # Current thread code causes grief with signal handlers under # BSD - chances are extremely high rsyslogd will dump core if # enabled under BSD! -FEATURE_PTHREADS=0 +FEATURE_PTHREADS=1 # Enable debug mode (much slower code) FEATURE_DEBUG=0 diff --git a/syslogd.c b/syslogd.c index aff5e34f..5f5d3550 100644 --- a/syslogd.c +++ b/syslogd.c @@ -597,6 +597,10 @@ static int bGlblDone = 0; #endif /* END supporting structures for multithreading */ +static int bFinished = 0; /* used by termination signal handler, read-only except there + * is either 0 or the number of the signal that requested the + * termination. + */ /* * Intervals at which we flush out "message repeated" messages, @@ -4763,6 +4767,20 @@ static void logerror(char *type) return; } +/* doDie() is a signal handler. If called, it sets the bFinished variable + * to indicate the program should terminate. However, it does not terminate + * it itself, because that causes issues with multi-threading. The actual + * termination is then done on the main thread. This solution might introduce + * a minimal delay, but it is much cleaner than the approach of doing everything + * inside the signal handler. + * rgerhards, 2005-10-26 + */ +static void doDie(int sig) +{ + dprintf("DoDie called.\n"); + bFinished = sig; +} + /* die() is called when the program shall end. This typically only occurs * during sigterm or during the initialization. If you search for places where @@ -6672,6 +6690,11 @@ static void mainloop(void) fd_set writefds; struct filed *f; #endif +#ifdef BSD +#ifdef USE_PTHREADS + struct timeval tvSelectTimeout; +#endif +#endif #ifndef TESTING int fd; @@ -6686,7 +6709,7 @@ static void mainloop(void) int maxfds; /* --------------------- Main loop begins here. ----------------------------------------- */ - for (;;) { + while(!bFinished){ int nfds; errno = 0; FD_ZERO(&readfds); @@ -6777,13 +6800,38 @@ static void mainloop(void) dprintf("%d ", nfds); dprintf("\n"); } + +#define MAIN_SELECT_TIMEVAL NULL +#ifdef BSD +#ifdef USE_PTHREADS + /* There seems to be a problem with BSD and threads. When running on + * multiple threads, a signal will not cause the select call to be + * interrrupted. I am not sure if this is by design or an bug (some + * information on the web let's me think it is a bug), but that really + * does not matter. The issue with our code is that we will not gain + * control when rsyslogd is terminated or huped. What I am doing now is + * make the select call timeout after 10 seconds, so that we can check + * the condition then. Obviously, this causes some sluggish behaviour and + * also the loss of some (very few) cpu cycles. Both, I think, are + * absolutely acceptable. + * rgerhards, 2005-10-26 + */ + tvSelectTimeout.tv_sec = 10; + tvSelectTimeout.tv_usec = 0; +# undef MAIN_SELECT_TIMEVAL +# define MAIN_SELECT_TIMEVAL &tvSelectTimeout +#endif +#endif #ifdef SYSLOG_INET - nfds = select(maxfds+1, (fd_set *) &readfds, (fd_set *) &writefds, - (fd_set *) NULL, (struct timeval *) NULL); +#define MAIN_SELECT_WRITEFDS (fd_set *) &writefds #else - nfds = select(maxfds+1, (fd_set *) &readfds, (fd_set *) NULL, - (fd_set *) NULL, (struct timeval *) NULL); +#define MAIN_SELECT_WRITEFDS NULL #endif + nfds = select(maxfds+1, (fd_set *) &readfds, MAIN_SELECT_WRITEFDS, + (fd_set *) NULL, MAIN_SELECT_TIMEVAL); +#undef MAIN_SELECT_TIMEVAL +#undef MAIN_SELECT_WRITEFDS + if(bRequestDoMark) { domark(); bRequestDoMark = 0; @@ -6978,7 +7026,6 @@ static void mainloop(void) } FD_CLR(fileno(stdin), &readfds); } - #endif } } @@ -7231,9 +7278,9 @@ int main(int argc, char **argv) if (isupper(*p)) *p = tolower(*p); - (void) signal(SIGTERM, die); - (void) signal(SIGINT, Debug ? die : SIG_IGN); - (void) signal(SIGQUIT, Debug ? die : SIG_IGN); + (void) signal(SIGTERM, doDie); + (void) signal(SIGINT, Debug ? doDie : SIG_IGN); + (void) signal(SIGQUIT, Debug ? doDie : SIG_IGN); (void) signal(SIGCHLD, reapchild); (void) signal(SIGALRM, domarkAlarmHdlr); (void) signal(SIGUSR1, Debug ? debug_switch : SIG_IGN); @@ -7284,6 +7331,7 @@ int main(int argc, char **argv) /* --------------------- Main loop begins here. ----------------------------------------- */ mainloop(); + die(bFinished); return 0; } -- cgit