Hi,

I am experiencing dead-lock with the new futex based rwlock
implementation commited few days ago.

I showed the problem on both amd64 and i386.

I spotted it with the rust testsuite, as some tests are now hanging
whereas they were fine before.

As I am expecting to have more audience with C reproducer instead of
Rust reproducer, I ported to C a hanging test from lang/rust.

Just keep in mind I didn't go too deeply in Rust libstd to check all
aspects of underline code, but just enough to reproduce in C. If my C
code is wrong, Rust code could be right, and I will redo my porting
work.


The program is relatively simple.

It uses a rwlock (RWLock variable) to protect a char array.

The function `panic_set_hook()' replace the value inside the char array
(with wrlock/unlock), and the function `panic()' read the char array to
print it (rdlock/unlock).

The test function `c()' (a separate thread) will globally set the char array
(using `panic_set_hook()') and read it (using `panic()').

We are creating several threads calling `c()' simultaneously, and we do
it several times.


$ cat test.c
#include <err.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define LOOP_MAIN 10
#define LOOP_THREAD 10

static pthread_rwlock_t RWLock = PTHREAD_RWLOCK_INITIALIZER;
static char msg[1024] = "default message";

void
panic_set_hook(char *new_msg)
{
        if (pthread_rwlock_wrlock(&RWLock) != 0)
                err(EXIT_FAILURE, "panic_set_hook: pthread_rwlock_wrlock");
                
        strlcpy(msg, new_msg, 1024);
        
        if (pthread_rwlock_unlock(&RWLock) != 0)
                err(EXIT_FAILURE, "panic_set_hook: pthread_rwlock_unlock");
}

void
panic()
{
        if (pthread_rwlock_rdlock(&RWLock) != 0)
                err(EXIT_FAILURE, "panic: pthread_rwlock_rdlock");
                
        printf("%s\n", msg);

        if (pthread_rwlock_unlock(&RWLock) != 0)
                err(EXIT_FAILURE, "panic: pthread_rwlock_unlock");
}

void *
c(void *_arg)
{
        printf("c\n");

        /* panic::set_hook() */
        panic_set_hook("c handler");
        
        /* panic!() */
        panic();

        return NULL;
}

int
main(int argc, char *argv[])
{
        int i, j;

        for (i=0; i < LOOP_MAIN; i++) {
                pthread_t handlers[LOOP_THREAD];

                printf("main: %d\n", i);

                for (j=0; j < LOOP_THREAD; j++) {
                        if (pthread_create(&(handlers[j]), NULL,
                            &c, NULL) != 0)
                                err(EXIT_FAILURE, "main: pthread_create");
                }

                for (j=0; j < LOOP_THREAD; j++) {
                        if (pthread_join(handlers[j], NULL) != 0)
                                err(EXIT_FAILURE, "main: pthread_join");
                }
        }

        return EXIT_SUCCESS;
}

$ cc -Wall -lpthread test.c
$ ./a.out
main: 0
c
c handler
c
c handler
c
c handler
c
c handler
c
c handler
c
c handler
c
c
c
c
c handler
c handler
[<--- HANG HERE]


If I am compiling libpthread with rthread_rwlock_compat.c instead
of rthread_rwlock.c (and no -DFUTEX), the program terminate without
hanging.


Thanks.
-- 
Sebastien Marie

Reply via email to