From 30b8a77fc9ce9da63a4e81d357130c0a136c2057 Mon Sep 17 00:00:00 2001 From: Sergio Benitez Date: Mon, 20 Jun 2022 23:49:13 -0700 Subject: [PATCH] Avoid dropping 'Error' inside '#[launch]' future. Due to tokio-rs/tokio#4780, a panicking top-level future combined with an uncooperative background task prevents runtime shutdown. To avoid this in the case of `Rocket::launch()` returning an `Error`, which panics on drop if it isn't inspected, we return the `Result` to the caller (i.e., `main`) instead of the `block_on` future. This prevent the panic from occuring inside of the `block_on` future and so the runtime terminates even with uncooperative I/O. --- core/codegen/src/attribute/entry/launch.rs | 7 ++++++- core/lib/src/server.rs | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/core/codegen/src/attribute/entry/launch.rs b/core/codegen/src/attribute/entry/launch.rs index 65834a9b..f3081e3a 100644 --- a/core/codegen/src/attribute/entry/launch.rs +++ b/core/codegen/src/attribute/entry/launch.rs @@ -42,6 +42,11 @@ impl EntryAttr for Launch { ___rocket }); + let launch = match f.sig.asyncness { + Some(_) => quote_spanned!(ty.span() => async move { #rocket.launch().await }), + None => quote_spanned!(ty.span() => #rocket.launch()), + }; + let (vis, mut sig) = (&f.vis, f.sig.clone()); sig.ident = syn::Ident::new("main", sig.ident.span()); sig.output = syn::ReturnType::Default; @@ -51,7 +56,7 @@ impl EntryAttr for Launch { #[allow(dead_code)] #f #vis #sig { - ::rocket::async_main(async move { let _res = #rocket.launch().await; }) + let _ = ::rocket::async_main(#launch); } )) } diff --git a/core/lib/src/server.rs b/core/lib/src/server.rs index 5a71c5bb..c2a62ca9 100644 --- a/core/lib/src/server.rs +++ b/core/lib/src/server.rs @@ -529,13 +529,13 @@ impl Rocket { Ok(rocket) } Err(rocket) => { - warn!("Server failed to shutdown cooperatively."); + warn!("Shutdown failed: outstanding background I/O."); Err(Error::shutdown(rocket, None)) } } } _ = &mut shutdown_timer => { - warn!("Server failed to shutdown cooperatively."); + warn!("Shutdown failed: server executing after timeouts."); return Err(Error::shutdown(rocket.clone(), None)); }, }