self_update icon indicating copy to clipboard operation
self_update copied to clipboard

Not usable from async contexts

Open clux opened this issue 4 years ago • 5 comments

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>

clux avatar Feb 19 '20 16:02 clux

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;
 }

redrabbit avatar Sep 27 '20 22:09 redrabbit

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.

etam avatar Mar 19 '21 08:03 etam

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?

avsaase avatar Jan 04 '23 22:01 avsaase

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

jaemk avatar Jan 06 '23 00:01 jaemk

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)
}

ShayBox avatar Jun 10 '23 10:06 ShayBox