[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