When a thread installs a signal handler, and then is pthread_kill'd during a select, it returns 0 (as if the select timed out) instead of -1. In addition, errno is not set to EINTR. If a signal handler is not installed, select correctly returns -1 and sets errno to EINTR. I'm not sure if this affects reads and writes or not, yet. How-To-Repeat: cd /tmp cat <<END_PROG > simple.c #include <errno.h> #include <pthread.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> void *t_body(void *arg); pthread_mutex_t t_lock; pthread_cond_t t_cond; sigset_t set; #define WRITE(x) do { printf(x "\n"); fflush(stdout); } while (0) int main(void) { pthread_t t; WRITE("main: hello"); pthread_mutex_init(&t_lock, NULL); pthread_cond_init(&t_cond, NULL); sigemptyset(&set); sigaddset(&set, SIGUSR1); pthread_mutex_lock(&t_lock); WRITE("main: creating test thread..."); pthread_create(&t, NULL, t_body, NULL); pthread_cond_wait(&t_cond, &t_lock); pthread_mutex_unlock(&t_lock); pthread_sigmask(SIG_BLOCK, &set, NULL); sleep(1); WRITE("main: killing test thread"); pthread_kill(t, SIGUSR1); pthread_exit(NULL); /* NOTREACHED */ exit(EXIT_SUCCESS); } void handle_sigusr1(int sig) { WRITE("handle_sigusr1"); signal(sig, handle_sigusr1); } void * t_body(void *arg) { struct sigaction sact; fd_set fds; int error; WRITE("test: hello"); #ifdef SIG sact.sa_flags = 0; sact.sa_handler = handle_sigusr1; sigaction(SIGUSR1, &sact, NULL); #endif FD_ZERO(&fds); pthread_detach(pthread_self()); pthread_sigmask(SIG_UNBLOCK, &set, NULL); WRITE("test: go ahead, main"); pthread_mutex_lock(&t_lock); pthread_cond_signal(&t_cond); pthread_mutex_unlock(&t_lock); WRITE("test: sleeping..."); error = select(0, &fds, 0, 0, 0); printf("test: select returned %d\n", error); fflush(stdout); if (errno == EINTR) WRITE("test: INTERRUPTED! Yeah!"); else { printf("test: uh-oh (error: %s)\n", strerror(errno)); fflush(stdout); } return NULL; } END_PROG cc -o simple -DSIG simple.c -pthread ./simple cc -o simple simple.c -pthread ./simple
Responsible Changed From-To: freebsd-bugs->jasone Over to our threads guy.
Responsible Changed From-To: jasone->deischen I've got some changes to the threads library in the pipeline and have this problem fixed.
State Changed From-To: open->closed This is fixed in both -current and -stable. There was one flaw in this PR, though. If a signal handler is not installed, then the signal gets sent to the process. For the test case included here, that means that the program will get killed by SIGUSR1.