[Issue 15353] New: std.experimental.allocator cannot free memory in its destructor if the GC is an ancestor

via Digitalmars-d-bugs digitalmars-d-bugs at puremagic.com
Tue Nov 17 10:44:19 PST 2015


https://issues.dlang.org/show_bug.cgi?id=15353

          Issue ID: 15353
           Summary: std.experimental.allocator cannot free memory in its
                    destructor if the GC is an ancestor
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: normal
          Priority: P1
         Component: dmd
          Assignee: nobody at puremagic.com
          Reporter: andrei at erdani.com

Brian Schott noticed this and wrote:

==============
I've discovered a problem with the interaction between CAllocatorImpl and
GCAllocator: CAllocatorImpl cannot have a parent allocator that uses
GCAllocator, or a parent that has a parent (and so on) that uses GCAllocator.
This is because several of the allocator implementations are structs that
deallocate their memory during their destructors.

In the case of CAllocatorImpl, this destructor call is often caused by the GC.
Calls to the GC fail during destructors called by the GC, so something needs to
be done to fix this. Maybe extra logic can be added to the various allocators
to check that they are not calling GCAllocator during a destructor, or we can
somehow disallow using GC-backed allocators from CAllocatorImpl.

Example:
https://gist.github.com/Hackerpilot/26c2d0e7b1aa0605b344
==============

To which I replied:

==============
I imagine there are a number of ways we can fix this:

(a) Allow freeing memory but not allocation during GC. I'm not sure but I
suspect that it's memory allocation that mustn't be allowed during a GC cycle.
Martin, could you please confirm/deny this?

(b) The GC has or should have a primitive that tells code whether a collection
is in progress. Then allocator destructors can test that and do nothing if
that's the case.

(c) Have the GC itself ignore calls to free during a collection cycle.
==============

To which Martin Nowak replied:

==============
Free also manipulates internal structures.
https://github.com/D-Programming-Language/druntime/blob/12ea1075fc24a5389a4e1aa24ae9e177903f85d2/src/gc/gc.d#L873
https://github.com/D-Programming-Language/druntime/blob/12ea1075fc24a5389a4e1aa24ae9e177903f85d2/src/gc/gc.d#L2245

With the current code, it would be very delicate to allow free during
finalization.

[About having the GC just ignore calls to free during a GC cycle:] 
Seems like a feasible solution for now.

In general the GC isn't reentrant safe, and that will be enforced even
stricter by using a non-recursive lock
https://trello.com/c/Xp44NwHG/87-ttas-spinlock-for-gc.
We do want to get rid of the InvalidMemoryOperation issue, and should
revisit it once the thread caches are implemented. During a collection
it should be possible to queue most operations and serve allocations
(maybe from a separate pool). There are still a lot of rather big
changes planned to the GC before it makes sense to look at this
particular issue.
==============

So it seems a good fix for this bug would be to just have the GC ignore calls
to free().

--


More information about the Digitalmars-d-bugs mailing list