[Gc] Dynamic lib support for GC on MacOSX

Andrew Begel abegel@eecs.berkeley.edu
Fri, 27 Jun 2003 17:53:53 -0700


MacOSX dynamic library support can cause GC to deadlock during  
initialization of the libgc library (a dynamic library).

Due to a FIFO dynamic library loading queue, during initialization of  
the GC library in GC_thr_init(), the sigaction() call causes the  
dynamic loader to interrupt and start loading a new library. In the  
image, if multiple dynamic libraries are using the garbage collector  
(as in my application) and the dynamic loader chooses to load one of  
these during the first interruption of the garbage collection  
initialization, it may in fact try to reentrantly invoke the garbage  
collector (usually by calling GC_malloc()). This reentrant call  
deadlocks because the initialization of the garbage collector has  
locked the GC mutex. GC_malloc() tries to grab the same mutex, and  
deadlocks.

I was able to work around the problem by commenting out two lines of  
code in the GC_thr_init() routines: the calls to sigaction() to set up  
the thread suspend and restart signal handlers.

1. I don't know why sigaction() triggers the dynamic loader, to cause  
the problem. I've contacted Apple to find out why.
2. I'm sure the sigaction() calls are important to proper operation of  
GC with threads. Are there any documents that describe how threaded GC  
uses the signal handlers so I can figure out how to work around the  
problem? Other signal system calls do not trigger the dynamic loader.
3. This is running with DYLD_BIND_AT_LAUNCH set. Without this, we  
always get the deadlock, but the backtraces are always much longer and  
involve far more fanciful call stacks all ending up in the same  
deadlock.

andrew

PS. here's a gdb batchtrace showing the deadlock:

