Skip to content

Instantly share code, notes, and snippets.

@wlhlm
Last active February 3, 2016 18:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wlhlm/a9fd6bfd3945295fa5fb to your computer and use it in GitHub Desktop.
Save wlhlm/a9fd6bfd3945295fa5fb to your computer and use it in GitHub Desktop.
Segfault on Mac when unloading shared library linked to libguile

This is a test program which triggers a Segfault when compiled and run on Mac (Yosemite 10.10.5). This happens only after scm_init_guile() is called.

Save the two files pasted below and...
Compile

$ clang -g -shared -o guile.so guile.c $(pkg-config --cflags --libs guile-2.0)
$ clang -g test.c -o test

Example output

$ ./test
Loading Guile... Done!
Trying to load "init_guile" Done!
Trying to run "init_guile"
[1]    10678 segmentation fault  ./test

Output with additional dyld debugging info:

$ DYLD_PRINT_APIS=1 ./test
[...]
Trying to load "init_guile" Done!
Trying to run "init_guile"
_dyld_register_func_for_add_image(0x103399840)
_dyld_register_func_for_remove_image(0x103399b70)
_dyld_bind_fully_image_containing_address(0x1033a7ea0)
dladdr(0x1031eefd3, 0x7fff5ca61940)
dladdr(0x10320e06d, 0x7fff5ca61960)
dlclose(0x7ffefbc04a90)
dlclose(), found unused image 0x7ffefbc04a90 guile.so
dlclose(), found unused image 0x7ffefbc04bf0 libguile-2.0.22.dylib
dlclose(), found unused image 0x7ffefbc04cb0 libgc.1.dylib
dlclose(), found unused image 0x7ffefbc04e00 libffi.6.dylib
dlclose(), found unused image 0x7ffefbc04e90 libunistring.2.dylib
dlclose(), found unused image 0x7ffefbc04fc0 libgmp.10.dylib
dlclose(), found unused image 0x7ffefbc05050 libltdl.7.dylib
dlclose(), deleting 0x7ffefbc04a90 guile.so
dlclose(), deleting 0x7ffefbc04bf0 libguile-2.0.22.dylib
dlclose(), deleting 0x7ffefbc04cb0 libgc.1.dylib
dlclose(), deleting 0x7ffefbc04e00 libffi.6.dylib
[1]    41174 segmentation fault  DYLD_PRINT_APIS=1 ./test

This happens both with guile-stable (2.0) and guile-HEAD.

Backtrace

$ lldb test
(lldb) target create "test"
Current executable set to 'test' (x86_64).
(lldb) run
Process 10696 launched: '/Users/wlhlm/test' (x86_64)
Loading Guile... Done!
Trying to load "init_guile" Done!
Trying to run "init_guile"
Process 10696 stopped
* thread #1: tid = 0x1c2923, 0x000000010003cf57, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x10003cf57)
    frame #0: 0x000000010003cf57
error: memory read failed for 0x10003ce00
(lldb) bt all
* thread #1: tid = 0x1c2923, 0x000000010003cf57, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x10003cf57)
  * frame #0: 0x000000010003cf57
    frame #1: 0x00007fff5fc01cd3 dyld`dyld::removeImage(ImageLoader*) + 338
    frame #2: 0x00007fff5fc04fbc dyld`dyld::garbageCollectImages() + 823
    frame #3: 0x00007fff5fc0c3e8 dyld`dlclose + 134
    frame #4: 0x00007fff8f195808 libdyld.dylib`dlclose + 61
    frame #5: 0x0000000100000ea2 test`main + 258 at test.c:25
    frame #6: 0x00007fff8f1965c9 libdyld.dylib`start + 1
    frame #7: 0x00007fff8f1965c9 libdyld.dylib`start + 1
#include <libguile.h>
extern void init_guile(void);
void init_guile(void) {
scm_init_guile();
}
#include <stdio.h>
#include <dlfcn.h>
typedef void (*guile_func)(void);
int main (void) {
void *guile = NULL;
guile_func init_func = NULL;
printf("Loading Guile... ");
guile = dlopen("guile.so", RTLD_GLOBAL | RTLD_NOW);
if (!guile) printf("Error!\n");
else printf("Done!\n");
printf("Trying to load \"init_guile\" ");
init_func = dlsym(guile, "init_guile");
if (!init_func) printf("Error!\n");
else {
printf("Done!\n");
printf("Trying to run \"init_guile\"\n");
init_func();
}
printf("Closing Guile... ");
dlclose(guile);
printf("Done!\n");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment