Skip to content

Commit f7f1490

Browse files
committed
rt: Run resource destructors during cycle collection
1 parent f3fe85d commit f7f1490

File tree

4 files changed

+90
-0
lines changed

4 files changed

+90
-0
lines changed

src/rt/rust_cc.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,9 +565,26 @@ class sweep : public shape::data<sweep,shape::ptr> {
565565
}
566566
}
567567

568+
struct run_dtor_args {
569+
const shape::rust_fn *dtor;
570+
void *data;
571+
};
572+
573+
typedef void (*dtor)(void **retptr, void *env, void *dptr);
574+
575+
static void run_dtor(run_dtor_args *args) {
576+
dtor f = (dtor)args->dtor;
577+
f(NULL, args->dtor->env, args->data);
578+
}
579+
568580
void walk_res2(const shape::rust_fn *dtor, unsigned n_params,
569581
const shape::type_param *params, const uint8_t *end_sp,
570582
bool live) {
583+
void *data = (void*)(uintptr_t)dp;
584+
// Switch back to the Rust stack to run the destructor
585+
run_dtor_args args = {dtor, data};
586+
task->call_on_rust_stack((void*)&args, (void*)run_dtor);
587+
571588
while (this->sp != end_sp) {
572589
this->walk();
573590
align = true;

src/rt/rust_task.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ rust_task : public kernel_owned<rust_task>, rust_cond
252252
void prev_stack();
253253
void record_stack_limit();
254254
void reset_stack_limit();
255+
255256
bool on_rust_stack();
256257
void check_stack_canary();
257258
void delete_all_stacks();
@@ -334,6 +335,7 @@ inline void
334335
rust_task::call_on_rust_stack(void *args, void *fn_ptr) {
335336
// Too expensive to check
336337
// I(thread, !on_rust_stack());
338+
A(thread, get_sp_limit() != 0, "Stack must be configured");
337339
I(thread, next_rust_sp);
338340

339341
bool had_reentered_rust_stack = reentered_rust_stack;
@@ -344,6 +346,8 @@ rust_task::call_on_rust_stack(void *args, void *fn_ptr) {
344346

345347
uintptr_t sp = sanitize_next_sp(next_rust_sp);
346348

349+
// FIXME(2047): There are times when this is called and needs
350+
// to be able to throw, and we don't account for that.
347351
__morestack(args, fn_ptr, sp);
348352

349353
next_c_sp = prev_c_sp;

src/test/run-pass/resource-cycle.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Don't leak the unique pointers
2+
3+
resource r(v: *int) unsafe {
4+
let v2: ~int = unsafe::reinterpret_cast(v);
5+
}
6+
7+
enum t = {
8+
mut next: option<@t>,
9+
r: r
10+
};
11+
12+
fn main() unsafe {
13+
let i1 = ~0;
14+
let i1p = unsafe::reinterpret_cast(i1);
15+
unsafe::forget(i1);
16+
let i2 = ~0;
17+
let i2p = unsafe::reinterpret_cast(i2);
18+
unsafe::forget(i2);
19+
20+
let x1 = @t({
21+
mut next: none,
22+
r: r(i1p)
23+
});
24+
let x2 = @t({
25+
mut next: none,
26+
r: r(i2p)
27+
});
28+
x1.next = some(x2);
29+
x2.next = some(x1);
30+
}

src/test/run-pass/resource-cycle2.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Don't leak the unique pointers
2+
3+
type u = {
4+
a: int,
5+
b: int,
6+
c: *int
7+
};
8+
9+
resource r(v: u) unsafe {
10+
let v2: ~int = unsafe::reinterpret_cast(v.c);
11+
}
12+
13+
enum t = {
14+
mut next: option<@t>,
15+
r: r
16+
};
17+
18+
fn main() unsafe {
19+
let i1 = ~0xA;
20+
let i1p = unsafe::reinterpret_cast(i1);
21+
unsafe::forget(i1);
22+
let i2 = ~0xA;
23+
let i2p = unsafe::reinterpret_cast(i2);
24+
unsafe::forget(i2);
25+
26+
let u1 = {a: 0xB, b: 0xC, c: i1p};
27+
let u2 = {a: 0xB, b: 0xC, c: i2p};
28+
29+
let x1 = @t({
30+
mut next: none,
31+
r: r(u1)
32+
});
33+
let x2 = @t({
34+
mut next: none,
35+
r: r(u2)
36+
});
37+
x1.next = some(x2);
38+
x2.next = some(x1);
39+
}

0 commit comments

Comments
 (0)