unofficial mirror of bug-guile@gnu.org 
 help / color / mirror / Atom feed
* pthreads and libgc
@ 2011-03-18 20:56 Andy Wingo
       [not found] ` <m37hbwxi57.fsf-CaTCM8lwFkgB9AHHLWeGtNQXobZC6xk2@public.gmane.org>
  0 siblings, 1 reply; 14+ messages in thread
From: Andy Wingo @ 2011-03-18 20:56 UTC (permalink / raw)
  To: gc; +Cc: bug-guile

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/



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re:  pthreads and libgc
       [not found] ` <m37hbwxi57.fsf-CaTCM8lwFkgB9AHHLWeGtNQXobZC6xk2@public.gmane.org>
@ 2011-03-19 19:18   ` Ivan Maidanski
  2011-03-19 23:26     ` [Gc] " Andy Wingo
  0 siblings, 1 reply; 14+ messages in thread
From: Ivan Maidanski @ 2011-03-19 19:18 UTC (permalink / raw)
  To: Andy Wingo; +Cc: bug-guile, gc-V9/bV5choksm30D7ZfaTJw

Hi Andy,

Fri, 18 Mar 2011 21:56:04 +0100 Andy Wingo <wingo-e+AXbWqSrlAAvxtiuMwx3w@public.gmane.org>:

> 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 ();

GC_all_interior_pointers cannot be modified after GC_INIT according to the spec. GC_set_all_interior_pointers() has an assertion check for this condition.

> 
> 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
> ...
> 
> 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?

You could compile GC without -D ALL_INTERIOR_POINTERS.

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.

Regards.

> 
> Thanks,
> 
> Andy
> -- 
> http://wingolog.org/

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Gc] pthreads and libgc
  2011-03-19 19:18   ` Ivan Maidanski
@ 2011-03-19 23:26     ` Andy Wingo
       [not found]       ` <m3zkoqvgis.fsf-CaTCM8lwFkgB9AHHLWeGtNQXobZC6xk2@public.gmane.org>
  0 siblings, 1 reply; 14+ messages in thread
From: Andy Wingo @ 2011-03-19 23:26 UTC (permalink / raw)
  To: Ivan Maidanski; +Cc: bug-guile, gc

Hi Ivan,

Thanks for the response.

On Sat 19 Mar 2011 20:18, Ivan Maidanski <ivmai@mail.ru> writes:

> GC_all_interior_pointers cannot be modified after GC_INIT according to
> the spec. GC_set_all_interior_pointers() has an assertion check for this
> condition.

I realize this.  We still allow compilation against 6.8, so I can't
blindly use GC_set_all_interior_pointers, though there are
possibilities.

However, that's not quite the issue.

 (1) How do I detect that GC has already been initialized, by some other
     module, and so avoid the GC_INIT ?
   
> You could compile GC without -D ALL_INTERIOR_POINTERS.

Unfortunately this is not possible, e.g. on Debian where we use a shared
libgc.

> 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.

Best regards,

Andy
-- 
http://wingolog.org/



^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: pthreads and libgc
       [not found]       ` <m3zkoqvgis.fsf-CaTCM8lwFkgB9AHHLWeGtNQXobZC6xk2@public.gmane.org>
@ 2011-03-20  3:51         ` Boehm, Hans
  2011-03-21  9:29           ` Ludovic Courtès
                             ` (2 more replies)
  2011-03-20 10:45         ` Re[2]: pthreads and libgc Ivan Maidanski
  1 sibling, 3 replies; 14+ messages in thread
From: Boehm, Hans @ 2011-03-20  3:51 UTC (permalink / raw)
  To: Andy Wingo, Ivan Maidanski
  Cc: bug-guile, gc-V9/bV5choksm30D7ZfaTJw@public.gmane.org

> 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.

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.

Hans

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re[2]:  pthreads and libgc
       [not found]       ` <m3zkoqvgis.fsf-CaTCM8lwFkgB9AHHLWeGtNQXobZC6xk2@public.gmane.org>
  2011-03-20  3:51         ` Boehm, Hans
@ 2011-03-20 10:45         ` Ivan Maidanski
  2011-03-25 14:48           ` [Gc] " Andy Wingo
  1 sibling, 1 reply; 14+ messages in thread
