Not usable from async contexts
Hey. Was trying to use the new version to get unified reqwest 0.10 everywhere to move to async / remove dependency tree. But it seems that the blocking client interacts badly with async atm.
cargo toml:
self_update = { version = "0.13.0", features = ["archive-tar"] }
tokio = { version = "0.2.11", features = ["full"] }
reqwest = "0.10.1"
and all I have is a #[tokio::main] that a few functions down ends up calling a list on self_update::backends::github. But because, the reqwest::blocking::Client seems to spawn another tokio runtime, this just causes a panic immediately.
thread 'main' panicked at 'Cannot start a runtime from within a runtime. This happens because a function (like
block_on) attempted to block the current thread while the thread is being used to drive asynchronous tasks.
Full stacktrace
thread 'main' panicked at 'Cannot start a runtime from within a runtime. This happens because a function (like `block_on`) attempted to block the current thread while the thread is being used to drive asynchronous tasks.', /home/clux/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.11/src/runtime/enter.rs:19:5
stack backtrace:
0: 0x558ad554e274 - backtrace::backtrace::libunwind::trace::heb43798aede8bd30
at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/libunwind.rs:88
1: 0x558ad554e274 - backtrace::backtrace::trace_unsynchronized::had2ba7dec4bd2732
at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/mod.rs:66
2: 0x558ad554e274 - std::sys_common::backtrace::_print_fmt::hda61f46e822731b2
at src/libstd/sys_common/backtrace.rs:84
3: 0x558ad554e274 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::hfe37fa5de6572965
at src/libstd/sys_common/backtrace.rs:61
4: 0x558ad5577bac - core::fmt::write::h74887d18db27282c
at src/libcore/fmt/mod.rs:1025
5: 0x558ad55482c7 - std::io::Write::write_fmt::h6808f3d5eceed5e5
at src/libstd/io/mod.rs:1426
6: 0x558ad5550b9e - std::sys_common::backtrace::_print::hcc0fd4b3552039ef
at src/libstd/sys_common/backtrace.rs:65
7: 0x558ad5550b9e - std::sys_common::backtrace::print::h1c9c5c1c0505592d
at src/libstd/sys_common/backtrace.rs:50
8: 0x558ad5550b9e - std::panicking::default_hook::{{closure}}::hefb6085c1ab83a59
at src/libstd/panicking.rs:193
9: 0x558ad5550891 - std::panicking::default_hook::h1b037d2bf0657ab3
at src/libstd/panicking.rs:210
10: 0x558ad555127b - std::panicking::rust_panic_with_hook::h787d7f532b084b9a
at src/libstd/panicking.rs:471
11: 0x558ad4ffbe27 - std::panicking::begin_panic::hf6f80a6760574375
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/panicking.rs:404
12: 0x558ad4f934dc - tokio::runtime::enter::enter::he9051ec054dcfd32
at /home/clux/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.11/src/runtime/enter.rs:19
13: 0x558ad4fd7ba0 - tokio::runtime::blocking::shutdown::Receiver::wait::h54c85b384d7234d9
at /home/clux/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.11/src/runtime/blocking/shutdown.rs:38
14: 0x558ad4fc372e - <tokio::runtime::blocking::pool::BlockingPool as core::ops::drop::Drop>::drop::h55575462e28eec56
at /home/clux/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.11/src/runtime/blocking/pool.rs:116
15: 0x558ad4925775 - core::ptr::real_drop_in_place::hb5c4378272efde28
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libcore/ptr/mod.rs:182
16: 0x558ad491eace - core::ptr::real_drop_in_place::h64fb5188d56aaa9b
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libcore/ptr/mod.rs:182
17: 0x558ad4947df2 - reqwest::blocking::wait::enter::he8252476c7f2eab0
at /home/clux/.cargo/registry/src/github.com-1ecc6299db9ec823/reqwest-0.10.1/src/blocking/wait.rs:73
18: 0x558ad4945fc3 - reqwest::blocking::wait::timeout::hd66cb015ab680631
at /home/clux/.cargo/registry/src/github.com-1ecc6299db9ec823/reqwest-0.10.1/src/blocking/wait.rs:14
19: 0x558ad490c931 - reqwest::blocking::client::ClientHandle::new::hc530c9153f53fbba
at /home/clux/.cargo/registry/src/github.com-1ecc6299db9ec823/reqwest-0.10.1/src/blocking/client.rs:662
20: 0x558ad490bacd - reqwest::blocking::client::ClientBuilder::build::h99c2ec740eba3deb
at /home/clux/.cargo/registry/src/github.com-1ecc6299db9ec823/reqwest-0.10.1/src/blocking/client.rs:84
21: 0x558ad490bb81 - reqwest::blocking::client::Client::new::h49294ac019aa5ac2
at /home/clux/.cargo/registry/src/github.com-1ecc6299db9ec823/reqwest-0.10.1/src/blocking/client.rs:469
22: 0x558ad4375159 - self_update::backends::github::ReleaseList::fetch_releases::h79a06c8acc8f29c0
at /home/clux/.cargo/registry/src/github.com-1ecc6299db9ec823/self_update-0.13.0/src/backends/github.rs:159
23: 0x558ad4374c8f - self_update::backends::github::ReleaseList::fetch::h023cf19d2b8b81c5
at /home/clux/.cargo/registry/src/github.com-1ecc6299db9ec823/self_update-0.13.0/src/backends/github.rs:147
24: 0x558ad3b003aa - shipcat::upgrade::self_upgrade::{{closure}}::h569e7958857a5dfa
at /home/clux/babylon/shipcat/shipcat_cli/src/upgrade.rs:77
25: 0x558ad39ddda8 - <std::future::GenFuture<T> as core::future::future::Future>::poll::h4a29021de0d7d754
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/future.rs:43
26: 0x558ad39d277a - std::future::poll_with_tls_context::ha5c63dde9323fd1b
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/future.rs:99
27: 0x558ad3e16b3c - shipcat::dispatch_commands::{{closure}}::h862ab6e248aeebaa
at shipcat_cli/src/main.rs:539
28: 0x558ad39e84a8 - <std::future::GenFuture<T> as core::future::future::Future>::poll::hc741103e33926ebc
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/future.rs:43
29: 0x558ad39d424a - std::future::poll_with_tls_context::hd217b7e226c0c204
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/future.rs:99
30: 0x558ad3e11900 - shipcat::run::{{closure}}::h87e0a48886cfe2b5
at shipcat_cli/src/main.rs:452
31: 0x558ad39ea3b8 - <std::future::GenFuture<T> as core::future::future::Future>::poll::hda07fe0bc63b7548
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/future.rs:43
32: 0x558ad39d03ba - std::future::poll_with_tls_context::h5b5e4f50e0a8939f
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/future.rs:99
33: 0x558ad3e3e3ed - shipcat::main::{{closure}}::h4c8d52216421cce2
at shipcat_cli/src/main.rs:424
34: 0x558ad39da2ca - <std::future::GenFuture<T> as core::future::future::Future>::poll::h1012b2e438abfda9
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/future.rs:43
35: 0x558ad3f038cc - tokio::runtime::enter::Enter::block_on::h3e95c77d786ac59d
at /home/clux/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.11/src/runtime/enter.rs:100
36: 0x558ad3f1246d - tokio::runtime::thread_pool::ThreadPool::block_on::h2968698c19f0e6e8
at /home/clux/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.11/src/runtime/thread_pool/mod.rs:93
37: 0x558ad3d3d5bb - tokio::runtime::Runtime::block_on::{{closure}}::hc1778ae61d231d7a
at /home/clux/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.11/src/runtime/mod.rs:413
38: 0x558ad397d22d - tokio::runtime::context::enter::hbbd214dda6ef5038
at /home/clux/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.11/src/runtime/context.rs:72
39: 0x558ad3c19ba6 - tokio::runtime::handle::Handle::enter::he374b51860c2d132
at /home/clux/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.11/src/runtime/handle.rs:34
40: 0x558ad3d3d466 - tokio::runtime::Runtime::block_on::hefb5182b24fe2948
at /home/clux/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.11/src/runtime/mod.rs:408
41: 0x558ad3de31d9 - shipcat::main::h18a1b3b861809cb8
at shipcat_cli/src/main.rs:411
42: 0x558ad3931300 - std::rt::lang_start::{{closure}}::h1b2325711f7f7adb
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/rt.rs:67
43: 0x558ad5550cc3 - std::rt::lang_start_internal::{{closure}}::h0760fb8bd9f1a4c7
at src/libstd/rt.rs:52
44: 0x558ad5550cc3 - std::panicking::try::do_call::hccaa7cebf2335ab2
at src/libstd/panicking.rs:292
45: 0x558ad555afba - __rust_maybe_catch_panic
at src/libpanic_unwind/lib.rs:78
46: 0x558ad55517d0 - std::panicking::try::h3ce8e2e4440720f0
at src/libstd/panicking.rs:270
47: 0x558ad55517d0 - std::panic::catch_unwind::h2a767bac361346af
at src/libstd/panic.rs:394
48: 0x558ad55517d0 - std::rt::lang_start_internal::h14e7168ba039f170
at src/libstd/rt.rs:51
49: 0x558ad39312d9 - std::rt::lang_start::ha64f6a4661cac25b
at /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libstd/rt.rs:67
50: 0x558ad3de325a - main
51: 0x7f12ed642153 - __libc_start_main
52: 0x558ad39311be - _start
53: 0x0 - <unknown>
My current workaround is to use tokio::task::spawn_blocking():
In general, issuing a blocking call or performing a lot of compute in a future without yielding is not okay, as it may prevent the executor from driving other futures forward. This function runs the provided closure on a thread dedicated to blocking operations. See the CPU-bound tasks and blocking code section for more information.
https://docs.rs/tokio/0.2.22/tokio/task/fn.spawn_blocking.html
Here's a working example for the github.rs example:
diff --git a/Cargo.toml b/Cargo.toml
index 407d9f2..902402a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -24,6 +24,7 @@ indicatif = "0.13.0"
quick-xml = "0.17.2"
regex = "1.3.1"
log = "0.4.8"
+tokio = { version = "0.2", features = ["full"] }
[features]
default = ["reqwest/default-tls"]
diff --git a/examples/github.rs b/examples/github.rs
index 2cffd62..4a997d5 100644
--- a/examples/github.rs
+++ b/examples/github.rs
@@ -36,9 +36,12 @@ fn run() -> Result<(), Box<dyn ::std::error::Error>> {
Ok(())
}
-pub fn main() {
- if let Err(e) = run() {
- println!("[ERROR] {}", e);
- ::std::process::exit(1);
- }
+#[tokio::main]
+pub async fn main() {
+ tokio::task::spawn_blocking(move || {
+ if let Err(e) = run() {
+ println!("[ERROR] {}", e);
+ ::std::process::exit(1);
+ }
+ }).await;
}
I have an idea for self_update: by default provide async functions. Provide a blocking functions in a way like reqwest does: inside a submodule and enabled by a feature.
Another option would be to switch to an inherently synchronous http client like ureq. It's more than capable of replacing reqwest in this library and has the added benefit of using less dependencies and faster compile times. @jaemk are you open to a PR switching http clients?
I'd be open to adding a config option to use either ureq or reqwest. I'd imagine some people might want to continue using reqwest if they are already using it elsewhere and fine with spawning a blocking task when necessary
Could maybe-async be used to accomplish this? I'd rather not use the spawn-blocking workaround
EDIT: This is my workaround example
#[tokio::main]
async fn main() -> Result<()> {
tokio::task::spawn_blocking(check_for_updates).await??;
Ok(())
}
fn check_for_updates() -> Result<Status> {
let status = Update::configure()
.repo_owner("ShayBox")
.repo_name("VRC-OSC")
.bin_name("vrc-osc")
.show_download_progress(true)
.current_version(CARGO_PKG_VERSION)
.build()?
.update()?;
Ok(status)
}