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.
This commit is contained in:
Sergio Benitez 2022-06-20 23:49:13 -07:00
parent c8b8b2b022
commit 30b8a77fc9
2 changed files with 8 additions and 3 deletions

View File

@ -42,6 +42,11 @@ impl EntryAttr for Launch {
___rocket ___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()); let (vis, mut sig) = (&f.vis, f.sig.clone());
sig.ident = syn::Ident::new("main", sig.ident.span()); sig.ident = syn::Ident::new("main", sig.ident.span());
sig.output = syn::ReturnType::Default; sig.output = syn::ReturnType::Default;
@ -51,7 +56,7 @@ impl EntryAttr for Launch {
#[allow(dead_code)] #f #[allow(dead_code)] #f
#vis #sig { #vis #sig {
::rocket::async_main(async move { let _res = #rocket.launch().await; }) let _ = ::rocket::async_main(#launch);
} }
)) ))
} }

View File

@ -529,13 +529,13 @@ impl Rocket<Orbit> {
Ok(rocket) Ok(rocket)
} }
Err(rocket) => { Err(rocket) => {
warn!("Server failed to shutdown cooperatively."); warn!("Shutdown failed: outstanding background I/O.");
Err(Error::shutdown(rocket, None)) Err(Error::shutdown(rocket, None))
} }
} }
} }
_ = &mut shutdown_timer => { _ = &mut shutdown_timer => {
warn!("Server failed to shutdown cooperatively."); warn!("Shutdown failed: server executing after timeouts.");
return Err(Error::shutdown(rocket.clone(), None)); return Err(Error::shutdown(rocket.clone(), None));
}, },
} }