Skip to content

Commit 64a361a

Browse files
committed
Stop asserting that threads are not created during deferred ctors
It's valid for constructors to create threads, so we should allow it. A potentially problematic case (already handled by locking the deferred constructor list) is where the constructor calls dlopen and triggers further constructor calls, so add test coverage for it, The new test is just a copy of filc/tests/concurrentloadstress with the body of main() moved to a constructor.
1 parent f1e9adf commit 64a361a

File tree

5 files changed

+4086
-1
lines changed

5 files changed

+4086
-1
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include <stdfil.h>
2+
#include <unistd.h>
3+
#include <sched.h>
4+
#include <stdbool.h>
5+
6+
static void foo(void) __attribute__((constructor));
7+
8+
static void foo(void)
9+
{
10+
zprintf("gctor: gonna sleep a bit.\n");
11+
sched_yield();
12+
zprintf("gctor: done.\n");
13+
}
14+
15+
void bar(void)
16+
{
17+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
puts "libraries:"
2+
1000.times {
3+
| index |
4+
puts " gctor#{index}.so:"
5+
puts " isBundle: true"
6+
puts " files:"
7+
puts " - gctor.c"
8+
}
9+
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#include <stdfil.h>
2+
#include <dlfcn.h>
3+
#include <pthread.h>
4+
#include <stdlib.h>
5+
#include <stdbool.h>
6+
7+
#define N 1000
8+
9+
static void do_stuff(const char* name, const char* so, const char* sym)
10+
{
11+
zprintf("%s: loading %s\n", name, so);
12+
void* lib = dlopen(so, RTLD_LAZY | RTLD_LOCAL);
13+
zprintf("%s: lib = %p\n", name, lib);
14+
if (!lib)
15+
zprintf("%s: error: %s\n", name, dlerror());
16+
zprintf("%s: dlsymming.\n", name);
17+
void (*bar)(void) = dlsym(lib, sym);
18+
zprintf("%s: %s = %p\n", name, sym, bar);
19+
if (!bar)
20+
zprintf("%s: error: %s\n", name, dlerror());
21+
zprintf("%s: calling %s.\n", name, sym);
22+
bar();
23+
}
24+
25+
static void* thread_main(void* arg)
26+
{
27+
unsigned i;
28+
for (i = N / 2; i--;) {
29+
do_stuff(
30+
"thread",
31+
zasprintf("filc/test-output/concurrentloadstress3/gctor%u.so", i + N / 2),
32+
"bar");
33+
}
34+
return NULL;
35+
}
36+
37+
int main()
38+
{
39+
return 0;
40+
}
41+
42+
__attribute__((constructor)) static void foo(void)
43+
{
44+
pthread_t t;
45+
pthread_create(&t, NULL, thread_main, NULL);
46+
47+
unsigned i;
48+
for (i = N / 2; i--;)
49+
do_stuff("main", zasprintf("filc/test-output/concurrentloadstress3/gctor%u.so", i), "bar");
50+
51+
pthread_join(t, NULL);
52+
}
53+

0 commit comments

Comments
 (0)