Open ArthaTi opened 2 years ago
import std;
import core.thread;
import core.memory;
import csprng.system;
void finalizerThread() {
Thread.sleep(100.msecs);
// Start the GC from a thread the generators are not located in
GC.collect();
ownerTid.send("done");
}
void main() {
// Sequentially run two number generators to make one reuse the stack of the other
doRNG();
doRNG();
// Spawn the other thread
spawn(&finalizerThread);
// This is to make sure we get to know about any potential errors in the child thread
receiveOnly!string;
}
void doRNG() {
auto rng = new CSPRNG;
writefln!"%(%.2x%)"(cast(ubyte[]) rng.getBytes(16));
}
When analyzed by GDB, the deadlock can be seen in thread 2 (finalizerThread). If compiled with druntime debug symbols, a _d_throwdwarf
frame at (druntime) src/rt/dwarfeh.d:315
appears to contain an assert error raised specifically at csprng/source/csprng/system.d:497
.
Note the error is the most important part of this; the deadlock itself is caused by a runtime bug. https://issues.dlang.org/show_bug.cgi?id=23253
The class destructor is accessing a thread-local variable
openInstances
. The same class defines invariants, which access said variable. Those get executed before the destructor. The GC can run object finalizers on any thread however (spec), so it may end up accessing an invalid state. This causes the invariants to fail, when they shouldn't.I'll try to provide an MRE soon, if I remember about it.