[Gc] GC_INIT? Threads?

Bruce Hoult bruce at hoult.org
Mon Aug 19 23:22:19 PDT 2013


It's really very hard to tell without knowing what error the GC is
detecting and aborting on (it writes the message to stderr), and without
being able to see your source code.

It could be as basic as your GC library not having been built to support
threads, or your client program not having done "#define GC_THREADS" before
including gc.h.

You can define the GC_LOOP_ON_ABORT environment variable, in which case
GC_abort() will sit in an infinite loop so you can attach to the process
and debug it. But then you could also have just set a breakpoint in
GC_abort() to achieve the same end.


On Tue, Aug 20, 2013 at 6:08 PM, The Devils Jester <
thedevilsjester at gmail.com> wrote:

> I apologize, I do not mean "crash" in the literal sense.  I appreciate the
> help finding a solution to my problem.
>
> The commands supplied, causes the program to lock up and consume all of
> the CPU.
>
> The code I have is as follows.  I am unsure about the stack_base or how it
> is used.
>
> In my primary thread:
>     GC_INIT();
>     GC_allow_register_threads();
>     ClassFromMyLib * myclass = new ClassFromMyLib();
>
> In my new thread:
>     struct GC_stack_base *my_sb;
>     GC_get_stack_base(my_sb);
>     GC_register_my_thread(my_sb);
>            myclass->myfunction();
>     GC_unregister_my_thread();
>
> Without the special GC_ functions, everything works fine until GC tries to
> reclaim memory, with them it locks up.
>
> Am I doing something wrong?
>
>
>
>
> On Tue, Aug 20, 2013 at 12:00 AM, Bruce Hoult <bruce at hoult.org> wrote:
>
>> Once again, it's not crashing, it's a controlled exit because it detected
>> something wrong.
>>
>> Try using these (from gc.h)
>>
>> call GC_allow_register_threads() from your main program, after GC_INIT()
>> call GC_register_my_thread() at the start of the main function for each
>> thread you create. (and GC_unregister_my_thread() at the end)
>>
>> You may also find  GC_call_with_stack_base() useful.
>>
>>   /* Explicitly enable GC_register_my_thread() invocation.              */
>>   /* Done implicitly if a GC thread-creation function is called (or     */
>>   /* implicit thread registration is activated).  Otherwise, it must    */
>>   /* be called from the main (or any previously registered) thread      */
>>   /* between the collector initialization and the first explicit        */
>>   /* registering of a thread (it should be called as late as possible). */
>>   GC_API void GC_CALL GC_allow_register_threads(void);
>>
>>   /* Register the current thread, with the indicated stack base, as     */
>>   /* a new thread whose stack(s) should be traced by the GC.  If it     */
>>   /* is not implicitly called by the GC, this must be called before a   */
>>   /* thread can allocate garbage collected memory, or assign pointers   */
>>   /* to the garbage collected heap.  Once registered, a thread will be  */
>>   /* stopped during garbage collections.                                */
>>   /* This call must be previously enabled (see above).                  */
>>   /* This should never be called from the main thread, where it is      */
>>   /* always done implicitly.  This is normally done implicitly if GC_   */
>>   /* functions are called to create the thread, e.g. by including gc.h  */
>>   /* (which redefines some system functions) before calling the system  */
>>   /* thread creation function.  Nonetheless, thread cleanup routines    */
>>   /* (eg., pthread key destructor) typically require manual thread      */
>>   /* registering (and unregistering) if pointers to GC-allocated        */
>>   /* objects are manipulated inside.                                    */
>>   /* It is also always done implicitly on some platforms if             */
>>   /* GC_use_threads_discovery() is called at start-up.  Except for the  */
>>   /* latter case, the explicit call is normally required for threads    */
>>   /* created by third-party libraries.                                  */
>>   /* A manually registered thread requires manual unregistering.        */
>>   GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *);
>>
>>   /* Unregister the current thread.  Only an explicitly registered      */
>>   /* thread (i.e. for which GC_register_my_thread() returns GC_SUCCESS) */
>>   /* is allowed (and required) to call this function.  (As a special    */
>>   /* exception, it is also allowed to once unregister the main thread.) */
>>   /* The thread may no longer allocate garbage collected memory or      */
>>   /* manipulate pointers to the garbage collected heap after making     */
>>   /* this call.  Specifically, if it wants to return or otherwise       */
>>   /* communicate a pointer to the garbage-collected heap to another     */
>>   /* thread, it must do this before calling GC_unregister_my_thread,    */
>>   /* most probably by saving it in a global data structure.  Must not   */
>>   /* be called inside a GC callback function (except for                */
>>   /* GC_call_with_stack_base() one).                                    */
>>   GC_API int GC_CALL GC_unregister_my_thread(void);
>>
>>
>>
>> On Tue, Aug 20, 2013 at 4:48 PM, The Devils Jester <
>> thedevilsjester at gmail.com> wrote:
>>
>>> The only output I get, aside from the stack trace is:
>>> Collecting from unknown thread
>>> Abort trap: 6
>>>
>>> My application is organized as follows:
>>>
>>> MAIN APP (does not use GC)
>>>    GC_INIT()
>>>    NEW THREAD
>>>          CALL LIBRARY FUNCTION (library uses GC)
>>>
>>> This crashes, while
>>>
>>> MAIN APP (does not use GC)
>>>    GC_INIT()
>>>    CALL LIBRARY FUNCTION (library uses GC)
>>>
>>> Works perfectly fine.
>>>
>>> What am I doing wrong?  Do I have to initialize the GC in some special
>>> fashion?
>>>
>>>
>>> On Mon, Aug 19, 2013 at 11:35 PM, Bruce Hoult <bruce at hoult.org> wrote:
>>>
>>>> That's not a crash, it's a deliberate abort because some
>>>> sanity-checking code found that your world was insane. There are several
>>>> things that can go wrong inside GC_push_all_stacks, so it would be
>>>> helpful to have the message that GC_abort() printed.
>>>>
>>>> However, you should always call GC_INIT() from your main program, and
>>>> as early as possible.
>>>>
>>>> On some versions and platforms GC_INIT() installs code that registers
>>>> threads in a GC data structure because it's not possible to ask the OS for
>>>> all your threads. If you call GC_INIT() from a new thread on those
>>>> platforms then that thread will remain unregistered, which is one of the
>>>> things that will make GC_push_all_stacks abort later.
>>>>
>>>>
>>>>
>>>> On Tue, Aug 20, 2013 at 4:10 PM, The Devils Jester <
>>>> thedevilsjester at gmail.com> wrote:
>>>>
>>>>> I have a library that makes heavy use of of the GC, and it works quite
>>>>> well when everything (the app, and the library) is in one thread.  I call
>>>>> GC_INIT in the app, and all is well.
>>>>>
>>>>> If, however, the app creates a new thread that calls the library
>>>>> function, then it crashes when the GC does its magic (below I have pasted
>>>>> some relevant output).
>>>>>
>>>>> Is there some trick to using GC on a separate thread?  Do I call
>>>>> GC_INIT from the main thread, or the one that calls the library functions?
>>>>>
>>>>>
>>>>> 0   libsystem_kernel.dylib         0x00007fff8ad14212 __pthread_kill
>>>>> + 10
>>>>> 1   libsystem_c.dylib             0x00007fff90d01b54 pthread_kill + 90
>>>>> 2   libsystem_c.dylib             0x00007fff90d45dce abort + 143
>>>>> 3   libgc.1.dylib                 0x000000010357676e GC_abort + 97
>>>>> 4   libgc.1.dylib                 0x000000010357b413
>>>>> GC_push_all_stacks + 285
>>>>> 5   libgc.1.dylib                 0x000000010357396e GC_mark_some +
>>>>> 377
>>>>> 6   libgc.1.dylib                 0x000000010356d73e GC_stopped_mark
>>>>> + 148
>>>>> 7   libgc.1.dylib                 0x000000010356d645
>>>>> GC_try_to_collect_inner + 245
>>>>> 8   libgc.1.dylib                 0x000000010356e302
>>>>> GC_collect_or_expand + 147
>>>>> 9   libgc.1.dylib                 0x000000010356e51a GC_allocobj + 228
>>>>> 10  libgc.1.dylib                 0x0000000103572515
>>>>> GC_generic_malloc_inner + 249
>>>>> 11  libgc.1.dylib                 0x00000001035725dd
>>>>> GC_generic_malloc + 79
>>>>> 12  libgc.1.dylib                 0x00000001035728c0 GC_core_malloc +
>>>>> 196
>>>>>
>>>>> --
>>>>> This message has been scanned for viruses and
>>>>> dangerous content by *MailScanner* <https://www.mailscanner.info/>,
>>>>> and is
>>>>> believed to be clean.
>>>>> _______________________________________________
>>>>> Gc mailing list
>>>>> Gc at linux.hpl.hp.com
>>>>> https://www.hpl.hp.com/hosted/linux/mail-archives/gc/
>>>>>
>>>>
>>>>
>>>
>>> --
>>> This message has been scanned for viruses and
>>> dangerous content by *MailScanner* <https://www.mailscanner.info/>, and
>>> is
>>> believed to be clean.
>>>
>>
>>
>
> --
> This message has been scanned for viruses and
> dangerous content by *MailScanner* <https://www.mailscanner.info/>, and is
> believed to be clean.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: https://napali.hpl.hp.com/pipermail/gc/attachments/20130820/51452ede/attachment-0001.htm


More information about the Gc mailing list