diff --git a/libphobos/ChangeLog b/libphobos/ChangeLog index f1b76bb88d2..0d937e02bfc 100644 --- a/libphobos/ChangeLog +++ b/libphobos/ChangeLog @@ -1,3 +1,11 @@ +2019-04-25 Iain Buclaw + + PR d/90250 + * libdruntime/gcc/sections/elf_shared.d (initTLSRanges): Populate + _tlsRanges in every startup thread. + * testsuite/libphobos.thread/thread.exp: Load libphobos-dg.exp. + * testsuite/libphobos.thread/tlsgc_sections.d: New test. + 2019-04-25 Rainer Orth * m4/druntime/cpu.m4 (DRUNTIME_CPU_SOURCES): Quote brackets. diff --git a/libphobos/libdruntime/gcc/sections/elf_shared.d b/libphobos/libdruntime/gcc/sections/elf_shared.d index 3a2c85cba64..1eafecdd322 100644 --- a/libphobos/libdruntime/gcc/sections/elf_shared.d +++ b/libphobos/libdruntime/gcc/sections/elf_shared.d @@ -308,7 +308,13 @@ else */ Array!(void[])* initTLSRanges() nothrow @nogc { - return &_tlsRanges(); + auto rngs = &_tlsRanges(); + if (rngs.empty) + { + foreach (ref pdso; _loadedDSOs) + rngs.insertBack(pdso.tlsRange()); + } + return rngs; } void finiTLSRanges(Array!(void[])* rngs) nothrow @nogc diff --git a/libphobos/testsuite/libphobos.thread/thread.exp b/libphobos/testsuite/libphobos.thread/thread.exp index d35df567ab3..3e760d3e370 100644 --- a/libphobos/testsuite/libphobos.thread/thread.exp +++ b/libphobos/testsuite/libphobos.thread/thread.exp @@ -14,6 +14,8 @@ # along with GCC; see the file COPYING3. If not see # . +load_lib libphobos-dg.exp + # Initialize dg. dg-init diff --git a/libphobos/testsuite/libphobos.thread/tlsgc_sections.d b/libphobos/testsuite/libphobos.thread/tlsgc_sections.d new file mode 100644 index 00000000000..1421d926a38 --- /dev/null +++ b/libphobos/testsuite/libphobos.thread/tlsgc_sections.d @@ -0,0 +1,39 @@ +final class Class +{ + // This gets triggered although the instance always stays referenced. + ~this() + { + import core.stdc.stdlib; + abort(); + } +} + +Class obj; + +static this() +{ + obj = new Class; +} + +static ~this() +{ + // Free without destruction to avoid triggering abort() + import core.memory; + GC.free(cast(void*)obj); +} + +void doit() +{ + foreach (i; 0 .. 10_000) + new ubyte[](100_000); +} + +void main() +{ + import core.thread; + auto t = new Thread(&doit); + t.start(); + + // This triggers the GC that frees the still referenced Class instance. + doit(); +}