sustrik / libdill

Structured concurrency in C
MIT License
1.68k stars 155 forks source link

[Bug] Segfault in 3th go_mem() call #86

Closed pudelkoM closed 7 years ago

pudelkoM commented 7 years ago

When using the go_mem() function to start coroutines, it consistently fails with a segmentation fault after the 2nd time:

#include <libdill.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define errno_assert(x) \
    do {\
        if(!(x)) {\
            fprintf(stderr, "%s [%d] (%s:%d)\n", strerror(errno),\
                (int)errno, __FILE__, __LINE__);\
            fflush(stderr);\
            abort();\
        }\
    } while(0)

coroutine void fun() {
    msleep(now() + 1000);
}

// Resource cleanup omitted for brevity
int main(int argc, char *argv[]) {
    int cnt = 0;
    while(1) {
        void *stk = malloc(16384);
        errno_assert(stk != NULL);

        int cr = go_mem(fun(), stk, 16384);
        printf("%d\n", ++cnt);
        errno_assert(cr >= 0);
    }
}

Output:

> ./go_mem_fail 
1
2
fish: “./go_mem_fail” terminated by signal SIGSEGV (Address boundary error)

GDB:

1
2

Program received signal SIGSEGV, Segmentation fault.
0x0000000000401679 in dill_prologue (jb=0x7fffffffdcc0, ptr=0x7fffffffdcc8, len=16384, 
    file=0x404b1c "go_mem_fail.c", line=29) at cr.c:198
198         cr->vfs.query = dill_cr_query;

Plattfom: Linux, x86_64, static libdill build (git 5e736e5), debug enabled

sustrik commented 7 years ago

Now, this is super weird. If you replace 'stk' in the test case above by, say, 'p' is suddenly works OK.

pudelkoM commented 7 years ago

Oh, I can reproduce that. Maybe that's some funky interaction with GCC's statement expressions, the exact name stk is also used inside the go_mem() macro.

Not really a bug then, but would it be wise to change the variable names to something which is less likely to clash, e.g. stk_?

sustrik commented 7 years ago

Or dill_stk ...