Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.
/ druntime Public archive
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/core/thread/osthread.d
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
23 changes: 14 additions & 9 deletions src/gc/impl/conservative/gc.d
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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)
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So what happened here? A DLL with running threads was unloaded, terminating them (causing them to segfault)?

Copy link
Member Author

@rainers rainers Oct 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the process terminates while threads are still running. The threads are just terminated as well without DllMain(DLL_THREAD_DETACH) being called. DllMain(DLL_PROCESS_DETACH) is still ìnvoked, though.

stopGC = true;
while (atomicLoad(stoppedThreads) < startedThreads)
while (atomicLoad(stoppedThreads) < startedThreads && !allThreadsDead)
{
evStart.set();
evDone.wait(dur!"msecs"(1));
Expand Down
5 changes: 4 additions & 1 deletion test/gc/Makefile
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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)
22 changes: 22 additions & 0 deletions test/gc/startbackgc.d
Original file line number Diff line number Diff line change
@@ -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();
}