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/