Bug 15353 – std.experimental.allocator cannot free memory in its destructor if the GC is an ancestor

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2015-11-17T18:44:19Z
Last change time
2018-01-05T13:27:16Z
Assigned to
No Owner
Creator
Andrei Alexandrescu

Comments

Comment #0 by andrei — 2015-11-17T18:44:19Z
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().
Comment #1 by github-bugzilla — 2016-03-13T19:31:51Z
Commits pushed to master at https://github.com/D-Programming-Language/druntime https://github.com/D-Programming-Language/druntime/commit/1113bf1476ca66bac8a25bea4598daf6fb4bd598 fix Issue 15353 - ignore freeing during finalization https://github.com/D-Programming-Language/druntime/commit/f7604efbc6572ce62a8f0e5617b42d65815979bb Merge pull request #1508 from MartinNowak/fix15353 fix Issue 15353 - ignore freeing during finalization
Comment #2 by github-bugzilla — 2016-03-19T20:21:29Z
Comment #3 by github-bugzilla — 2018-01-05T13:27:16Z
Commits pushed to dmd-cxx at https://github.com/dlang/druntime https://github.com/dlang/druntime/commit/1113bf1476ca66bac8a25bea4598daf6fb4bd598 fix Issue 15353 - ignore freeing during finalization https://github.com/dlang/druntime/commit/f7604efbc6572ce62a8f0e5617b42d65815979bb Merge pull request #1508 from MartinNowak/fix15353