From dc9f6ede1922c6c7541d20f8149ef62969de1ad0 Mon Sep 17 00:00:00 2001 From: Paco Cartones <253313177+pacocartones@users.noreply.github.com> Date: Fri, 4 Sep 2026 17:59:55 +0200 Subject: [PATCH] runtime: re-enable ignored io shutdown tests in rt_handle_block_on (#8404) These tests were added in #3569 (2021) but immediately marked `#[ignore]` because of a then-known bug where shutting down the io driver while concurrently registering new resources was unsound. That bug class was resolved by the io driver rewrite in #5833, which replaced the slab-based registration with a `RegistrationSet` guarded by a mutex-protected `Synced`. Allocating a new registration now checks `is_shutdown` under the lock and returns a proper error instead of racing, so binding a resource after (or concurrently with) runtime shutdown fails deterministically. Re-enable the 7 ignored tests (across the 3 scheduler configurations). Five of them pass unchanged. The two `unix_listener_shutdown_after_*` tests asserted the old `"reactor gone"` message; #5833 unified that path onto the single `RUNTIME_SHUTTING_DOWN_ERROR` string, so update those two assertions to the current message. --- tokio/tests/rt_handle_block_on.rs | 61 ++++++------------------------- 1 file changed, 12 insertions(+), 49 deletions(-) diff --git a/tokio/tests/rt_handle_block_on.rs b/tokio/tests/rt_handle_block_on.rs index 29a83cfd1..e3272710a 100644 --- a/tokio/tests/rt_handle_block_on.rs +++ b/tokio/tests/rt_handle_block_on.rs @@ -1,12 +1,6 @@ #![warn(rust_2018_idioms)] #![cfg(feature = "full")] -// All io tests that deal with shutdown is currently ignored because there are known bugs in with -// shutting down the io driver while concurrently registering new resources. See -// https://github.com/tokio-rs/tokio/pull/3569#pullrequestreview-612703467 for more details. -// -// When this has been fixed we want to re-enable these tests. - use std::time::Duration; use tokio::runtime::{Handle, Runtime}; use tokio::sync::mpsc; @@ -250,8 +244,6 @@ rt_test! { .unwrap(); } - // All io tests are ignored for now. See above why that is. - #[ignore] #[test] fn tcp_listener_connect_after_shutdown() { let rt = rt(); @@ -263,15 +255,9 @@ rt_test! { .block_on(net::TcpListener::bind("127.0.0.1:0")) .unwrap_err(); - assert_eq!(err.kind(), std::io::ErrorKind::Other); - assert_eq!( - err.get_ref().unwrap().to_string(), - "A Tokio 1.x context was found, but it is being shutdown.", - ); + assert!(tokio::runtime::is_rt_shutdown_err(&err)); } - // All io tests are ignored for now. See above why that is. - #[ignore] #[test] fn tcp_listener_connect_before_shutdown() { let rt = rt(); @@ -283,11 +269,7 @@ rt_test! { let err = Handle::current().block_on(bind_future).unwrap_err(); - assert_eq!(err.kind(), std::io::ErrorKind::Other); - assert_eq!( - err.get_ref().unwrap().to_string(), - "A Tokio 1.x context was found, but it is being shutdown.", - ); + assert!(tokio::runtime::is_rt_shutdown_err(&err)); } #[test] @@ -301,8 +283,7 @@ rt_test! { .unwrap(); } - // All io tests are ignored for now. See above why that is. - #[ignore] + #[cfg_attr(miri, ignore)] // No UDP sockets in miri. #[test] fn udp_stream_bind_after_shutdown() { let rt = rt(); @@ -314,15 +295,10 @@ rt_test! { .block_on(net::UdpSocket::bind("127.0.0.1:0")) .unwrap_err(); - assert_eq!(err.kind(), std::io::ErrorKind::Other); - assert_eq!( - err.get_ref().unwrap().to_string(), - "A Tokio 1.x context was found, but it is being shutdown.", - ); + assert!(tokio::runtime::is_rt_shutdown_err(&err)); } - // All io tests are ignored for now. See above why that is. - #[ignore] + #[cfg_attr(miri, ignore)] // No UDP sockets in miri. #[test] fn udp_stream_bind_before_shutdown() { let rt = rt(); @@ -334,15 +310,10 @@ rt_test! { let err = Handle::current().block_on(bind_future).unwrap_err(); - assert_eq!(err.kind(), std::io::ErrorKind::Other); - assert_eq!( - err.get_ref().unwrap().to_string(), - "A Tokio 1.x context was found, but it is being shutdown.", - ); + assert!(tokio::runtime::is_rt_shutdown_err(&err)); } - // All io tests are ignored for now. See above why that is. - #[ignore] + #[cfg_attr(miri, ignore)] // No Unix domain sockets in miri. #[cfg(unix)] #[test] fn unix_listener_bind_after_shutdown() { @@ -356,15 +327,10 @@ rt_test! { let err = net::UnixListener::bind(path).unwrap_err(); - assert_eq!(err.kind(), std::io::ErrorKind::Other); - assert_eq!( - err.get_ref().unwrap().to_string(), - "A Tokio 1.x context was found, but it is being shutdown.", - ); + assert!(tokio::runtime::is_rt_shutdown_err(&err)); } - // All io tests are ignored for now. See above why that is. - #[ignore] + #[cfg_attr(miri, ignore)] // No Unix domain sockets in miri. #[cfg(unix)] #[test] fn unix_listener_shutdown_after_bind() { @@ -381,12 +347,10 @@ rt_test! { // this should not timeout but fail immediately since the runtime has been shutdown let err = Handle::current().block_on(listener.accept()).unwrap_err(); - assert_eq!(err.kind(), std::io::ErrorKind::Other); - assert_eq!(err.get_ref().unwrap().to_string(), "reactor gone"); + assert!(tokio::runtime::is_rt_shutdown_err(&err)); } - // All io tests are ignored for now. See above why that is. - #[ignore] + #[cfg_attr(miri, ignore)] // No Unix domain sockets in miri. #[cfg(unix)] #[test] fn unix_listener_shutdown_after_accept() { @@ -405,8 +369,7 @@ rt_test! { // this should not timeout but fail immediately since the runtime has been shutdown let err = Handle::current().block_on(accept_future).unwrap_err(); - assert_eq!(err.kind(), std::io::ErrorKind::Other); - assert_eq!(err.get_ref().unwrap().to_string(), "reactor gone"); + assert!(tokio::runtime::is_rt_shutdown_err(&err)); } // ==== nesting ======