[Gc] Re: (Win32) attempt to unregister first GC thread will cause acrash.

Jean-Claude Beaudoin jean.claude.beaudoin at gmail.com
Thu Dec 17 20:06:24 PST 2009


To answer your question Ivan, yes the patch as I submitted it at the
beginning of this exchange is all that I need to make my code work.
It has been working for a few weeks now as far as I can tell.

Cheers,

Jean-Claude

Ivan Maidanski wrote:
> Hi!
> Jean-Claude Beaudoin <jean.claude.beaudoin at gmail.com> wrote:
>> Ivan Maidanski wrote:
>>> Hi!
>>> "Boehm, Hans" <hans.boehm at hp.com> wrote:
>>>> Under normal circumstances, this shouldn't be an issue, right?  The structure for the main thread should be statically allocated when the GC is initialized.  And GC_unregister_my_thread() shouldn't be called on the main thread.
>>>>
>>>> The patch looks fine.  I just wonder whether there is correct client code that really needs it.
>>>>
>>  >> Hans
>>
>> The situation that led me to this came up while debugging the shutdown code
>> of the Common Lisp environment I am currently porting to mingw32 from linux
>> where it seems to work just fine.  During the CL world shutdown each thread
>> must have its stack properly unwound with its unwind-protects properly executed.
>> In order to conveniently achieve this a dedicated thread is spawned with
>> sole mission to see that each and all of the other threads wrap-up their
>> business and terminate. Once that is assured, the shutdown thread with
>> its very limited and controlled context itself terminates.
>>
>> (BTW, the shutdown thread code is currently written in Common Lisp).
>>
>> In this process the 'initial' thread is not the last one to terminate,
>> thus the need to somehow "unregister" it just before it terminates.
>> If you don't unregister it before its termination then you are very likely to
>> get a crash of an other kind on a following GC collect.
>>
>> I don't know if you consider this correct client code but it sure feels
>> legitimate to me.
>>
>> The 'initial' thread does not have a special status in pthreads or Win32
>> (short of what happens on return from main()) and I don't see why it
>> should be considered any differently than any other thread.
>>
>> That the registration of the initial thread through GC_init() is
>> implicit rather than explicit does not change much to its reality.
>> The registration is very well there and must be undone before
>> the thread terminates.
>>
>> Regards,
>>
>> Jean-Claude Beaudoin
> 
> Q: Does that patch work for you?
> 
> ---
> 
> Hans -
> I found pthread's GC_unregister_my_thread could be called many times (for a thread while not detached) and this is not consistent with Win32.
> Should I add assertion (me->flags&FINISHED)==0 (after me=...) or alternatively try to provide similar behavior to win32 (and change gc.h docs)?
> 
>>
>>>>> -----Original Message-----
>>>>> From: gc-bounces at napali.hpl.hp.com
>>>>> [mailto:gc-bounces at napali.hpl.hp.com] On Behalf Of
>>>>> Jean-Claude Beaudoin
>>>>> Sent: Wednesday, December 16, 2009 4:30 AM
>>>>> To: gc at napali.hpl.hp.com
>>>>> Subject: [Gc] (Win32) attempt to unregister first GC thread
>>>>> will cause a crash.
>>>>>
>>>>>
>>>>> Hello BDW-GC maintainers,
>>>>>
>>>>> In file win32_threads.c there is a special case for the
>>>>> static allocation of the first GC_thread structure.
>>>>>
>>>>> If someone calls GC_unregister_my_thread() on that very first
>>>>> GC thread there will be a segmentation violation inside
>>>>> GC_delete_thread() when it tries to call GC_INTERNAL_FREE().
>>> The docs cleanly say it's not allowed:
>>>
>>> /* Unregister the current thread.  Only an explicity registered thread  */
>>> /* (i.e. for which GC_register_my_thread() returns GC_SUCCESS) is       */
>>> /* allowed (and required) to call this function.  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);
>>>
>>> The rule is: if you registered a thread then you, nobody else, are allowed and obliged to unregister it.
>>> The primordial thread is registered by the collector itself, so if someone calls C_register_my_thread() in it, the returned value would not be GC_SUCCESS.
>>>
>>> Of course, we may change the docs and the behavior, but is it worth (as Hans asked above)?
>>>
>>>>> I attached to this message a patch against 7.2alpha4 that
>>>>> seems to fix the problem.
>>>>>
>>>>> Cheers,
>>>>>
>>>>> Jean-Claude Beaudoin
> 
> Bye.



More information about the Gc mailing list