[Gc] GC_INIT? Threads?

Bruce Hoult bruce at hoult.org
Tue Aug 20 06:42:07 PDT 2013


Oh!

I just looked at your code.

In my new thread:
    struct GC_stack_base *my_sb;
    GC_get_stack_base(my_sb);

You need to allocate a GC_stack_base structure, not a pointer to one! You
just made an uninitialized pointer, which means that when GC_get_stack_base()
tries to fill in the structure it could be writing to any random place in
memory.

It should be:

    struct GC_stack_base my_sb;
    GC_get_stack_base(&my_sb);



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/20130821/e03d05ef/attachment.htm


More information about the Gc mailing list