[Gc] Calling ‘GC_INIT’ from a secondary thread
Ludovic Courtès
ludo at gnu.org
Fri Apr 15 14:35:04 PDT 2011
Hi Hans,
"Boehm, Hans" <hans.boehm at hp.com> writes:
>> From: Andy Wingo
>> ...
>> [From Ivan:]
>> > But, anyway, it is recommended to initialize GC explicitly (i.e. by
>> > GC_INIT), so placing GC_INIT() (together with
>> > GC_set_all_interior_pointer) to the beginning of your main() should
>> be
>> > the best way out.
>>
>> We can add some documentation to this regard in the manual, if needed.
>> But is there no way to get around this, and do the right thing? For
>> example, to avoid implicit GC initialization in response to a
>> pthread_create.
>>
> The problem is that GC_pthread_create needs to allocate memory, and relies on some other GC state. Hence the GC must have been initialized for it to work.
>
> For newer collectors, it might be possible to instead arrange for pthread_create not to be redirected to GC_pthread_create, and for threads that need to be known to the GC to register themselves. I haven't thought through whether that might be feasible here.
With current CVS, it doesn’t seem to be possible to call GC_INIT from a
secondary thread, as in this example:
--8<---------------cut here---------------start------------->8---
#define GC_THREADS 1
#define GC_NO_THREAD_REDIRECTS 1
#include <gc/gc.h>
#include <pthread.h>
#include <stdlib.h>
static void *
thread (void *arg)
{
GC_INIT ();
GC_MALLOC (123);
GC_MALLOC (12345);
return NULL;
}
int
main (int argc, char *argv[])
{
pthread_t t;
pthread_create (&t, NULL, thread, NULL);
pthread_join (t, NULL);
return EXIT_SUCCESS;
}
/*
Local Variables:
compile-command: "gcc -Wall t.c `pkg-config bdw-gc --cflags --libs`"
End:
*/
--8<---------------cut here---------------end--------------->8---
This program segfaults:
--8<---------------cut here---------------start------------->8---
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff73e5700 (LWP 772)]
GC_push_all_eager (bottom=<value optimized out>, top=<value optimized out>) at ../mark.c:1528
1528 GC_PUSH_ONE_STACK(q, p);
(gdb) thread apply all bt
Thread 2 (Thread 0x7ffff73e5700 (LWP 772)):
#0 GC_push_all_eager (bottom=<value optimized out>, top=<value optimized out>) at ../mark.c:1528
#1 0x00007ffff7b91d4a in GC_push_all_stacks () at ../pthread_stop_world.c:336
#2 0x00007ffff7b898c4 in GC_mark_some (cold_gc_frame=0x7ffff73e4e0c "") at ../mark.c:373
#3 0x00007ffff7b800e8 in GC_stopped_mark (stop_func=0x7ffff7b7fbf0 <GC_never_stop_func>) at ../alloc.c:639
#4 0x00007ffff7b80880 in GC_try_to_collect_inner (stop_func=0x7ffff7b7fbf0 <GC_never_stop_func>) at ../alloc.c:457
#5 0x00007ffff7b8bb19 in GC_init () at ../misc.c:991
#6 0x0000000000400865 in thread ()
#7 0x00007ffff75f0cec in start_thread () from /nix/store/vxycd107wjbhcj720hzkw2px7s7kr724-glibc-2.12.2/lib/libpthread.so.0
#8 0x00007ffff78d81ed in clone () from /nix/store/vxycd107wjbhcj720hzkw2px7s7kr724-glibc-2.12.2/lib/libc.so.6
Thread 1 (Thread 0x7ffff7ff5700 (LWP 769)):
#0 0x00007ffff75f1f15 in pthread_join () from /nix/store/vxycd107wjbhcj720hzkw2px7s7kr724-glibc-2.12.2/lib/libpthread.so.0
#1 0x00000000004008bb in main ()
--8<---------------cut here---------------end--------------->8---
Is it expected?
> Another imperfect solution might be to set all_interior_pointers and probably call GC_INIT in a constructor, either a C++ constructor, or a C function that's suitably attributed. That still fails if other constructors run into this problem before our constructor runs.
If GC_INIT must be called from the main thread, then constructors would
seem to be the only way to get it called.
Thanks,
Ludo’.
More information about the Gc
mailing list