[dm-devel] pthread_cancel and clone weirdness
Benjamin Marzinski
bmarzins at redhat.com
Sat Jul 16 14:31:22 UTC 2005
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
-------------- next part --------------
#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
}
More information about the dm-devel
mailing list