diff --git a/src/core/thread/osthread.d b/src/core/thread/osthread.d index 1470b41e1e..c4cab8acf1 100644 --- a/src/core/thread/osthread.d +++ b/src/core/thread/osthread.d @@ -3805,7 +3805,8 @@ private version (CRuntime_Microsoft) extern(C) extern __gshared ubyte msvcUsesUCRT; // from rt/msvc.c - package(core) __gshared bool thread_DLLProcessDetaching; + /// set during termination of a DLL on Windows, i.e. while executing DllMain(DLL_PROCESS_DETACH) + public __gshared bool thread_DLLProcessDetaching; __gshared HMODULE ll_dllModule; __gshared ThreadID ll_dllMonitorThread; diff --git a/src/gc/impl/conservative/gc.d b/src/gc/impl/conservative/gc.d index 2f1673b76b..e8607243a4 100644 --- a/src/gc/impl/conservative/gc.d +++ b/src/gc/impl/conservative/gc.d @@ -2597,6 +2597,15 @@ struct Gcx //printf("\tpool address range = %p .. %p\n", minAddr, maxAddr); { + version (COLLECT_PARALLEL) + { + bool doParallel = config.parallel > 0; + if (doParallel && !scanThreadData) + startScanThreads(); + } + else + enum doParallel = false; + // lock roots and ranges around suspending threads b/c they're not reentrant safe rangesLock.lock(); rootsLock.lock(); @@ -2615,11 +2624,6 @@ struct Gcx prepTime += (stop - start); start = stop; - version (COLLECT_PARALLEL) - bool doParallel = config.parallel > 0; - else - enum doParallel = false; - if (doParallel) { version (COLLECT_PARALLEL) @@ -2744,9 +2748,6 @@ struct Gcx void** pbot = toscanRoots._p; void** ptop = toscanRoots._p + toscanRoots._length; - if (!scanThreadData) - startScanThreads(); - debug(PARALLEL_PRINTF) printf("markParallel\n"); size_t pointersPerThread = toscanRoots._length / (numScanThreads + 1); @@ -2869,8 +2870,12 @@ struct Gcx if (scanThreadData[idx].tid != scanThreadData[idx].tid.init) startedThreads++; + version (Windows) + alias allThreadsDead = thread_DLLProcessDetaching; + else + enum allThreadsDead = false; stopGC = true; - while (atomicLoad(stoppedThreads) < startedThreads) + while (atomicLoad(stoppedThreads) < startedThreads && !allThreadsDead) { evStart.set(); evDone.wait(dur!"msecs"(1)); diff --git a/test/gc/Makefile b/test/gc/Makefile index 7a81cfd49f..935d046ce0 100644 --- a/test/gc/Makefile +++ b/test/gc/Makefile @@ -1,6 +1,6 @@ include ../common.mak -TESTS := sentinel printf memstomp invariant logging precise precisegc forkgc forkgc2 sigmaskgc +TESTS := sentinel printf memstomp invariant logging precise precisegc forkgc forkgc2 sigmaskgc startbackgc SRC_GC = ../../src/gc/impl/conservative/gc.d SRC = $(SRC_GC) ../../src/rt/lifetime.d @@ -46,5 +46,8 @@ $(ROOT)/forkgc2: forkgc2.d $(ROOT)/sigmaskgc: sigmaskgc.d $(DMD) $(UDFLAGS) -of$@ sigmaskgc.d +$(ROOT)/startbackgc: startbackgc.d + $(DMD) $(UDFLAGS) -of$@ sigmaskgc.d + clean: rm -rf $(ROOT) diff --git a/test/gc/startbackgc.d b/test/gc/startbackgc.d new file mode 100644 index 0000000000..bf51fbdbef --- /dev/null +++ b/test/gc/startbackgc.d @@ -0,0 +1,22 @@ +// https://issues.dlang.org/show_bug.cgi?id=20270 +import core.sys.posix.sys.wait : waitpid; +import core.sys.posix.unistd : fork, _exit; +import core.thread : Thread; + +void main() +{ + foreach (t; 0 .. 10) + new Thread({ + foreach (n; 0 .. 100) + { + foreach (x; 0 .. 100) + new ubyte[x]; + auto f = fork(); + assert(f >= 0); + if (f == 0) + _exit(0); + else + waitpid(f, null, 0); + } + }).start(); +}