Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 6 Mar 2008 21:45:15 -0600
From:      "Marko, Shaun" <Shaun.Marko@lodgenet.com>
To:        "FreeBSD Hackers" <freebsd-hackers@freebsd.org>
Subject:   libpthread/fork issue
Message-ID:  <87D91DEDB1111C44BBFB9E3E90FF1E6E9553E0@host.lodgenet.com>

next in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
I'm working on FreeBSD 6.2 and I'm wondering if anybody can help with an
issue I've found using fork and threads. The attached program
demonstrates the problem. In short, if a process creates a thread, joins
the thread, then forks a child process which creates a thread, the
child's attempt to create a thread will cause the program to dump core
with the following error message:
Fatal error 'mutex is on list' at line 540 in file
/usr/src/lib/libpthread/thread/thr_mutex.c (errno = 0).

This seems to be true using an SMP or UP kernel.

If you run the attached program with no arguments, the parent process
will not create and join a thread and will not crash. Here is the
output:
[Sherlock]$ ./threadTest
child: born
child: thread created
child: thread joined
parent: child died

If you run the attached program with "-crash", the parent process
creates and joins a thread, causing the error:
[Sherlock]$ ./threadTest -crash
parent: thread created
parent: thread joined
child: born
Fatal error 'mutex is on list' at line 540 in file
/usr/src/lib/libpthread/thread/thr_mutex.c (errno = 0)
parent: child died

Here is the backtrace of the resulting core:
#0  0x28097537 in pthread_testcancel () from /lib/libpthread.so.2
[New Thread 0x8053200 (LWP 100163)]
[New Thread 0x8053000 (LWP 100201)]
(gdb) where
#0  0x28097537 in pthread_testcancel () from /lib/libpthread.so.2
#1  0x2808689a in sigaction () from /lib/libpthread.so.2
#2  0x2808088d in pthread_kill () from /lib/libpthread.so.2
#3  0x28080256 in raise () from /lib/libpthread.so.2
#4  0x28159b78 in abort () from /lib/libc.so.6
#5  0x28097c6f in pthread_testcancel () from /lib/libpthread.so.2
#6  0x2808c85f in _pthread_mutex_trylock () from /lib/libpthread.so.2
#7  0x2808d590 in _pthread_mutex_lock () from /lib/libpthread.so.2
#8  0x28083361 in _spinlock () from /lib/libpthread.so.2
#9  0x280f7ddb in _UTF8_init () from /lib/libc.so.6
#10 0x28172940 in _thread_autoinit_dummy_decl_stub () from
/lib/libc.so.6
#11 0x28074200 in ?? ()
#12 0x2804f405 in symlook_obj () from /libexec/ld-elf.so.1
#13 0x280883ff in pthread_attr_init () from /lib/libpthread.so.2
#14 0x280848fd in sigaction () from /lib/libpthread.so.2
#15 0x2808e915 in pthread_mutexattr_init () from /lib/libpthread.so.2
#16 0x28088116 in pthread_create () from /lib/libpthread.so.2
#17 0x08048795 in spawnThread (caller=0x80489f0 "child") at
threadTest.c:21
#18 0x08048879 in main (argc=2, argv=0x17e) at threadTest.c:62

Any help would be greatly appreciated. 

-Shaun

[-- Attachment #2 --]
PROG=threadTest
SRCS=threadTest.c
NO_MAN=t
NO_OBJ=t
LDADD=-lpthread
.include<bsd.prog.mk>

[-- Attachment #3 --]
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>

static void usage(void)
{
    fprintf(stderr, "usage: threadTest [-crash]\n");
    exit(1);
}
void* threadFunc(void* args)
{
    char *caller = (char*)args;
    printf("%s: thread created\n", caller);
    return 0;
}

int spawnThread(char *caller)
{
    pthread_t t;
    int err = pthread_create(&t, 0, threadFunc, caller);
    if (err)
    {
	fprintf(stderr, "%s: unable to create thread: %s\n", caller, strerror(err));
	return 1;
    }
    err = pthread_join(t, 0);
    if (err)
    {
	fprintf(stderr, "%s: unable to join thread: %s\n", caller, strerror(err));
	return 1;
    }
    printf("%s: thread joined\n", caller);
    return 0;
}

int main(int argc, char **argv)
{
    if (argc == 2)
    {
	if (strcmp(argv[1], "-crash") == 0)
	{
	    if (spawnThread("parent"))
	    {
		return 1;
	    }
	}
	else
	{
	    usage();
	}
    }
    pid_t pid = fork();
    if (pid == -1)
    {
	fprintf(stderr, "unable to fork: %s\n", strerror(errno));
	return 1;
    }
    else if (pid == 0)
    {
	printf("child: born\n");
	return spawnThread("child");
    }
    else
    {
	int status;
	pid_t pid = wait(&status);
	if (pid == -1)
	{
	   fprintf(stderr, "parent: wait: %s\n", strerror(errno));
	   return 1;
	}
	printf("parent: child died\n");
    }
    return 0;
}

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?87D91DEDB1111C44BBFB9E3E90FF1E6E9553E0>