www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 4104] New: No way to get notified about D runtime termination.

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4104

           Summary: No way to get notified about D runtime termination.
           Product: D
           Version: unspecified
          Platform: Other
        OS/Version: Linux
            Status: NEW
          Severity: critical
          Priority: P2
         Component: druntime
        AssignedTo: sean invisibleduck.org
        ReportedBy: samukha voliacable.com



PDT ---
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.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Apr 19 2010
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4104


Sean Kelly <sean invisibleduck.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |ASSIGNED



---
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?

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jul 20 2010
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4104




PDT ---
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.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jul 22 2010