From: Ivan Maidanski @ 2011-03-20 10:45 UTC (permalink / raw)
  To: Andy Wingo; +Cc: bug-guile, gc-V9/bV5choksm30D7ZfaTJw

Hi,

I've modified GC_set_all_interior_pointer(), so it should be possible to alter all-interior-pointers mode even after GC_INIT (not quite sure this will always work as expected although).

If you want to still support v6.8 then I think you should check GC_VERSION_MAJOR/MINOR and use GC_set_all_interior_pointer() if v7.2+.

GC_INIT is  a no-op if GC is already initialized.

If you already care about threads registering then you can compile your app with -D GC_NO_THREAD_REDIRECTS (thus avoiding GC initialization in response to a pthread_create).

Regards.

Sun, 20 Mar 2011 00:26:19 +0100 Andy Wingo <wingo-e+AXbWqSrlAAvxtiuMwx3w@public.gmane.org>:

> Hi Ivan,
> 
> Thanks for the response.
> 
> On Sat 19 Mar 2011 20:18, Ivan Maidanski <ivmai-JGs/UdohzUI@public.gmane.org> writes:
> 
> > GC_all_interior_pointers cannot be modified after GC_INIT according to
> > the spec. GC_set_all_interior_pointers() has an assertion check for this
> > condition.
> 
> I realize this.  We still allow compilation against 6.8, so I can't
> blindly use GC_set_all_interior_pointers, though there are
> possibilities.
> 
> However, that's not quite the issue.
> 
> (1) How do I detect that GC has already been initialized, by some other
> module, and so avoid the GC_INIT ?
> 
> > You could compile GC without -D ALL_INTERIOR_POINTERS.
> 
> Unfortunately this is not possible, e.g. on Debian where we use a shared
> libgc.
> 
> > 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.
> 
> Best regards,
> 
> Andy
> -- 
> http://wingolog.org/
> _______________________________________________
> Gc mailing list
> Gc-V9/bV5choksm30D7ZfaTJw@public.gmane.org
> http://www.hpl.hp.com/hosted/linux/mail-archives/gc/

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: pthreads and libgc
  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
  2 siblings, 0 replies; 14+ messages in thread
From: Ludovic Courtès @ 2011-03-21  9:29 UTC (permalink / raw)
  To: gc-V9/bV5choksm30D7ZfaTJw; +Cc: bug-guile-mXXj517/zsQ

Hi,

"Boehm, Hans" <hans.boehm-VXdhtT5mjnY@public.gmane.org> writes:

> 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.

It looks like a hack that we could easily add in Guile.

Thanks,
Ludo’.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Gc] pthreads and libgc
  2011-03-20 10:45         ` Re[2]: pthreads and libgc Ivan Maidanski
@ 2011-03-25 14:48           ` Andy Wingo
  0 siblings, 0 replies; 14+ messages in thread
From: Andy Wingo @ 2011-03-25 14:48 UTC (permalink / raw)
  To: Ivan Maidanski; +Cc: bug-guile, gc

Greets,

On Sun 20 Mar 2011 11:45, Ivan Maidanski <ivmai@mail.ru> writes:

> If you already care about threads registering then you can compile your
> app with -D GC_NO_THREAD_REDIRECTS (thus avoiding GC initialization in
> response to a pthread_create).

Thanks for the pointer.  We were mistakenly redirecting pthread
functions not only in libguile, but also for our users.  I have fixed
that, and that helps this issue.

In addition, we were not calling GC_allow_register_threads().  I changed
to do so, and now the code in the original report (both with and without
GC_INIT in the main thread) works.

However it is now leaking memory.  I cannot reproduce the issue with
just libgc though, so it must be a Guile problem.

Thanks for the help!

Andy
-- 
http://wingolog.org/



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Gc] pthreads and libgc
  2011-03-20  3:51         ` Boehm, Hans
  2011-03-21  9:29           ` Ludovic Courtès
@ 2011-03-25 14:49           ` Andy Wingo
  2011-04-15 21:35           ` Calling ‘GC_INIT’ from a secondary thread Ludovic Courtès
  2 siblings, 0 replies; 14+ messages in thread
From: Andy Wingo @ 2011-03-25 14:49 UTC (permalink / raw)
  To: Boehm, Hans; +Cc: bug-guile, gc@linux.hpl.hp.com, Ivan Maidanski

On Sun 20 Mar 2011 04:51, "Boehm, Hans" <hans.boehm@hp.com> writes:

> 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.

I have done this, and it seems to work, though I have a leak to track
down, yet.  I'll let the list know if I get stuck again.  But in the
meantime, thanks very much for the help!

Andy
-- 
http://wingolog.org/



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Calling ‘GC_INIT’ from a secondary thread
  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           ` Ludovic Courtès
  2011-04-16  9:38             ` [Gc] Calling ‘GC_INIT’from " Ivan Maidanski
  2 siblings, 1 reply; 14+ messages in thread
From: Ludovic Courtès @ 2011-04-15 21:35 UTC (permalink / raw)
  To: gc-V9/bV5choksm30D7ZfaTJw; +Cc: bug-guile-mXXj517/zsQ

Hi Hans,

"Boehm, Hans" <hans.boehm-VXdhtT5mjnY@public.gmane.org> 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’.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Gc] Calling ‘GC_INIT’from a secondary thread
  2011-04-15 21:35           ` Calling ‘GC_INIT’ from a secondary thread Ludovic Courtès
@ 2011-04-16  9:38             ` Ivan Maidanski
  2011-04-17 14:01               ` Ludovic Courtès
  0 siblings, 1 reply; 14+ messages in thread
From: Ivan Maidanski @ 2011-04-16  9:38 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: bug-guile, gc

Hi Ludo,

Fixed. Thanks.

Fri, 15 Apr 2011 23:35:04 +0200 ludo@gnu.org (Ludovic Courtès):

> Hi Hans,
> 
> "Boehm, Hans" <hans.boehm@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:
> ...
> 
> 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’.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Gc] Calling ‘GC_INIT’from a secondary thread
  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
  0 siblings, 1 reply; 14+ messages in thread
From: Ludovic Courtès @ 2011-04-17 14:01 UTC (permalink / raw)
  To: Ivan Maidanski; +Cc: bug-guile, gc

Hi Ivan,

Ivan Maidanski <ivmai@mail.ru> writes:

> Fixed. Thanks.

I confirm it fixes the problem, thanks!

How about committing the code snippet I posted as a test case?

Ludo’.



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re[2]: [Gc] Calling ‘GC_INIT’ from a secondary thread
  2011-04-17 14:01               ` Ludovic Courtès
@ 2011-04-17 14:11                 ` Ivan Maidanski
  2011-04-17 19:49                   ` Ludovic Courtès
  0 siblings, 1 reply; 14+ messages in thread
From: Ivan Maidanski @ 2011-04-17 14:11 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: bug-guile, gc

Hi,

NP, I think. Just prepare a patch.

There is only one problem: Solaris expects GC_INIT to be called from the main thread due to:

  /* These variables are used to cache ss_sp value for the primordial   */
  /* thread (it's better not to call thr_stksegment() twice for this    */
  /* thread - see JDK bug #4352906).                                    */

Is there a way to find out whether this is a primordial thread on not on Solaris? if yes then it would be easy to fix the problem on Solaris as well.
(I don't see any other multi-threaded platform that prevents calling GC_INIT from non-primordial threads.)

Regards.

Sun, 17 Apr 2011 16:01:02 +0200 ludo@gnu.org (Ludovic Courtès):

> Hi Ivan,
> 
> Ivan Maidanski <ivmai@mail.ru> writes:
> 
> > Fixed. Thanks.
> 
> I confirm it fixes the problem, thanks!
> 
> How about committing the code snippet I posted as a test case?
> 
> Ludo’.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Gc] Calling ‘GC_INIT’ from a secondary thread
  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
  0 siblings, 1 reply; 14+ messages in thread
From: Ludovic Courtès @ 2011-04-17 19:49 UTC (permalink / raw)
  To: Ivan Maidanski; +Cc: bug-guile, gc

