[Date Prev][Date Next] [Chronological] [Thread] [Top]

Re: signal() behavior

I've noticed an annoying behavior in the alpha slapd on Linux: If the daemon
is running in the background, it appears to ignore SIGTERM. What has
actually happened is that the daemon is in select(), and the select call has
been restarted after the signal handler was invoked. I.e., the default
behavior on Linux for signal() is to restart system calls - it uses the
default BSD semantics. Anyone testing on Solaris or other SVR4-derived OSs
will not see this problem, because SysV signal() does not restart system
calls by default.

The solution seems to be to check for sigaction() in configure, and use it
instead of signal() if it's found. I'll make this fix in a little while.

I've been fighting with this for a while, too. However, it's not as simple as using sigaction (or sigvec) in place of signal where possible. Some systems don't return EINTR from select even when a signal is set with the SA_RESTART (or SA_INTERRUPT) flag set in these two calls. The issue is that some systems set the signal, and the first thread to notice the signal will service it. If the thread that has called select is not the thread to pick up the signal, the select call will not return with EINTR.

There has to be some way to make this work "correctly" on all systems, and that's what I've been searching for. For now, I've been using a kludge solution that never passes NULL as the time value to select. Instead, tvp is set to point to a tv that specifies some small number of seconds. This uses a bit of CPU time, but solves the problem of killing slapd (without using kill -9).

Here are diffs from daemon.c. I have not submitted them because they are not the ideal fix for this problem. However, if there is no good fix, I'll submit them.

--- daemon.c	1999/08/19 09:44:44	1.106
+++ daemon.c	1999/08/24 23:46:36
@@ -517,5 +517,5 @@
         struct hostent		*hp;
-		struct timeval		zero;
+		struct timeval		zero , five;
 		struct timeval		*tvp;

@@ -532,4 +532,6 @@
 		zero.tv_sec = 0;
 		zero.tv_usec = 0;
+		five.tv_sec = 5;
+		five.tv_usec = 0;

 		ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
@@ -573,4 +575,7 @@

+		if (!tvp)
+			tvp = &five;
 		for ( l = 0; slap_listeners[l] != NULL; l++ ) {
 			if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )