signal handling and posix threads
coderman
coderman at gmail.com
Tue Feb 20 07:01:54 UTC 2007
hi guys, someone mentioned a problem with SIGPIPE causing aborts with
posix threads.[0] typically this is handled a few ways:
- with a dedicated signal handling thread (linux messes this up when
threads get distinct process ids [1]) that sigwait's for events. all
other threads block signals.
- masking and trapping/checking signals within each thread; usually
more complicated than it's worth and may lead to odd behavior with
sigaction.
i'm not familiar enough with the internals of Tor to know the
trade-off's involved in such a decision. the process based signal
handling in do_main_loop/handle_signals would work fine in a dedicated
sighandler thread, but somehow this would need to be distinguished
from the others and yet utilize the same event loop. (perhaps
something as simple as a new thread doing nothing but sigwait/sleeping
without signals masked, but it would have to dispatch long sig
handlers to a worker lest processing block any new incoming signals)
there are some libevent considerations as well, particularly
evsignal_*, although i'm also not very familiar with how libevent
handles signals in a threaded context.
in any case, the naive and untested approach is to simply mask signals
in worker threads, like:
---cut---
diff -Naur orig/src/common/compat.c mod/src/common/compat.c
--- orig/src/common/compat.c 2007-02-03 02:42:43.000000000 +0000
+++ mod/src/common/compat.c 2007-02-20 01:16:05.648185312 +0000
@@ -81,6 +81,7 @@
#include <assert.h>
#ifdef HAVE_PTHREAD_H
#include <pthread.h>
+#include <signal.h>
#endif
#ifdef HAVE_UTIME_H
#include <utime.h>
@@ -978,6 +979,11 @@
tor_pthread_data_t *data = _data;
void (*func)(void*);
void *arg;
+ /* mask signals to worker threads to avoid SIGPIPE, etc */
+ sigset_t sigs;
+ const int how = SIG_SETMASK;
+ sigfillset (&sigs);
+ pthread_sigmask (how, &sigs, 0);
func = data->func;
arg = data->data;
tor_free(_data);
---end-cut---
however, at least one thread would need to be the sole handler for
incoming signals via unmasked state or sigwait.
has this been discussed before in the context of the Tor event loop
when using pthread? is anyone more familiar with libevent aware of
the usual idioms for handling signals within worker pthreads? (it
appears at first glance that most signal mgmt in libevent is at a
process level)
best regards,
0. from <frozen> in irc:
Feb 19 23:00:07.602 [notice] Self-testing indicates your DirPort is
reachable from the outside. Excellent.
[New Thread 0x80f4200 (LWP 100068)]
Program received signal SIGPIPE, Broken pipe.
[Switching to Thread 0x80f4200 (LWP 100068)]
0x2827f5b7 in pthread_testcancel () from /lib/libpthread.so.2
1. pthread_signal(3)
"Signal handling in LinuxThreads departs significantly from the
POSIX standard. According to the standard, ''asynchronous'' (external)
signals are addressed to the whole process (the collection of all
threads), which then delivers them to one particular thread. The
thread that actually receives the signal is any thread that does not
currently block the signal.
In LinuxThreads, each thread is actually a kernel process with its
own PID, so external signals are always directed to one particular
thread. If, for instance, another thread is blocked in sigwait on
that signal, it will not be restarted.
The LinuxThreads implementation of sigwait installs dummy signal
handlers for the signals in set for the duration of the wait.
Since signal handlers are shared between all threads, other threads
must not attach their own signal handlers to these signals, or
alternatively they should all block these signals (which is
recommended anyway -- see the Notes section."
More information about the tor-dev
mailing list