#0  0x90006ae8 in clock_sleep_trap ()
#1  0x900067ec in nanosleep ()
#2  0x024667a0 in GC_lock () at linux_threads.c:1948
#3  0x02466ef4 in GC_malloc (lb=16) at malloc.c:292
#4  0x03b7ab84 in Collectable::operator new(unsigned long) (size=16) at  
../../alloc/alloc.h:423
#5  0x03b7b1c4 in VG::VG() (this=0x3d19ff8) at globalInlines.h:143
#6  0x03b7ad38 in VG::VG() (this=0x3d19ff8) at globalInlines.h:152
#7  0x03ce50bc in __static_initialization_and_destruction_0(int, int)  
(__initialize_p=1, __priority=65535) at global.cc:23
#8  0x03ce517c in _GLOBAL__I_system_vg () at  
/usr/include/gcc/darwin/3.3/c++/iostream:152
#9  0x8fe16350 in __dyld_call_module_initializers_for_library ()
#10 0x8fe160e4 in __dyld_call_module_initializers ()
#11 0x8fe106f0 in __dyld_link_in_need_modules ()
#12 0x8fe12b94 in __dyld__dyld_bind_fully_image_containing_address ()
#13 0x90005374 in _dyld_bind_fully_image_containing_address ()
#14 0x900052cc in sigaction__ ()
#15 0x02465da8 in GC_thr_init () at linux_threads.c:1349
#16 0x0246ae00 in GC_init_inner () at misc.c:633
#17 0x02467684 in GC_generic_malloc_words_small_inner (lw=6, k=1) at  
mallocx.c:260
#18 0x024677b4 in GC_generic_malloc_words_small (lw=6, k=24) at  
mallocx.c:294
#19 0x01cadea8 in GC_aux_template<0>::GC_out_of_line_malloc(unsigned  
long, int) (nwords=6, kind=1) at /usr/local/include/new_gc_alloc.h:171
#20 0x01cadcc8 in single_client_gc_alloc_template<0>::allocate(unsigned  
long) (n=17) at /usr/local/include/new_gc_alloc.h:192
#21 0x01cadbb0 in gc_typed_allocator<char>::allocate(unsigned long,  
void const*) (this=0xbfffba84, n=17, hint=0x0) at ../alloc/alloc.h:222
#22 0x01cadb30 in std::basic_string<char, std::char_traits<char>,  
gc_typed_allocator<char> >::_Rep::_S_create(unsigned long,  
gc_typed_allocator<char> const&) (__capacity=4, __alloc=@0xbfffbcc0) at  
/usr/include/gcc/darwin/3.3/c++/bits/basic_string.tcc:443
#23 0x01cad5dc in char* std::basic_string<char, std::char_traits<char>,  
gc_typed_allocator<char> >::_S_construct<char const*>(char const*, char  
const*, gc_typed_allocator<char> const&, std::forward_iterator_tag)  
(__beg=0x1c907bc "Grey", __end=0x1c907c0 "", __a=@0xbfffbcc0) at  
/usr/include/gcc/darwin/3.3/c++/bits/basic_string.tcc:150
#24 0x01cad430 in char* std::basic_string<char, std::char_traits<char>,  
gc_typed_allocator<char> >::_S_construct_aux<char const*>(char const*,  
char const*, gc_typed_allocator<char> const&, __false_type)  
(__beg=0x1c907bc "Grey", __end=0x1c907c0 "", __a=@0xbfffbcc0) at  
/usr/include/gcc/darwin/3.3/c++/bits/basic_string.h:754
#25 0x01cad368 in char* std::basic_string<char, std::char_traits<char>,  
gc_typed_allocator<char> >::_S_construct<char const*>(char const*, char  
const*, gc_typed_allocator<char> const&) (__beg=0x1c907bc "Grey",  
__end=0x1c907c0 "", __a=@0xbfffbcc0) at  
/usr/include/gcc/darwin/3.3/c++/bits/basic_string.h:771
#26 0x01cad244 in std::basic_string<char, std::char_traits<char>,  
gc_typed_allocator<char> >::basic_string(char const*,  
gc_typed_allocator<char> const&) (this=0x1d0948c, __s=0x1c907bc "Grey",  
__a=@0xbfffbcc0) at  
/usr/include/gcc/darwin/3.3/c++/bits/basic_string.tcc:228
#27 0x01cad1cc in std::basic_string<char, std::char_traits<char>,  
gc_typed_allocator<char> >::basic_string(char const*,  
gc_typed_allocator<char> const&) (this=0x1d0948c, __s=0x1c907bc "Grey",  
__a=@0xbfffbcc0) at  
/usr/include/gcc/darwin/3.3/c++/bits/basic_string.tcc:226
#28 0x01c9f714 in __static_initialization_and_destruction_0(int, int)  
(__initialize_p=1, __priority=65535) at  
../lk/iparser/AbstractIncDebug.h:34
#29 0x01ca044c in _GLOBAL__I__Z5dummyPcm () at  
../lk/version/VDifferentialImpl.h:101
#30 0x8fe16594 in __dyld_call_module_initializers_for_objects ()
#31 0x8fe160a0 in __dyld_call_module_initializers ()
#32 0x8fe106f0 in __dyld_link_in_need_modules ()
#33 0x8fe121a4 in __dyld__dyld_link_module ()
#34 0x90016ae8 in NSLinkModule ()
#35 0x00069170 in dll_open (fname=0xbfffc150  
"/Users/abegel/Developer/harmonia/src/Library/Application  
Support/Harmonia/PlugIns/Harmonia_XEmacs.adapter/Contents/MacOS/ 
libHarmonia_XEmacs.dylib") at sysdll.c:271
#36 0x00069444 in emodules_load (module=0xffffffd0 <Address 0xffffffd0  
out of bounds>, modname=0x187a28 "", modver=0x187a28 "") at  
emodules.c:349
...
the rest of this backtrace is XEmacs internal functions that aren't  
relevant.

-----------
Andrew Begel
Ph.D. Candidate
Computer Science Division
University of California, Berkeley