-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
thread::Builder::spawn
returns WouldBlock for EAGAIN
#46345
Comments
…alexcrichton Print a slightly clearer message when failing to launch a thread As discussed in rust-lang#46345, the `io::Error` you get when a thread fails to launch is of type `io::ErrorKind::WouldBlock`. This is super uninformative when an arbitrary `thread::spawn` fails somewhere in your code: ``` thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 11, kind: WouldBlock, message: "operation would block" }', src/libcore/result.rs:997:5 ``` This PR improves the situation a little bit by using `expect` instead of `unwrap`. I don't consider this a complete fix for rust-lang#46345 though.
…alexcrichton Print a slightly clearer message when failing to launch a thread As discussed in rust-lang#46345, the `io::Error` you get when a thread fails to launch is of type `io::ErrorKind::WouldBlock`. This is super uninformative when an arbitrary `thread::spawn` fails somewhere in your code: ``` thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 11, kind: WouldBlock, message: "operation would block" }', src/libcore/result.rs:997:5 ``` This PR improves the situation a little bit by using `expect` instead of `unwrap`. I don't consider this a complete fix for rust-lang#46345 though.
In rr we automatically retry Linux |
The only thing we currently do this for widely is |
If the process has reached its limit on how many threads it is allowed to have, it does not seem wise to just hot-spin trying to make a new one forever. |
I observed this error when I was much below the limit of threads, but I was creating them very quickly. fn go() {
std::thread::sleep(std::time::Duration::from_millis(10000));
}
fn main() {
let mut cnt = 0;
loop {
match std::thread::Builder::new().spawn(go) {
Ok(_) => cnt += 1,
Err(e) => {
println!("error: {:?} {:?}", e.kind(), e);
println!("cnt {}", cnt);
return
}
}
}
} results in
|
True. Backing off for a second would probably be fine. |
I've only tried under a VM but fwiw I'm not able to reproduce This on my system reaches the thread limit reliably without transient failures. Transient failures would cause use std::{
io::ErrorKind,
mem::forget,
thread::{sleep, Builder},
time::Duration,
};
fn idle() {
loop {
sleep(Duration::from_secs(60));
}
}
fn main() {
let mut threads = 0;
let mut stuck = false;
loop {
match Builder::new().stack_size(4096).spawn(idle) {
Ok(handle) => {
threads += 1;
if stuck {
println!("progress after {}", threads);
}
stuck = false;
forget(handle);
}
Err(ref err) if err.kind() == ErrorKind::WouldBlock => {
if !stuck {
println!("wouldblock after {}", threads);
}
stuck = true;
sleep(Duration::from_millis(100));
}
Err(e) => {
panic!("{}: {:?}", threads, e.kind());
}
}
}
} It's possible that thread limits are lower than people are expecting. In particular, |
My GitHub Actions workflow often fails because libtest failed to spawn new threads. Log
|
There are three separate issues mentioned here:
I would like to have this issue only track the third problem. |
thread::Builder::spawn
returns WouldBlock for EAGAIN
Renamed issue to reflect (3). |
Assigning |
|
When trying to launch a thread and the thread limit is reached or there is not enough virtual address space available for another thread,
thread::Builder::spawn
returns anio::Error
of kindWouldBlock
.This prints (on Linux):
WouldBlock means:
This doesn't make a lot of sense in the context of thread creation. Yes, if the create call were to block until the thread/virtual address space limit is no longer reached, this error interpretation would be correct, but I know of no threading API (Windows or Linux) with these semantics.
The source of the problem is that the POSIX errors
EAGAIN
andEWOULDBLOCK
may be defined as the same error value, and Rust chose to always interpret that asEWOULDBLOCK
. I'm not sure what course of action I'd suggest to clear up the confusion.(NB. On Windows, AFAICT there is no way to limit the number of threads, but when running out of virtual address space,
CreateThread
returnsERROR_NOT_ENOUGH_MEMORY
, which gets decoded as kindOther
)The text was updated successfully, but these errors were encountered: