Subject: lib/20001: native pthreads, signals and cond. variables
To: None <gnats-bugs@gnats.netbsd.org>
From: Anthony Mallet <anthony.mallet@useless-ficus.net>
List: netbsd-bugs
Date: 01/22/2003 22:55:13
>Number: 20001
>Category: lib
>Synopsis: native pthreads, signals and cond. variables
>Confidential: no
>Severity: critical
>Priority: medium
>Responsible: lib-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Wed Jan 22 13:56:00 PST 2003
>Closed-Date:
>Last-Modified:
>Originator: Anthony Mallet
>Release: NetBSD 1.6M - 2003-01-21
>Organization:
>Environment:
System: NetBSD ficus 1.6M NetBSD 1.6M (FICUS) #9: Wed Jan 22 01:35:03 CET 2003 troot@ficus:/home/src/netbsd-current/sys/arch/i386/compile/FICUS i386
Architecture: i386
Machine: i386
-lpthread.0 => /usr/lib/libpthread.so.0
-lc.12 => /usr/lib/libc.so.12
Jan 22 00:47 /usr/lib/libpthread.so.0.1
>Description:
I'm trying to use the new native libpthread with condition variables
signaled from signal handlers. The whole software is a bit complicated,
but I've written a simple C test program (which I attach below) that
suffers from the same bugs.
Basically, the program does the following:
1. Create a timer, with setitimer and a SIGALRM handler
2. Wait on a condition variable
3. The SIGALRM handler then signals the cond. variable
(this might look useless here, but in the context of the whole software
it does make sense ;)
When used with only one thread, this triggers an assert in libpthread:
assertion "next != 0" failed: file
"/home/src/netbsd-current/lib/libpthread/pthread_run.c", line 117,
function "pthread__next"
When used with a 2nd (dummy) thread that returns _before_ the SIGALRM is
handled, this prevent the program from returning from pthread_cond_wait
When used with a 2nd thread that returns _after_ the SIGALRM is handled,
this works. (Yeah !)
See the code below for a clearer description :)
>How-To-Repeat:
Compile and run the program below, it should produce the following
output:
ficus[~] > cc -Wall -o pthread-bug pthread-bug.c -lpthread
ficus[~] > ./pthread-bug one
Using 1 threadbefore cond wait
before cond wait
assertion "next != 0" failed: file
"/home/src/netbsd-current/lib/libpthread/pthr
ead_run.c", line 117, function "pthread__next"
Abort (core dumped)
ficus[~] > ./pthread-bug two
Using 2 threads, counting to 2
before cond wait
thread 2 started
thread 2 stopped
before cond signal
after cond signal
^C
(must interrupt by hand)
ficus[~] > ./pthread-bug 1000000000
Using 2 threads, counting to 1000000000
before cond wait
thread 2 started
before cond signal
after cond signal
after cond wait
ficus[~] >
(it works)
----------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/time.h>
pthread_cond_t cond;
void * thread_two(void *);
void timer_func(int);
int
main(int argc, char *argv[])
{
pthread_t thread;
pthread_mutex_t lock;
struct itimerval tv;
int option;
int status;
if (argc < 2) {
printf("Usage: %s [one|two|<integer>]\n", argv[0]);
return 2;
}
if (!strcmp(argv[1], "one")) {
option = 1;
printf("Using 1 thread", option);
} else if (!strcmp(argv[1], "two")) {
option = 2;
printf("Using 2 threads, counting to %d\n", option);
} else {
option = strtol(argv[1], NULL, 10);
printf("Using 2 threads, counting to %d\n", option);
}
/* intialize a mutex */
status = pthread_mutex_init(&lock, NULL);
if (status) { perror("pthread_mutex_init"); return 2; }
/* initialize a condition variable */
status = pthread_cond_init(&cond, NULL);
if (status) { perror("pthread_cond_init"); return 2; }
/* create a second thread, according to the command-line option */
if (option > 1) {
status = pthread_create(&thread, NULL, thread_two, &option);
if (status) { perror("pthread_create"); return 2; }
}
/* prepare for receiving SIGALRM */
signal(SIGALRM, timer_func);
/* setup a timer that starts after 1s */
tv.it_interval.tv_usec = 0;
tv.it_interval.tv_sec = 0;
tv.it_value.tv_usec = 0;
tv.it_value.tv_sec = 1;
status = setitimer(ITIMER_REAL, &tv, NULL);
if (status) { perror("setitimer"); return 2; }
/* block on the condition variable */
pthread_mutex_lock(&lock);
printf("before cond wait\n");
pthread_cond_wait(&cond, &lock);
printf("after cond wait\n");
pthread_mutex_unlock(&lock);
return 0;
}
/* Second thread body */
void *
thread_two(void *length)
{
int i = *(int *)length;
printf("thread 2 started\n");
while(i--) /* empty body */;
printf("thread 2 stopped\n");
return NULL;
}
/* SIGALRM handler */
void
timer_func(int dummy)
{
printf("before cond signal\n");
pthread_cond_signal(&cond);
printf("after cond signal\n");
}
>Fix:
No idea :(
>Release-Note:
>Audit-Trail:
>Unformatted: