GC object finalization not guaranteed

Fawzi Mohamed fmohamed at mac.com
Sat Apr 18 14:43:38 PDT 2009


On 2009-04-18 23:22:21 +0200, Leandro Lucarella <llucax at gmail.com> said:

> Leandro Lucarella, el 18 de abril a las 18:03 me escribiste:
>> Fawzi Mohamed, el 18 de abril a las 22:48 me escribiste:
>>> On 2009-04-18 22:25:32 +0200, Don <nospam at nospam.com> said:
>>> 
>>>> Leandro Lucarella wrote:
>>>>> Robert Jacques, el 18 de abril a las 11:56 me escribiste:
>>>>>> On Sat, 18 Apr 2009 11:24:14 -0400, Leandro Lucarella <llucax at gmail.com> wrote:
>>>>>>> I've just found out[1] this[2]:
>>>>>>> 	The garbage collector is not guaranteed to run the destructor for
>>>>>>> 	all unreferenced objects.
>>>>>>> Is there any reason why D can't guarantee that all finalizers will be
>>>>>>> called, at least when the program ends?
>>> 
>>> when the main thread ends other threads might be running, and removing
>>> memory they are using is not necessarily a good idea.
>> 
>> Then I guess gc_term() should be invoked when all threads have terminated.
>> Is there any technical difficulty to do that?
>> 
>>> Exceptions might delay things indefinitely and allocate more memory.
>> 
>> Then I guess gc_term() should be invoked when all exceptions were
>> processed. Is there any technical difficulty to do that?
>> 
>> I really didn't take a look at the compiler runtime stuff, so I don't
>> really know how all that works.
> 
> Ok, this is the code that handle the D main (Tango runtime
> compiler/ldc/rt/dmain2.d, main() function, around line 260):
> 
>     void runMain()
>     {
>         debug(PRINTF) printf("main runMain\n");
>         result = main(args);
>     }
> 
>     void runAll()
>     {
>         debug(PRINTF) printf("main runAll\n");
>         gc_init();
>         _moduleCtor();
>         if (runModuleUnitTests())
>             tryExec(&runMain);
>         thread_joinAll();
>         _d_isHalting = true;
>         _moduleDtor();
>         gc_term();
>     }
> 
>     tryExec(&runAll);
> 
>     debug(PRINTF) printf("main dtor\n");
>     _STD_critical_term();
>     _STD_monitor_staticdtor();
> 
>     return result;
> 
> If thread_joinAll() is called before gc_term(), I can't see how a thread
> could be still running when gc_term() is called. So, in terms of threads,
> I don't see a problem here.

daemon theads are not joined

> About exceptions, I think it could be solved too. One option is to require
> gc_term() to be "nonthrow" (I mean, for D1 and D2). I think the specs
> doesn't say anything about destructors throwing exceptions. I think they
> shouldn't but let's suppose they could. Since there is no way the use can
> catch a destructor exception thrown in the GC (well, not in an useful way,
> one could try/catch the new call or something but that doesn't work for
> concurrent collectors that can sweep in a separate thread anyway, so
> I think it's a bad idea), I guess it would be acceptable to:
> a) Ignore the exception
> b) Let the user provide a callback to handle that kind of exceptions

finalizer should not throw already now, if they do an exception is raised.

> Then, gc_term() ca be moved outside the tryExec(&runAll) call and
> gc_term() can safely call all the live objects finalizers and provide
> guaranteed finalization.
> 
> 
> PS: I have not read all the runtime, just this small part, so maybe I'm
>     missing the big picture =)





More information about the Digitalmars-d mailing list