Skip to content

Commit

Permalink
Make run_as_sync safe to use if runtime is present
Browse files Browse the repository at this point in the history
Summary:
The issue with the way we use block_on() is that it tries to unconditionally create new Tokio runtime and panics if there is one already (because nested runtimes are not allowed).

Here if the runtime is present, we reuse it instead of creating a new one.

Reviewed By: ndmitchell

Differential Revision: D61635145

fbshipit-source-id: caed839c5e42ddf222d6770b1d3949228beb32c5
  • Loading branch information
Fedir Panasenko authored and facebook-github-bot committed Aug 23, 2024
1 parent 8d24251 commit 8cc88c3
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 5 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ members = [

[workspace.dependencies]
fbinit = { git = "https://github.com/facebookexperimental/rust-shed" }
fbinit-tokio = { git = "https://github.com/facebookexperimental/rust-shed" }
scuba = { git = "https://github.com/facebookexperimental/rust-shed" }

[profile.release]
Expand Down
2 changes: 2 additions & 0 deletions td_util/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ argfile = "0.1.5"
clap = {version = "4.1.4"}
equivalent = "1.0.0"
fbinit = { workspace = true }
fbinit-tokio = { workspace = true }
futures = "0.3.30"
lazy_static = "1.4.0"
static_interner.version = "0.1"
# @oss-disable: static_interner.path = "../../buck2/shed/static_interner"
Expand Down
35 changes: 30 additions & 5 deletions td_util/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,35 @@
use std::future::Future;

// Run future within a sync context
// Uses existing Tokio runtime if available, otherwise creates a new one.
pub fn run_as_sync<F: Future>(future: F) -> F::Output {
tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap()
.block_on(future)
match tokio::runtime::Handle::try_current() {
Ok(handle) => {
let _guard = handle.enter();
futures::executor::block_on(future)
}
Err(_) => tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap()
.block_on(future),
}
}

#[cfg(test)]
mod tests {
use crate::executor::run_as_sync;

#[test]
fn test_run_as_sync_without_runtime() {
// Should not panic and should return the result of the future.
assert_eq!(run_as_sync(async { 42 }), 42);
}

#[fbinit::test]
async fn test_run_as_sync_with_runtime() {
// Tokio runtime is injected by fbinit. Still, should not panic and should return the result of the future.
assert_eq!(run_as_sync(async { 42 }), 42);
}
}

0 comments on commit 8cc88c3

Please sign in to comment.