diff options
| author | Dylan DPC <dylan.dpc@gmail.com> | 2021-02-18 16:57:33 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-02-18 16:57:33 +0100 |
| commit | 55ab2e38797ad1661ff4cfa95074a3d81636fde0 (patch) | |
| tree | f0e24335cc00fb698c7aeab728539113bf1da127 | |
| parent | cb2effd44e667d133e31ef334e30d10195218ce6 (diff) | |
| parent | 43aed7441ee289c6228ecead91ee66245122b880 (diff) | |
| download | rust-55ab2e38797ad1661ff4cfa95074a3d81636fde0.tar.gz rust-55ab2e38797ad1661ff4cfa95074a3d81636fde0.zip | |
Rollup merge of #81546 - hyd-dev:libtest-run-out-of-threads, r=Mark-Simulacrum
[libtest] Run the test synchronously when hitting thread limit
libtest currently panics if it hits the thread limit. This often results in spurious test failures (<code>thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 11, kind: WouldBlock, message: "Resource temporarily unavailable" }'</code> ... `error: test failed, to rerun pass '--lib'`). This PR makes it continue to run the test synchronously if it runs out of threads.
Closes #78165.
``@rustbot`` label: A-libtest T-libs
| -rw-r--r-- | library/test/src/lib.rs | 13 | ||||
| -rw-r--r-- | src/test/run-make/libtest-thread-limit/Makefile | 7 | ||||
| -rw-r--r-- | src/test/run-make/libtest-thread-limit/test.rs | 16 |
3 files changed, 35 insertions, 1 deletions
diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index c38a8c965be..ae38030d497 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -506,7 +506,18 @@ pub fn run_test( let supports_threads = !cfg!(target_os = "emscripten") && !cfg!(target_arch = "wasm32"); if concurrency == Concurrent::Yes && supports_threads { let cfg = thread::Builder::new().name(name.as_slice().to_owned()); - Some(cfg.spawn(runtest).unwrap()) + let mut runtest = Arc::new(Mutex::new(Some(runtest))); + let runtest2 = runtest.clone(); + match cfg.spawn(move || runtest2.lock().unwrap().take().unwrap()()) { + Ok(handle) => Some(handle), + Err(e) if e.kind() == io::ErrorKind::WouldBlock => { + // `ErrorKind::WouldBlock` means hitting the thread limit on some + // platforms, so run the test synchronously here instead. + Arc::get_mut(&mut runtest).unwrap().get_mut().unwrap().take().unwrap()(); + None + } + Err(e) => panic!("failed to spawn thread to run test: {}", e), + } } else { runtest(); None diff --git a/src/test/run-make/libtest-thread-limit/Makefile b/src/test/run-make/libtest-thread-limit/Makefile new file mode 100644 index 00000000000..29c1bc71d87 --- /dev/null +++ b/src/test/run-make/libtest-thread-limit/Makefile @@ -0,0 +1,7 @@ +-include ../../run-make-fulldeps/tools.mk + +# only-linux + +all: + $(RUSTC) test.rs --test --target $(TARGET) + $(shell ulimit -p 0 && $(call RUN,test)) diff --git a/src/test/run-make/libtest-thread-limit/test.rs b/src/test/run-make/libtest-thread-limit/test.rs new file mode 100644 index 00000000000..d899411a49e --- /dev/null +++ b/src/test/run-make/libtest-thread-limit/test.rs @@ -0,0 +1,16 @@ +#![feature(once_cell)] + +use std::{io::ErrorKind, lazy::SyncOnceCell, thread::{self, Builder, ThreadId}}; + +static THREAD_ID: SyncOnceCell<ThreadId> = SyncOnceCell::new(); + +#[test] +fn spawn_thread_would_block() { + assert_eq!(Builder::new().spawn(|| unreachable!()).unwrap_err().kind(), ErrorKind::WouldBlock); + THREAD_ID.set(thread::current().id()).unwrap(); +} + +#[test] +fn run_in_same_thread() { + assert_eq!(*THREAD_ID.get().unwrap(), thread::current().id()); +} |
