Subject: fork(2) vs. pthread_create()
To: None <tech-userlevel@NetBSD.org>
From: Matthias Scheler <tron@zhadum.de>
List: tech-userlevel
Date: 06/08/2004 10:54:58
Hello,
I found out today that NetBSD's "libpthread" doesn't like it when an
application uses pthread_create(), fork() and finally pthread_create()
in the child process. It aborts the program in this function in
"src/lib/libpthread/pthread_sa.c":
/*
* Set the round-robin timeslice timer.
*/
static int
pthread__setrrtimer(int msec, int startit)
{
static int rrtimer_created;
struct itimerspec it;
/*
* This check is safe -- we will either be called before there
* are any threads, or with the rrtimer_mutex held.
*/
if (rrtimer_created == 0) {
struct sigevent ev;
ev.sigev_notify = SIGEV_SA;
ev.sigev_signo = 0;
ev.sigev_value.sival_int = (int) PT_RRTIMER_MAGIC;
if (timer_create(CLOCK_VIRTUAL, &ev, &pthread_rrtimer) == -1)
return (errno);
rrtimer_created = 1;
}
if (startit) {
it.it_interval.tv_sec = 0;
it.it_interval.tv_nsec = (long)msec * 1000000;
it.it_value = it.it_interval;
if (timer_settime(pthread_rrtimer, 0, &it, NULL) == -1)
return (errno);
}
pthread_rrtimer_interval = msec;
return (0);
}
The reason is that the timer was created in the parent process and is
therefore not valid in the child process so that timer_settime() fails.
This could be fixed like this:
/*
* Set the round-robin timeslice timer.
*/
static int
pthread__setrrtimer(int msec, int startit)
{
static pid_t rrtimer_pid = -1;
struct itimerspec it;
/*
* This check is safe -- we will either be called before there
* are any threads, or with the rrtimer_mutex held.
*/
if (rrtimer_pid != getpid()) {
struct sigevent ev;
ev.sigev_notify = SIGEV_SA;
ev.sigev_signo = 0;
ev.sigev_value.sival_int = (int) PT_RRTIMER_MAGIC;
if (timer_create(CLOCK_VIRTUAL, &ev, &pthread_rrtimer) == -1)
return (errno);
rrtimer_pid = getpid();
}
[...]
return (0);
}
Opinions?
Kind regards
--
Matthias Scheler http://scheler.de/~matthias/