pthread problem with asynchronous signals

From: Reto Baettig (baettig@scs.ch)
Date: Tue May 23 2000 - 19:54:26 EST


Hi

I saw that there are known problems with linux-threads and asynchronous
signals, but I could not find a matching error-report at
www-gnats.gnu.org.
So I am posting my observations of the problem. Maybe this helps
debugging the problems.

I also heard that this could be a kernel problem. This is the reason why
I'm posting this also to the kernel-list.

Please CC me answers because I'm not subscribed to all the
mailing-lists.

Thank you for your help

Reto

--------------------------------

Environment:
------------
Redhat 6.1, Kernel 2.2.14
SMP and UP on Alpha

C-Library: libc-2.1.3.so

Kernel modules 2.3.10-pre1
Gnu C egcs-2.91.66
Binutils 2.9.1.0.24
Dynamic linker ldd (GNU libc) 2.1.3
Linux C++ Library ..
Procps 2.0.5
Mount 2.9o
Net-tools 1.51
Console-tools 1999.03.02
Sh-utils 1.16
Modules Loaded eip elan rms qsw nfsd

Synopsis:
---------
Sending sigterm to a signal handler can cause pthread_cond_wait to
return.

Description:
------------
See attached example.
The threads are waiting for a condition. When I press CTRL-C, sometimes
the
threads waiting for the condition "wake up". This happens almost
everytime on
Alpha SMP and happens sometime on Alpha UP. I could not try Intel SMP
yet. Intel UP seems to work fine (but one never knows ;-)

Testcode:
---------

/*
 * thread.c
 *
 * compile with:
 * gcc -g -O2 -D_REENTRANT -o thread thread.c -lpthread
 *
 * run ./thread
 * press b to broadcast condition
 * press s to signal condition
 * press ctrl-c to call signal handler and set terminate variable
 * press b after ctrl-c to broadcast condition -> threads terminate
 *
 * Strange behaviour on alpha (UP ,SMP even worse), linux 2.2.14:
 * pressing ctrl-c sometimes lets foo come out of the
 * pthread_cond_wait(&cond, &mutex); condition
 *
 * On intel UP, this seems to work...
 *
 * Reto Baettig ( baettig@scs.ch )
 * 5-23-00
 *
 */

#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <asm/atomic.h>

#define NUM_THREADS 10

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

int terminate = 0;
int numthreads = 0;

void *foo(void *arg)
{
        for (;;) {
                pthread_mutex_lock(&mutex);
                if (terminate) {
                        goto terminate;
                }
                pthread_cond_wait(&cond, &mutex);
                if (terminate) {
                        goto terminate;
                }
                pthread_mutex_unlock(&mutex);
                printf("I got the signal!!!! 0x%Lx\n", pthread_self());
        }

terminate:
        numthreads--;
        pthread_mutex_unlock(&mutex);
        printf("I'm leaving now...\n");
        return NULL;
}
void bar(int signo)
{
        terminate++; /* Nobody decrements that variable, and we just
                        check it to be != 0, so I think that this is
safe and
                        that we do not need a mutex here */

        /*
         * we can also remove the next line. The strange behaviour
         * occurs less often but still occurs...
         */
        printf("%i: Got sigint!!! %i threads living...\n",
                        pthread_self(),numthreads);
}

int main(int argc, char *argv[])
{
        pthread_t threads[NUM_THREADS];
        pthread_attr_t attr;
        int i;
        char buffer[80];

        pthread_attr_init(&attr);

        for (i=0; i < NUM_THREADS; i++) {
                if (pthread_create(&threads[i], &attr, foo, NULL) < 0) {
                        perror("pthread_create");
                        exit(1);
                }
                pthread_mutex_lock(&mutex);
                numthreads++;
                pthread_mutex_unlock(&mutex);
        }

        signal(SIGINT, bar);

        while (fgets(buffer, 80, stdin)) {
                switch (toupper(*buffer)) {

                        case 'B' :
                                pthread_cond_broadcast(&cond);
                                break;

                        case 'S' :
                                pthread_cond_signal(&cond);
                                break;

                        default :
                                printf("Not an option.\n");
                                break;
                }

                pthread_mutex_lock(&mutex);
                if (!numthreads)
                        return 0; /* All the threads we had terminated
*/
                pthread_mutex_unlock(&mutex);
        }

        return 0;
}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Tue May 23 2000 - 21:00:25 EST