Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stack usage when using task::unowned in debug builds #4202

Closed
sander2 opened this issue Oct 28, 2021 · 3 comments
Closed

Stack usage when using task::unowned in debug builds #4202

sander2 opened this issue Oct 28, 2021 · 3 comments
Labels
A-tokio Area: The main tokio crate C-bug Category: This is a bug. M-task Module: tokio/task

Comments

@sander2
Copy link
Contributor

sander2 commented Oct 28, 2021

Version
Tokio 1.12

Platform
Linux kernel 5.11 (Ubuntu)

Description

I ran into a stack overflow in my application, and I think one of the contributing factors might be tokio's stack usage. Similarly to #2055, I think I see that creating a task throught the unowned function goes through several layers of functions, each consuming creating a copy of the task on the stack before finally allocating it. The function sequence is as follows:

As in #2055, my code runs fine when i compile with --release, but gets a stack overflow in the code above otherwise. I am not very familiar with assembly, so I could be completely wrong in thinking that the callstack above leads to a lot of duplication of the stack-allocated task data, and I'm also not sure how feasible it would be to optimize this, so feel free to close if this is not something you can address. For now, I will just try to reserve more stack space.

@sander2 sander2 added A-tokio Area: The main tokio crate C-bug Category: This is a bug. labels Oct 28, 2021
@Darksonn Darksonn added the M-task Module: tokio/task label Oct 28, 2021
@Darksonn
Copy link
Contributor

We already have some code for spawned tasks to avoid this here:

// preventing stack overflows on debug mode, by quickly sending the
// task to the heap.
if cfg!(debug_assertions) && std::mem::size_of::<T>() > 2048 {
spawn_inner(Box::pin(future), None)
} else {
spawn_inner(future, None)
}

However if you are using task::unowned, then you must be using spawn_blocking, in which case you don't hit the above piece of code. We could add the same to spawn_blocking.

@sander2
Copy link
Contributor Author

sander2 commented Oct 28, 2021

We already have some code for spawned tasks to avoid this here:

// preventing stack overflows on debug mode, by quickly sending the
// task to the heap.
if cfg!(debug_assertions) && std::mem::size_of::<T>() > 2048 {
spawn_inner(Box::pin(future), None)
} else {
spawn_inner(future, None)
}

However if you are using task::unowned, then you must be using spawn_blocking, in which case you don't hit the above piece of code. We could add the same to spawn_blocking.

Thanks for the quick reply, I made a PR to do just this

@Darksonn
Copy link
Contributor

Closed by #4203.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-tokio Area: The main tokio crate C-bug Category: This is a bug. M-task Module: tokio/task
Projects
None yet
Development

No branches or pull requests

2 participants