aboutsummaryrefslogtreecommitdiff
path: root/libphobos/testsuite/libphobos.thread/tlsgc_sections.d
blob: b0807ec6ff15993b8e38dbcebc81050814c8bbb8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import core.memory;
import core.sync.condition;
import core.sync.mutex;
import core.thread;

__gshared Condition g_cond;
__gshared Mutex g_mutex;
__gshared int g_step = 0;

class C
{
    ~this()
    {
        import core.stdc.stdlib : abort;
        abort();    // this gets triggered although the instance always stays referenced
    }
}

C c;

static this()
{
    c = new C;
}

static ~this()
{
    import core.memory;
    GC.free(cast(void*)c); // free without destruction to avoid triggering abort()
}

void test()
{
    assert(c !is null);

    // notify the main thread of the finished initialization
    synchronized (g_mutex) g_step = 1;
    g_cond.notifyAll();

    // wait until the GC collection is done
    synchronized (g_mutex) {
        while (g_step != 2)
            g_cond.wait();
    }
}


void main()
{
    g_mutex = new Mutex;
    g_cond = new Condition(g_mutex);

    auto th = new Thread(&test);
    th.start();

    // wait for thread to be fully initialized
    synchronized (g_mutex) {
        while (g_step != 1)
            g_cond.wait();
    }

    // this causes the other thread's C instance to be reaped with the bug present
    GC.collect();

    // allow the thread to shut down
    synchronized (g_mutex) g_step = 2;
    g_cond.notifyAll();

    th.join();
}