Skip to content

Commit 596376e

Browse files
committed
rt: Allow 2x normal stack during unwinding. Closes #2173
Allows room for destructors to run without allowing the stack to grow forever.
1 parent b42c6d0 commit 596376e

File tree

2 files changed

+35
-12
lines changed

2 files changed

+35
-12
lines changed

src/rt/rust_task.cpp

+12-12
Original file line numberDiff line numberDiff line change
@@ -512,19 +512,19 @@ rust_task::new_stack(size_t requested_sz) {
512512
size_t rust_stk_sz = get_next_stack_size(min_sz,
513513
current_sz, requested_sz);
514514

515-
if (total_stack_sz + rust_stk_sz > kernel->env->max_stack_size) {
515+
size_t max_stack = kernel->env->max_stack_size;
516+
size_t used_stack = total_stack_sz + rust_stk_sz;
517+
518+
// Don't allow stacks to grow forever. During unwinding we have to allow
519+
// for more stack than normal in order to allow destructors room to run,
520+
// arbitrarily selected as 2x the maximum stack size.
521+
if (!unwinding && used_stack > max_stack) {
516522
LOG_ERR(this, task, "task %" PRIxPTR " ran out of stack", this);
517-
if (!unwinding) {
518-
fail();
519-
} else {
520-
// FIXME: Because we have landing pads that may need more
521-
// stack than normally allowed we have to go allow the stack
522-
// to grow unbounded during unwinding. Would be nice to
523-
// have a different solution - maybe just double the limit.
524-
LOG_ERR(this, task, "task %" PRIxPTR " has blown its stack "
525-
"budget but we are unwinding so growing the stack "
526-
"anyway");
527-
}
523+
fail();
524+
} else if (unwinding && used_stack > max_stack) {
525+
LOG_ERR(this, task,
526+
"task %" PRIxPTR " ran out of stack during unwinding", this);
527+
fail();
528528
}
529529

530530
size_t sz = rust_stk_sz + RED_ZONE_SIZE;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// error-pattern:ran out of stack
2+
// xfail-test - right now we leak when we fail during failure
3+
4+
// Test that the task fails after hiting the recursion limit
5+
// durnig unwinding
6+
7+
fn recurse() {
8+
log(debug, "don't optimize me out");
9+
recurse();
10+
}
11+
12+
resource r(recursed: *mut bool) unsafe {
13+
if !*recursed {
14+
*recursed = true;
15+
recurse();
16+
}
17+
}
18+
19+
fn main() {
20+
let mut recursed = false;
21+
let _r = r(ptr::mut_addr_of(recursed));
22+
recurse();
23+
}

0 commit comments

Comments
 (0)