[-- Attachment #1: Type: text/plain, Size: 164 bytes --]

Hi Ivan,

Ivan Maidanski <ivmai@mail.ru> writes:

> NP, I think. Just prepare a patch.

Here’s one, without the re-generated files.

Thanks,
Ludo’.


[-- Attachment #2: the patch --]
[-- Type: text/x-patch, Size: 2873 bytes --]

Index: ChangeLog
===================================================================
RCS file: /cvsroot/bdwgc/bdwgc/ChangeLog,v
retrieving revision 1.467
diff -u -B -b -r1.467 ChangeLog
--- ChangeLog	16 Apr 2011 09:32:15 -0000	1.467
+++ ChangeLog	17 Apr 2011 19:46:58 -0000
@@ -1,3 +1,10 @@
+2011-04-17  Ludovic Courtès  <ludo@gnu.org>
+
+	* tests/tests.am (TESTS, check_PROGRAMS)[THREADS]: Add
+	`initsecondarythread'.
+	(initsecondarythread_SOURCES)
+	(initsecondarythread_LDADD)[THREADS]: New variables.
+
 2011-04-16  Ivan Maidanski  <ivmai@mail.ru>
 
 	* os_dep.c (GC_get_main_stack_base): Try to use
Index: tests/tests.am
===================================================================
RCS file: /cvsroot/bdwgc/bdwgc/tests/tests.am,v
retrieving revision 1.9
diff -u -B -b -r1.9 tests.am
--- tests/tests.am	23 Mar 2010 07:53:03 -0000	1.9
+++ tests/tests.am	17 Apr 2011 19:47:25 -0000
@@ -67,6 +67,11 @@
 check_PROGRAMS += threadleaktest
 threadleaktest_SOURCES = tests/thread_leak_test.c
 threadleaktest_LDADD = $(test_ldadd)
+
+TESTS += initsecondarythread$(EXEEXT)
+check_PROGRAMS += initsecondarythread
+initsecondarythread_SOURCES = tests/initsecondarythread.c
+initsecondarythread_LDADD = $(test_ldadd)
 endif
 
 if CPLUSPLUS
--- /dev/null	2011-04-15 17:57:42.483006363 +0200
+++ tests/initsecondarythread.c	2011-04-17 21:48:31.000000000 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 Ludovic Courtès <ludo@gnu.org>
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose,  provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+/* Make sure `GC_INIT' can be called from threads other than the initial
+ * thread.  See
+ * <http://article.gmane.org/gmane.comp.programming.garbage-collection.boehmgc/4490>
+ * for the original report.  */
+
+#if defined(__sun__) || defined(sun)
+
+/* Solaris expects `GC_INIT' to be called from the main thread, so skip this
+ * test.  */
+
+int main(int argc, char *argv[])
+{
+  /* Skip.  */
+  return 77;
+}
+
+#else /* ! __sun__ */
+
+#define GC_THREADS 1
+#define GC_NO_THREAD_REDIRECTS 1
+
+#include <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;
+}
+
+#endif /* ! __sun__ */

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re[2]: [Gc] Calling ‘GC_INIT’ from a secondarythread
  2011-04-17 19:49                   ` Ludovic Courtès
@ 2011-04-18 22:18                     ` Ivan Maidanski
  0 siblings, 0 replies; 14+ messages in thread
From: Ivan Maidanski @ 2011-04-18 22:18 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: bug-guile, gc

Hi Ludo,

I've committed the patch with minor modifications.
I've also fixed the problem on Solaris (by using thr_main()), so removed "ifndef sun" from the test.

Regards.

Sun, 17 Apr 2011 21:49:10 +0200 ludo@gnu.org (Ludovic Courtès):

> Hi Ivan,
> 
> Ivan Maidanski <ivmai@mail.ru> writes:
> 
> > NP, I think. Just prepare a patch.
> 
> Here’s one, without the re-generated files.
> 
> Thanks,
> Ludo’.
> 
> 
> Index: ChangeLog
> ...

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2011-04-18 22:18 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-03-18 20:56 pthreads and libgc Andy Wingo
     [not found] ` <m37hbwxi57.fsf-CaTCM8lwFkgB9AHHLWeGtNQXobZC6xk2@public.gmane.org>
2011-03-19 19:18   ` 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

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).