Skip to content

Commit 661cc26

Browse files
authored
fix(lambda-runtime,lambda-integration-tests): make spawn_graceful_shutdown_handler() async, await the extension being registered before spawning background extension handler task (#992)
1 parent 57cd659 commit 661cc26

File tree

3 files changed

+25
-22
lines changed

3 files changed

+25
-22
lines changed

lambda-integration-tests/src/helloworld.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use lambda_runtime::{service_fn, tracing, Error, LambdaEvent};
88
async fn main() -> Result<(), Error> {
99
tracing::init_default_subscriber();
1010
let func = service_fn(func);
11-
lambda_runtime::spawn_graceful_shutdown_handler(|| async move {});
11+
lambda_runtime::spawn_graceful_shutdown_handler(|| async move {}).await;
1212
lambda_runtime::run(func).await?;
1313
Ok(())
1414
}

lambda-runtime/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ hyper-util = { workspace = true, features = [
7373
"server-auto",
7474
"tokio",
7575
] }
76+
# pin back to pre-1.2.1 to avoid breaking rust MSRV of 1.81:
77+
# https://github.com/hsivonen/idna_adapter/commit/f948802e3a2ae936eec51886eefbd7d536a28791
78+
idna_adapter = "=1.2.0"
7679
# Self dependency to enable the graceful-shutdown feature for tests
7780
lambda_runtime = { path = ".", features = ["tracing", "graceful-shutdown"] }
7881
pin-project-lite = { workspace = true }

lambda-runtime/src/lib.rs

+21-21
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ where
131131
///
132132
/// You can use this future to execute cleanup or flush related logic prior to runtime shutdown.
133133
///
134-
/// This function must be called prior to [lambda_runtime::run()].
134+
/// This function's returned future must be resolved prior to [lambda_runtime::run()].
135135
///
136136
/// Note that this implicitly also registers and drives a no-op internal extension that subscribes to no events.
137137
/// This extension will be named `_lambda-rust-runtime-no-op-graceful-shutdown-helper`. This extension name
@@ -166,7 +166,7 @@ where
166166
/// let shutdown_hook = || async move {
167167
/// std::mem::drop(log_guard);
168168
/// };
169-
/// lambda_runtime::spawn_graceful_shutdown_handler(shutdown_hook);
169+
/// lambda_runtime::spawn_graceful_shutdown_handler(shutdown_hook).await;
170170
///
171171
/// lambda_runtime::run(func).await?;
172172
/// Ok(())
@@ -178,29 +178,29 @@ where
178178
/// ```
179179
#[cfg(all(unix, feature = "graceful-shutdown"))]
180180
#[cfg_attr(docsrs, doc(cfg(all(unix, feature = "tokio-rt"))))]
181-
pub fn spawn_graceful_shutdown_handler<Fut>(shutdown_hook: impl FnOnce() -> Fut + Send + 'static)
181+
pub async fn spawn_graceful_shutdown_handler<Fut>(shutdown_hook: impl FnOnce() -> Fut + Send + 'static)
182182
where
183183
Fut: Future<Output = ()> + Send + 'static,
184184
{
185-
tokio::task::spawn(async move {
186-
// You need an extension registered with the Lambda orchestrator in order for your process
187-
// to receive a SIGTERM for graceful shutdown.
188-
//
189-
// We accomplish this here by registering a no-op internal extension, which does not subscribe to any events.
190-
//
191-
// This extension is cheap to run since after it connects to the lambda orchestration, the connection
192-
// will just wait forever for data to come, which never comes, so it won't cause wakes.
193-
let extension = lambda_extension::Extension::new()
194-
// Don't subscribe to any event types
195-
.with_events(&[])
196-
// Internal extension names MUST be unique within a given Lambda function.
197-
.with_extension_name("_lambda-rust-runtime-no-op-graceful-shutdown-helper")
198-
// Extensions MUST be registered before calling lambda_runtime::run(), which ends the Init
199-
// phase and begins the Invoke phase.
200-
.register()
201-
.await
202-
.expect("could not register no-op extension for graceful shutdown");
185+
// You need an extension registered with the Lambda orchestrator in order for your process
186+
// to receive a SIGTERM for graceful shutdown.
187+
//
188+
// We accomplish this here by registering a no-op internal extension, which does not subscribe to any events.
189+
//
190+
// This extension is cheap to run since after it connects to the lambda orchestration, the connection
191+
// will just wait forever for data to come, which never comes, so it won't cause wakes.
192+
let extension = lambda_extension::Extension::new()
193+
// Don't subscribe to any event types
194+
.with_events(&[])
195+
// Internal extension names MUST be unique within a given Lambda function.
196+
.with_extension_name("_lambda-rust-runtime-no-op-graceful-shutdown-helper")
197+
// Extensions MUST be registered before calling lambda_runtime::run(), which ends the Init
198+
// phase and begins the Invoke phase.
199+
.register()
200+
.await
201+
.expect("could not register no-op extension for graceful shutdown");
203202

203+
tokio::task::spawn(async move {
204204
let graceful_shutdown_future = async move {
205205
let mut sigint = tokio::signal::unix::signal(tokio::signal::unix::SignalKind::interrupt()).unwrap();
206206
let mut sigterm = tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate()).unwrap();

0 commit comments

Comments
 (0)