Skip to content

Commit 9dd97ba

Browse files
authored
Unlock DTORS before calling the dtor functions. (#145)
This allows dtor functions to add more dtor functions. And, don't unlock `DTORS` when we're done with it, so that nothing else tries to access it.
1 parent c929f7d commit 9dd97ba

File tree

5 files changed

+163
-0
lines changed

5 files changed

+163
-0
lines changed

src/program/linux_raw.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,11 +278,18 @@ pub fn exit(status: c_int) -> ! {
278278
let dtors = unsafe { &mut *DTORS.0.get() };
279279

280280
if let Some(func) = dtors.pop() {
281+
// Unlock `DTORS` before calling `func`.
282+
drop(dtors);
283+
281284
#[cfg(feature = "log")]
282285
log::trace!("Calling `at_exit`-registered function");
283286

284287
func();
285288
} else {
289+
// Now that we're done processing `DTORS`, leak the lock, since
290+
// from this point on, nothing should try to add anything to it.
291+
#[cfg(feature = "thread")]
292+
core::mem::forget(dtors);
286293
break;
287294
}
288295
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//! Test main thread dtors that add new dtors.
2+
3+
#![no_std]
4+
#![no_main]
5+
6+
extern crate alloc;
7+
8+
use alloc::boxed::Box;
9+
use core::sync::atomic::{AtomicBool, Ordering};
10+
use origin::thread;
11+
12+
#[global_allocator]
13+
static GLOBAL_ALLOCATOR: rustix_dlmalloc::GlobalDlmalloc = rustix_dlmalloc::GlobalDlmalloc;
14+
15+
static FLAG: AtomicBool = AtomicBool::new(false);
16+
17+
#[no_mangle]
18+
unsafe fn origin_main(_argc: usize, _argv: *mut *mut u8, _envp: *mut *mut u8) -> i32 {
19+
thread::at_exit(Box::new(|| {
20+
assert!(FLAG.load(Ordering::Relaxed));
21+
}));
22+
23+
thread::at_exit(Box::new(|| {
24+
thread::at_exit(Box::new(|| {
25+
thread::at_exit(Box::new(|| {
26+
FLAG.store(true, Ordering::Relaxed);
27+
}));
28+
}));
29+
}));
30+
31+
thread::at_exit(Box::new(|| {
32+
assert!(!FLAG.load(Ordering::Relaxed));
33+
}));
34+
35+
0
36+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//! Test program dtors that add new dtors.
2+
3+
#![no_std]
4+
#![no_main]
5+
6+
extern crate alloc;
7+
8+
use alloc::boxed::Box;
9+
use core::sync::atomic::{AtomicBool, Ordering};
10+
use origin::program;
11+
12+
#[global_allocator]
13+
static GLOBAL_ALLOCATOR: rustix_dlmalloc::GlobalDlmalloc = rustix_dlmalloc::GlobalDlmalloc;
14+
15+
static FLAG: AtomicBool = AtomicBool::new(false);
16+
17+
#[no_mangle]
18+
unsafe fn origin_main(_argc: usize, _argv: *mut *mut u8, _envp: *mut *mut u8) -> i32 {
19+
program::at_exit(Box::new(|| {
20+
assert!(FLAG.load(Ordering::Relaxed));
21+
}));
22+
23+
program::at_exit(Box::new(|| {
24+
program::at_exit(Box::new(|| {
25+
program::at_exit(Box::new(|| {
26+
FLAG.store(true, Ordering::Relaxed);
27+
}))
28+
}))
29+
}));
30+
31+
program::at_exit(Box::new(|| {
32+
assert!(!FLAG.load(Ordering::Relaxed));
33+
}));
34+
35+
0
36+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//! Test thread dtors that add new dtors.
2+
3+
#![no_std]
4+
#![no_main]
5+
6+
extern crate alloc;
7+
8+
use alloc::boxed::Box;
9+
use core::sync::atomic::{AtomicBool, Ordering};
10+
use origin::thread;
11+
12+
#[global_allocator]
13+
static GLOBAL_ALLOCATOR: rustix_dlmalloc::GlobalDlmalloc = rustix_dlmalloc::GlobalDlmalloc;
14+
15+
static FLAG: AtomicBool = AtomicBool::new(false);
16+
17+
#[no_mangle]
18+
unsafe fn origin_main(_argc: usize, _argv: *mut *mut u8, _envp: *mut *mut u8) -> i32 {
19+
let thread = thread::create(
20+
|_args| {
21+
thread::at_exit(Box::new(|| {
22+
assert!(FLAG.load(Ordering::Relaxed));
23+
}));
24+
25+
thread::at_exit(Box::new(|| {
26+
thread::at_exit(Box::new(|| {
27+
thread::at_exit(Box::new(|| {
28+
FLAG.store(true, Ordering::Relaxed);
29+
}));
30+
}));
31+
}));
32+
33+
thread::at_exit(Box::new(|| {
34+
assert!(!FLAG.load(Ordering::Relaxed));
35+
}));
36+
37+
None
38+
},
39+
&[],
40+
thread::default_stack_size(),
41+
thread::default_guard_size(),
42+
)
43+
.unwrap();
44+
45+
thread::join(thread);
46+
47+
0
48+
}

tests/test_crates.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,39 @@ fn test_detach() {
8787
fn test_canary() {
8888
test_crate("origin-start", &["--bin=canary"], &[], "", "", Some(203));
8989
}
90+
91+
#[test]
92+
fn test_program_dtors_adding_dtors() {
93+
test_crate(
94+
"origin-start",
95+
&["--bin=program-dtors-adding-dtors"],
96+
&[],
97+
"",
98+
"",
99+
Some(0),
100+
);
101+
}
102+
103+
#[test]
104+
fn test_thread_dtors_adding_dtors() {
105+
test_crate(
106+
"origin-start",
107+
&["--bin=thread-dtors-adding-dtors"],
108+
&[],
109+
"",
110+
"",
111+
Some(0),
112+
);
113+
}
114+
115+
#[test]
116+
fn test_main_thread_dtors_adding_dtors() {
117+
test_crate(
118+
"origin-start",
119+
&["--bin=main-thread-dtors-adding-dtors"],
120+
&[],
121+
"",
122+
"",
123+
Some(0),
124+
);
125+
}

0 commit comments

Comments
 (0)