O.k. I finally figured out why pthread_cancel just wasn't working for me, and it has something to do with the clone() call in multipathd. If you fork child(), everything works correctly. If you clone it, pthread_cancel dosn't work on PTHREAD_CANCEL_ASYNCHRONOUS type threads. This makes no sense to me. Is this supposed to happen?? Could people please try running the attached test program? When I use clone() (WORKS_CORRECTLY set to 0) it hangs. When I use fork() (WORKS_CORRECTLY set to 1) it does exactly what I expect. This is happening for me on RHEL4. I would be interested in knowing if it happens on other distros. Thanks -Ben
#include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <pthread.h> #include <sched.h> #include <string.h> #include <signal.h> #include <sys/types.h> #include <sys/wait.h> /* Compile with # gcc -o pthread_test -lpthread pthread_test.c */ /* uncomment this to make the program work on RHEL4. */ /* #define WORK_CORRECTLY 1 */ pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; void *thread_test(void *unused) { pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); pthread_mutex_unlock(&mutex); pause(); return NULL; } int test(void *unused) { void *status; int r; pthread_t thread; pthread_mutex_lock(&mutex); if ((r = pthread_create(&thread, NULL, thread_test, NULL)) != 0) { printf("pthread_create returned %d\n", r); exit(1); } pthread_mutex_lock(&mutex); printf("cancelling thread\n"); r = pthread_cancel(thread); printf("pthread cancel returned : %s\n", strerror(r)); printf("joining thread\n"); r = pthread_join(thread, &status); printf("pthread_join returned : %s\n", strerror(r)); if (status == PTHREAD_CANCELED) printf("child was canceled\n"); else printf("child exit status is %u\n", (unsigned)status); return 0; } int main(void) { #if WORK_CORRECTLY int pid = fork(); if (pid < 0){ printf("fork failed\n"); exit(1); } if (!pid) /* child */ return test(NULL); /* parent */ wait(NULL); return 0; #else void *stack = (void *)malloc(16384); if (clone(test, stack + 16383, 0, NULL) < 0) { printf("clone failed\n"); exit(1); } waitpid(0, NULL, __WCLONE); return 0; #endif }