unofficial mirror of bug-guile@gnu.org 
 help / color / mirror / Atom feed
From: Andy Wingo <wingo@pobox.com>
To: gc@linux.hpl.hp.com
Cc: bug-guile <bug-guile@gnu.org>
Subject: pthreads and libgc
Date: Fri, 18 Mar 2011 21:56:04 +0100	[thread overview]
Message-ID: <m37hbwxi57.fsf@unquote.localdomain> (raw)

Hello list,

I was tracking down a bug in Guile, got to a sticky situation, and could
use some input.  Let me first show you the code.

    #include <unistd.h>
    #include <pthread.h>
    #include <time.h>
    #include <libguile.h>

    static void *thread_with_guile(void *null)
    {
      return NULL;
    }

    static void *the_thread(void *args)
    {
      scm_with_guile (thread_with_guile, NULL);
      return NULL;
    }


    int main(void)
    {
      int n;

      for (n = 0; n < 10000; n++) {
          pthread_t ptid;
          fprintf (stderr, "%d: create", n);
          pthread_create(&ptid, NULL, the_thread, NULL);
          void *ret;
          fprintf (stderr, " join");
          pthread_join(ptid, &ret);
          fprintf (stderr, " finished.\n");
        }

      return 0;
    }

I don't presume that you will compile it, but if you do, you can do so
with "gcc -o test test.c `pkg-config --cflags --libs guile-2.0`".

As you see, it creates a bunch of threads, and does something within
"guile mode" on each of them.  The use case is obviously for some big
threaded application with plugins, and you don't know what thread will
see Guile first.

The first scm_with_guile call will initialize Guile, which does a
GC_INIT, which basically goes like this:

  GC_all_interior_pointers = 0;
  GC_INIT ();

However, libgc appears already to have been initialized when this
happens, automagically, because of pthreads.  If I run the program under
GDB, it happens here:

    Breakpoint 1, GC_init () at misc.c:634
    634	{
    (gdb) thr apply all bt

    Thread 1 (Thread 0x7ffff78df700 (LWP 14166)):
    #0  GC_init () at misc.c:634
    #1  0x0000003fc8e1455e in GC_generic_malloc_inner (lb=56, k=1) at malloc.c:119
    #2  0x0000003fc8e1f4ce in GC_pthread_create (new_thread=0x7fffffffe020, attr=0x0, start_routine=0x4007e3 <the_thread>, 
        arg=0x0) at pthread_support.c:1469
    #3  0x0000000000400853 in main ()

