Description
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 an io::Error
of kind WouldBlock
.
extern crate libc;
fn main() {
unsafe {
libc::setrlimit(libc::RLIMIT_NPROC, &libc::rlimit { rlim_cur: 0, rlim_max: 0 });
}
let error = std::thread::Builder::new().spawn(|| unreachable!()).unwrap_err();
println!("I/O error kind {:?}: {:?}", error.kind(), error);
}
This prints (on Linux):
I/O error kind WouldBlock: Error { repr: Os { code: 11, message: "Resource temporarily unavailable" } }
The operation needs to block to complete, but the blocking operation was requested to not occur.
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
and EWOULDBLOCK
may be defined as the same error value, and Rust chose to always interpret that as EWOULDBLOCK
. 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
returns ERROR_NOT_ENOUGH_MEMORY
, which gets decoded as kind Other
)