Skip to content

Deadlock in pthread_barrier_wait #402

@g0djan

Description

@g0djan

Hi, I work on support of WASI-threads in WAMR.

I discovered a reproducible situation where 4 threads infinitely hang on pthread_barrier_wait.

Below I attach the minimal sample that hangs, it's reproducible if test run 500+ times. Left only calls to pthread_barrier_wait so we are sure that it doesn't stuck anywhere else.

#include <assert.h>
#include <pthread.h>
#include <malloc.h>


#define NUM_THREADS 3
static pthread_barrier_t barrier;

#define STACK_SIZE 32 * 1024 // same as the main stack

typedef struct {
    void *stack;
} start_args_t;

static inline int
start_args_init(start_args_t *start_args)
{
    start_args->stack = malloc(STACK_SIZE);
    if (!start_args->stack) {
        return 0;
    }

    start_args->stack += STACK_SIZE;
    return 1;
}

static inline void
start_args_deinit(start_args_t *start_args)
{
    free(start_args->stack - STACK_SIZE);
}

void
__wasi_thread_start_C(int thread_id, int *start_arg)
{
    pthread_barrier_wait(&barrier); <------ 3 threads stuck here and wasm_runtime_atomic_wait called inside
}

int
main(int argc, char **argv)
{
    assert(pthread_barrier_init(&barrier, NULL, NUM_THREADS + 1) == 0
           && "Failed to init barrier");
    int i;
    int thread_id = -1;
    start_args_t data[NUM_THREADS] = { 0 };
    for (i = 0; i < NUM_THREADS; i++) {
        /* No graceful memory free to simplify the test */
        assert(start_args_init(&data[i])
               && "Failed to allocate thread's stack");
    }
    for (i = 0; i < NUM_THREADS; i++) {
        thread_id = __wasi_thread_spawn(&data[i]);
        assert(thread_id > 0 && "Failed to create thread");
    }
    pthread_barrier_wait(&barrier);  <------ main thread stuck here and wasm_runtime_atomic_wait called inside
}

I used wasi-sdk-20+threads to compile .wasm file from this test with this command

/path/to/wasi-sdk/bin/clang \
        -g \
        --sysroot /path/to/wasi-sdk/share/wasi-sysroot/ \
        -target wasm32-wasi-threads \
        -pthread -ftls-model=local-exec \
        -z stack-size=32768 \
        -Wl,--export=__heap_base \
        -Wl,--export=__data_end \
        -Wl,--import-memory,--export-memory,--max-memory=1048576 \
        -Wl,--shared-memory,--max-memory=1966080 \
        -Wl,--export=wasi_thread_start \
        -Wl,--export=malloc \
        -Wl,--export=free \
        test.c -o test.wasm

To build WAMR that support threads this short manual can be followed.
Before compiling I recommend to change this value to 1e3 or lower so it's way faster to reproduce.

After WAMR(iwasm) and test.wasm are built I ran

for i in `seq 5000`; do ./iwasm -v=5 /tmp/hang_min.wasm ; done

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions