[Gc] Roots observed in GC stack with threads
lincoln at techhouse.org
Mon Nov 26 18:48:48 PST 2007
I've been having a problem that I don't know how to resolve with heap
I am adding GC to a fairly small (1500 line) multithreaded program.
The program is in a complex infinite loop which results in several
allocations each iteration. The essence of it is that it's constructing
a new node in a linked list on each iteration, but the head is being
advanced as fast as the tail. I (fairly strongly) believe I'm updating
any pointers to the old head, so that the old elements in the list
should not be retained and the collector should properly collect it as
But (as you can probably guess) the heap continues to grow. I'm
wondering if anyone has seen the actual garbage collector
thread-initialization stack frames being considered a root before,
and/or how I can fix it.
Technical details follow:
I'm in Linux on x86 using pthreads for the threading. I've seen this
with gc-7.0 and a checkout from today's CVS.
The GC is built with:
./configure --enable-gc-debug --enable-threads=posix
I turned on GC_BACKTRACES=1 and GC_PRINT_ADDRESS_MAP=1, and I am getting
an ever-growing backtrace. An example backtrace shows a block that's
"reachable via 117 levels of pointers from root at 0xb76153a4". The
address map shows that address as being inside what must be a thread
stack, fairly near the top:
b6e16000-b7616000 rw-p b6e16000 00:00 0
I break the thread in GDB after printing out the GC backtrace in order
to examine the execution backtrace. I am seeing 25 frames (expected).
No stack is overflowing. Here's the top of my stack:
#19 0x0804991a in schedule (th_id=0, do_io_also=0) at mvm.c:276
#20 0x08049c47 in thr_start (id_v=0x0) at mvm.c:431
#21 0xb7fb3f58 in GC_inner_start_routine (sb=0xb76153b0, arg=0x8061f00)
#22 0xb7fad60c in GC_call_with_stack_base (
fn=0xb7fb3eb0 <GC_inner_start_routine>, arg=0x8061f00) at misc.c:1160
#23 0xb7fb36d7 in GC_start_routine (arg=0x8061f00) at pthread_support.c:1104
#24 0xb7f7746b in start_thread () from /lib/tls/i686/cmov/libpthread.so.0
#25 0xb7efa6de in clone () from /lib/tls/i686/cmov/libc.so.6
And here's the information about the two frames around the interesting
(gdb) info f 22
Stack frame at 0xb76153c0:
eip = 0xb7fad60c in GC_call_with_stack_base (misc.c:1160); saved eip 0xb7fb36d7
called by frame at 0xb76153e0, caller of frame at 0xb76153a0
source language c.
Arglist at 0xb76153b8, args: fn=0xb7fb3eb0 <GC_inner_start_routine>,
Locals at 0xb76153b8, Previous frame's sp is 0xb76153c0
ebp at 0xb76153b8, eip at 0xb76153bc
(gdb) info f 21
Stack frame at 0xb76153a0:
eip = 0xb7fb3f58 in GC_inner_start_routine (pthread_support.c:1073);
saved eip 0xb7fad60c
called by frame at 0xb76153c0, caller of frame at 0xb7615370
source language c.
Arglist at 0xb7615398, args: sb=0xb76153b0, arg=0x8061f00
Locals at 0xb7615398, Previous frame's sp is 0xb76153a0
ebx at 0xb761538c, ebp at 0xb7615398, esi at 0xb7615390, edi at 0xb7615394,
eip at 0xb761539c
So this reference was retained on the stack somehow during thread
creation, before the system actually jumped to my code?
My pthread_create call has nothing weird in the invocation -- it just
passes a small integer to the thread function.
Thanks for reading this,
More information about the Gc