tokio icon indicating copy to clipboard operation
tokio copied to clipboard

Stack overflow in release builds with large futures

Open mathieulj opened this issue 9 months ago • 2 comments

Version

❯ cargo tree | rg tokio
repro-tokio v0.1.0 (/Users/mathieuletendre-jauniaux/work/repro-tokio)
└── tokio v1.32.0
    └── tokio-macros v2.1.0 (proc-macro)

Platform

I've observed this on both macos and windows but the problem likely also affects linux.

❯ uname -a
Darwin Mathieus-MacBook-Pro-2.local 23.0.0 Darwin Kernel Version 23.0.0: Fri Sep 15 14:41:43 PDT 2023; root:xnu-10002.1.13~1/RELEASE_ARM64_T6000 arm64

Description

In debug builds, spawn will put futures on the heap but the release behaviour is to just pass it on via the stack. This leads to code that passes tests and runs fine in debug but crashes in production if the futures are sufficiently large.

Reproduction steps:

cargo init --bin repro-tokio
cd repro-tokio
cargo add tokio --features rt-multi-thread,macros,time
# edit main.rs

# doesn't crash
cargo run 

#crashes
cargo run --release
use std::time::Duration;
use tokio::{task, time};

#[tokio::main]
async fn main() {
    println!("This works both in debug and in release");
    let _ = task::spawn(Box::pin(future())).await;

    println!("This compiles but will crash at runtime **only in release builds**");
    let _ = task::spawn(future()).await;
}

async fn future() {
    let data = [0; 200_000];
    time::sleep(Duration::from_millis(100)).await;
    println!("{}", data[22]);
}

I expected to see this happen: Ideally tokio wouldn't overflow the stack ever but it should at minimum have the same behaviour in debug builds as it does in release builds.

Instead, this happened: tokio overflowed the stack only in release builds, test and debug builds work as expected.

mathieulj avatar Oct 06 '23 22:10 mathieulj