Bug 4104 – No way to get notified about D runtime termination.

Status
ASSIGNED
Severity
critical
Priority
P2
Component
druntime
Product
D
Version
D2
Platform
All
OS
All
Creation time
2010-04-19T06:07:29Z
Last change time
2024-12-07T13:30:57Z
Keywords
patch
Assigned to
Sean Kelly
Creator
Max Samukha
Moved to GitHub: dmd#17224 →

Comments

Comment #0 by samukha — 2010-04-19T06:07:29Z
Qt classes have corresponding D wrappers in QtD. For many Qt classes we can avoid creating duplicate wrappers (or searching a wrapper cache) and store the D wrapper pointers directly in the C++ objects. When Qt takes ownership of such an object, QtD disables garbage collection for the D wrapper by adding its reference to the GC roots. When later Qt deletes the object, a callback to D is emitted, during which the wrapper is destroyed. Everything works well unless the C++ object is statically allocated or is owned by a statically allocated object. If it is, the C++ destructor is called *after* the D runtime has been terminated, meaning GC pools has been freed and there is no wrapper to delete. One solution is to have a flag that would be set after the D runtime has been terminated. Then we could avoid deleting already freed wrappers by checking the flag in the callback. Patch for druntime/src/rt/dmain2.d: @@ -165,12 +165,18 @@ } shared bool _d_isHalting = false; +shared bool _d_isTerminated = false; extern (C) bool rt_isHalting() { return _d_isHalting; } +extern (C) bool rt_isTerminated() +{ + return _d_isTerminated; +} + // This variable is only ever set by a debugger on initialization so it should // be fine to leave it as __gshared. extern (C) __gshared bool rt_trapExceptions = true; @@ -244,6 +250,7 @@ finally { _d_criticalTerm(); + _d_isTerminated = true; } return false; } @@ -404,5 +411,7 @@ _STD_critical_term(); _STD_monitor_staticdtor(); } + + _d_isTerminated = true; return result; } Another solution would be a notification. Tests show that 'atexit' doesn't work for us because the handlers registered with 'atexit' are invoked after the destructors has been run. So we need a separate notification. Even better solution: don't free the GC memory on exit and give the rooted objects a chance to be finalized properly. This is critical.
Comment #1 by sean — 2010-07-20T15:09:44Z
Is this something that can be addressed via a shared module dtor, or is that too early/late in the termination process? isHalting seems of limited utility so I tentatively deprecated it, but perhaps it should be replaced by a status field instead?
Comment #2 by samukha — 2010-07-22T01:21:54Z
I am afraid it is too early. The problem is that during the final GC cycle wrappers owned by D (subject to garbage collection) will be destroyed. As part of their destruction process, they will destroy their corresponding C++ objects, which may destroy other C++ objects, which will destroy their D wrappers (those added to roots). Though I am not entirely sure whether the last-mentioned wrappers need to be destroyed at program exit, I tend to think they do, just like the wrapper that owns them (that is the one that indirectly causes their destruction). From the above follows that we need to know when the final GC cycle has been finished, so that QtD doesn't try to destroy wrappers for the C++ objects that survived that cycle. Obviously isHalting does not help here because it is set before the GC cycle is initiated. A field of an enum type indicating the current runtime state would be great.
Comment #3 by dlang-bugzilla — 2017-07-21T04:49:06Z
If this enhancement request is still actual today, please submit the patch as a pull request; otherwise, it's unlikely anything will be done about it. I'll leave this open because it doesn't seem too unlikely that another project will require a similar addition, in which case having an existing issue could be useful.
Comment #4 by maxsamukha — 2020-05-26T08:56:01Z
QtD is dead. This can be closed if nobody else needs it.
Comment #5 by robert.schadek — 2024-12-07T13:30:57Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/17224 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB