[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
pthreads, signals, and shared libs
- To: OpenBSD Tech <tech@openbsd.org>
- Subject: pthreads, signals, and shared libs
- From: Marco S Hyman <marc@snafu.org>
- Date: Mon, 22 Oct 2001 16:24:19 -0700
The attached test program shows what appears to be a bug in pthread
signal handling with shared libs, tested on
OpenBSD hana.snafu.org 3.0 HANA#22 i386
OK: Not linked with -pthread
$ cc main.c
$ ./a.out
^Cterminated by signal 2
BAD: linked with -pthread, threads NOT used
$ cc -pthread main.c
$ ./a.out
^C (signal ignored)
OK: staticly linked with -pthread, threads NOT used
$ cc -static -pthread main.c
$ ./a.out
^Cterminated by signal 2
OK: staticly linked with -pthread, threads used
$ cc -static -pthread -DTHREAD main.c
$ ./a.out
^Cterminated by signal 2
Note that it is just the act of linking with -pthread that breaks
the code. Threads no not have to be used.
Workaround: don't use shared libs with -pthread.
---- main.c ----
#if defined(THREAD)
#include <pthread.h>
#endif
#include <signal.h>
typedef void (*Signal_handler)(int);
struct signal_state {
int sig;
int signal_pending;
Signal_handler top_half;
struct sigaction bottom_half;
} signal_state[NSIG + 1];
int running;
void
term_sig(int sig)
{
running = 0;
printf("terminated by signal %d\n", sig);
}
void
signal_handler(int sig)
{
if ((sig >= 1) && (sig <= NSIG)) {
signal_state[sig].signal_pending = 1;
}
}
int
signal_set(int sig, Signal_handler handler, Signal_handler top_half)
{
int result;
struct signal_state *s;
if ((sig < 1) || (sig > NSIG)) {
printf("signal_set: sig %d out of range\n", sig);
exit(1);
}
s = &signal_state[sig];
s->sig = sig;
s->signal_pending = 0;
s->top_half = top_half;
s->bottom_half.sa_handler = handler;
sigemptyset(&s->bottom_half.sa_mask);
s->bottom_half.sa_flags = 0;
result = sigaction(sig, &s->bottom_half, 0);
if (result == -1) {
warn("setting signal handler %p", handler);
}
return result;
}
void
signal_process(void)
{
struct signal_state *s;
for (s = &signal_state[1]; s < &signal_state[NSIG + 1]; s += 1) {
if (s->sig && s->signal_pending && s->top_half) {
s->signal_pending = 0;
(*s->top_half)(s->sig);
}
}
}
void *
thread(void *arg)
{
sigset_t sigs;
running = 1;
signal_set(SIGHUP, signal_handler, term_sig);
signal_set(SIGINT, signal_handler, term_sig);
sigemptyset(&sigs);
while (running) {
sigsuspend(&sigs);
signal_process();
}
return 0;
}
int
main(int argc, char *argv[])
{
#if defined(THREAD)
pthread_t thread_id;
pthread_create(&thread_id, 0, thread, 0);
pthread_join(thread_id, 0);
#else
thread(0);
#endif
return 0;
}