summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS3
-rw-r--r--freebsd/Makefile2
-rw-r--r--syslogd.c66
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;
}