Unhappily though, the initialization is done with
GC_all_interior_pointers == 1.  So later after Guile initializes, it
gets a segfault:

    Program received signal SIGSEGV, Segmentation fault.
    0x0000003fc8e0f6e3 in GC_is_black_listed (h=0x655000, len=<value optimized out>) at blacklst.c:233
    233	      if (get_pht_entry_from_index(GC_old_normal_bl, index)
    (gdb) thr apply all bt

    Thread 2 (Thread 0x7ffff78dd700 (LWP 14169)):
    #0  0x0000003fc8e0f6e3 in GC_is_black_listed (h=0x655000, len=<value optimized out>) at blacklst.c:233
    #1  0x0000003fc8e0d3db in GC_allochblk_nth (sz=16, kind=1, flags=0, n=29, may_split=<value optimized out>) at allchblk.c:694
    #2  0x0000003fc8e0d7dc in GC_allochblk (sz=16, kind=1, flags=0) at allchblk.c:629
    #3  0x0000003fc8e1a2fb in GC_new_hblk (gran=1, kind=1) at new_hblk.c:191
    #4  0x0000003fc8e0f593 in GC_allocobj (gran=1, kind=1) at alloc.c:1312
    #5  0x0000003fc8e1458a in GC_generic_malloc_inner (lb=8, k=1) at malloc.c:126
    #6  0x0000003fc8e12405 in GC_grow_table (table=0x3fc90394c0, log_size_ptr=0x3fc9028b70) at finalize.c:109
    #7  0x0000003fc8e126eb in GC_register_finalizer_inner (obj=0x654ff0, fn=0x7ffff7ca1841 <system_gc_callback>, cd=0x0, 
        ofn=0x0, ocd=0x0, mp=0x3fc8e11400 <GC_null_finalize_mark_proc>) at finalize.c:318
    #8  0x00007ffff7ca183a in scm_c_register_gc_callback (key=0x654ff0, func=0x7ffff7ca1841 <system_gc_callback>, data=0x0)
        at gc.c:554
    #9  0x00007ffff7ca19dc in scm_storage_prehistory () at gc.c:620
    #10 0x00007ffff7cb5e13 in scm_i_init_guile (base=0x7ffff78dcd80) at init.c:397
    #11 0x00007ffff7d27c48 in scm_i_init_thread_for_guile (base=0x7ffff78dcd80, parent=0x0) at threads.c:661
    #12 0x00007ffff7d27da8 in scm_i_with_guile_and_parent (func=0x4007d4 <thread_with_guile>, data=0x0, parent=0x0)
        at threads.c:798
    #13 0x00007ffff7d27d26 in scm_with_guile (func=0x4007d4 <thread_with_guile>, data=0x0) at threads.c:766
    #14 0x00000000004007fe in the_thread ()
    #15 0x0000003fc8e1e435 in GC_inner_start_routine (sb=<value optimized out>, arg=<value optimized out>) at pthread_start.c:61
    #16 0x0000003fc8e18525 in GC_call_with_stack_base (fn=<value optimized out>, arg=<value optimized out>) at misc.c:1491
    #17 0x0000003fc8607761 in start_thread (arg=0x7ffff78dd700) at pthread_create.c:301
    #18 0x0000003fc7ee098d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:115

    Thread 1 (Thread 0x7ffff78df700 (LWP 14166)):
    #0  0x0000003fc8607fbd in pthread_join (threadid=140737346656000, thread_return=0x7fffffffe018) at pthread_join.c:89
    #1  0x0000003fc8e1edd7 in GC_pthread_join (thread=140737346656000, retval=0x7fffffffe018) at pthread_support.c:1214
    #2  0x000000000040088a in main ()

In this case `GC_old_normal_bl' is NULL, as it is only initialized to a
valid value if GC_all_interior_pointers is zero, which was not the case
when libgc was automatically initialized.

What should we do here?

Thanks,

Andy
-- 
http://wingolog.org/



             reply	other threads:[~2011-03-18 20:56 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-03-18 20:56 Andy Wingo [this message]
     [not found] ` <m37hbwxi57.fsf-CaTCM8lwFkgB9AHHLWeGtNQXobZC6xk2@public.gmane.org>
2011-03-19 19:18   ` pthreads and libgc Ivan Maidanski
2011-03-19 23:26     ` [Gc] " Andy Wingo
     [not found]       ` <m3zkoqvgis.fsf-CaTCM8lwFkgB9AHHLWeGtNQXobZC6xk2@public.gmane.org>
2011-03-20  3:51         ` Boehm, Hans
2011-03-21  9:29           ` Ludovic Courtès
2011-03-25 14:49           ` [Gc] " Andy Wingo
2011-04-15 21:35           ` Calling ‘GC_INIT’ from a secondary thread Ludovic Courtès
2011-04-16  9:38             ` [Gc] Calling ‘GC_INIT’from " Ivan Maidanski
2011-04-17 14:01               ` Ludovic Courtès
2011-04-17 14:11                 ` Re[2]: [Gc] Calling ‘GC_INIT’ from " Ivan Maidanski
2011-04-17 19:49                   ` Ludovic Courtès
2011-04-18 22:18                     ` Re[2]: [Gc] Calling ‘GC_INIT’ from a secondarythread Ivan Maidanski
2011-03-20 10:45         ` Re[2]: pthreads and libgc Ivan Maidanski
2011-03-25 14:48           ` [Gc] " Andy Wingo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/guile/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=m37hbwxi57.fsf@unquote.localdomain \
    --to=wingo@pobox.com \
    --cc=bug-guile@gnu.org \
    --cc=gc@linux.hpl.hp.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).