Skip to content

Tokio thread panics when loading a Resource in a component with a table #93

@IsaacHorvath

Description

@IsaacHorvath

I am running into a bug in leptos-struct-table in an SSR Leptos Axum app. It seems to cause panics in a tokio thread because a SendWrapper is dropped on a different thread to the one it's created on. This only happens if the table is rendered in a component with an asynchronous Resource load that takes some amount of time.

I've uploaded a minimum reproducible demo based on the leptos axum template. In the main App() component, I have added an unused resource that calls a dummy server function that simply waits for two seconds. I have a hard-coded vec of rows containing one test struct with one field. Including the element leads to the following error when running the demo with cargo leptos watch:

thread 'tokio-rt-worker' (822384) panicked at /home/***/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:805:1:
Dropped SendWrapper<T> variable from a thread different to the one it has been created with.
note: run with 'RUST_BACKTRACE=1' environment variable to display a backtrace

Note that this error only happens sporadically, but at the two second mark it happens far more often than not on my machine. Refresh the page several times and you should see it.

Here is the relevant code in app.rs:
use leptos_struct_table::*;

#[derive(TableRow, Clone)]
#[table(impl_vec_data_provider)]
pub struct TestStruct {
  pub test_field: String,
}

#[server]
pub async fn load_resource() -> Result<Vec<i32>, ServerFnError> {
  tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
  Ok(vec![])
}

#[component]
pub fn App() -> impl IntoView {
  // Provides context that manages stylesheets, titles, meta tags, etc.
  provide_meta_context();

  let _resource = Resource::new(move || {}, move |_| load_resource());

  let rows: Vec<TestStruct> = vec![TestStruct {
      test_field: "test content".to_string(),
  }];

  view! {
      // sets the document title
      <Title text="Welcome to Leptos"/>
      <div>
          <table>
              <TableContent
                  rows
                  scroll_container="html"
              />
          </table>
      </div>
  }
}
Here is the full backtrace:

thread 'tokio-rt-worker' (837511) panicked at /home/***/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:805:1:
Dropped SendWrapper<T> variable from a thread different to the one it has been created with.
stack backtrace:
 0: __rustc::rust_begin_unwind
           at /rustc/4a4ef493e3a1488c6e321570238084b38948f6db/library/std/src/panicking.rs:689:5
 1: core::panicking::panic_fmt
           at /rustc/4a4ef493e3a1488c6e321570238084b38948f6db/library/core/src/panicking.rs:80:14
 2: core::panicking::panic_display
           at /home/***/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/panicking.rs:259:5
 3: send_wrapper::invalid_drop
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/send_wrapper-0.6.0/src/lib.rs:291:3
 4: <send_wrapper::SendWrapper<T> as core::ops::drop::Drop>::drop
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/send_wrapper-0.6.0/src/lib.rs:230:4
 5: core::ptr::drop_in_place<send_wrapper::SendWrapper<reactive_graph::signal::arc_rw::ArcRwSignal<core::option::Option<web_sys::features::gen_Element::Element>>>>
           at /home/***/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:805:1
 6: core::ptr::drop_in_place<alloc::boxed::Box<dyn core::any::Any+core::marker::Send+core::marker::Sync>>
           at /home/***/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:805:1
 7: core::ptr::drop_in_place<core::option::Option<alloc::boxed::Box<dyn core::any::Any+core::marker::Send+core::marker::Sync>>>
           at /home/***/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:805:1
 8: <std::sync::poison::rwlock::RwLock<reactive_graph::owner::OwnerInner> as reactive_graph::owner::Cleanup>::cleanup
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/reactive_graph-0.2.13/src/owner.rs:577:42
 9: reactive_graph::owner::Owner::cleanup
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/reactive_graph-0.2.13/src/owner.rs:296:20
10: reactive_graph::owner::Owner::unset_with_forced_cleanup
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/reactive_graph-0.2.13/src/owner.rs:363:14
11: leptos_integration_utils::ExtendResponse::from_app::{{closure}}::{{closure}}
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/leptos_integration_utils-0.8.8/src/lib.rs:124:31
12: <futures_util::stream::once::Once<Fut> as futures_core::stream::Stream>::poll_next
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-util-0.3.32/src/stream/once.rs:46:37
13: <futures_util::stream::stream::chain::Chain<St1,St2> as futures_core::stream::Stream>::poll_next
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-util-0.3.32/src/stream/stream/chain.rs:56:21
14: <reactive_graph::owner::arena::sandboxed::Sandboxed<T> as futures_core::stream::Stream>::poll_next
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/reactive_graph-0.2.13/src/owner/arena.rs:190:24
15: <futures_util::stream::stream::map::Map<St,F> as futures_core::stream::Stream>::poll_next
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-util-0.3.32/src/stream/stream/map.rs:58:47
16: <S as futures_core::stream::TryStream>::try_poll_next
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-core-0.3.32/src/stream.rs:206:14
17: <axum_core::body::StreamBody<S> as http_body::Body>::poll_frame
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/axum-core-0.5.6/src/body.rs:214:29
18: <http_body_util::combinators::map_err::MapErr<B,F> as http_body::Body>::poll_frame
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/http-body-util-0.1.3/src/combinators/map_err.rs:62:26
19: <http_body_util::combinators::box_body::UnsyncBoxBody<D,E> as http_body::Body>::poll_frame
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/http-body-util-0.1.3/src/combinators/box_body.rs:103:29
20: <axum_core::body::Body as http_body::Body>::poll_frame
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/axum-core-0.5.6/src/body.rs:122:31
21: hyper::proto::h1::dispatch::Dispatcher<D,Bs,I,T>::poll_write
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/hyper-1.8.1/src/proto/h1/dispatch.rs:373:53
22: hyper::proto::h1::dispatch::Dispatcher<D,Bs,I,T>::poll_loop
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/hyper-1.8.1/src/proto/h1/dispatch.rs:173:26
23: hyper::proto::h1::dispatch::Dispatcher<D,Bs,I,T>::poll_inner
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/hyper-1.8.1/src/proto/h1/dispatch.rs:149:21
24: hyper::proto::h1::dispatch::Dispatcher<D,Bs,I,T>::poll_catch
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/hyper-1.8.1/src/proto/h1/dispatch.rs:128:33
25: <hyper::proto::h1::dispatch::Dispatcher<D,Bs,I,T> as core::future::future::Future>::poll
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/hyper-1.8.1/src/proto/h1/dispatch.rs:471:14
26: <hyper::server::conn::http1::UpgradeableConnection<I,S> as core::future::future::Future>::poll
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/hyper-1.8.1/src/server/conn/http1.rs:539:51
27: <hyper_util::server::conn::auto::UpgradeableConnection<I,S,E> as core::future::future::Future>::poll
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/hyper-util-0.1.20/src/server/conn/auto/mod.rs:693:33
28: <core::pin::Pin<P> as core::future::future::Future>::poll
           at /home/***/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/future/future.rs:133:9
29: axum::serve::handle_connection::{{closure}}::{{closure}}::{{closure}}
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/macros/select.rs:705:49
30: <core::future::poll_fn::PollFn<F> as core::future::future::Future>::poll
           at /home/***/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/future/poll_fn.rs:151:9
31: axum::serve::handle_connection::{{closure}}::{{closure}}
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/axum-0.8.8/src/serve/mod.rs:400:13
32: tokio::runtime::task::core::Core<T,S>::poll::{{closure}}
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/task/core.rs:375:24
33: tokio::loom::std::unsafe_cell::UnsafeCell<T>::with_mut
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/loom/std/unsafe_cell.rs:16:9
34: tokio::runtime::task::core::Core<T,S>::poll
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/task/core.rs:364:30
35: tokio::runtime::task::harness::poll_future::{{closure}}
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/task/harness.rs:535:30
36: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
           at /home/***/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/panic/unwind_safe.rs:274:9
37: std::panicking::catch_unwind::do_call
           at /home/***/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:581:40
38: __rust_try
39: std::panicking::catch_unwind
           at /home/***/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:544:19
40: std::panic::catch_unwind
           at /home/***/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panic.rs:359:14
41: tokio::runtime::task::harness::poll_future
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/task/harness.rs:523:18
42: tokio::runtime::task::harness::Harness<T,S>::poll_inner
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/task/harness.rs:210:27
43: tokio::runtime::task::harness::Harness<T,S>::poll
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/task/harness.rs:155:20
44: tokio::runtime::task::raw::poll
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/task/raw.rs:337:13
45: tokio::runtime::task::raw::RawTask::poll
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/task/raw.rs:267:18
46: tokio::runtime::task::LocalNotified<S>::run
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/task/mod.rs:510:13
47: tokio::runtime::scheduler::multi_thread::worker::Context::run_task::{{closure}}
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/scheduler/multi_thread/worker.rs:724:22
48: tokio::task::coop::with_budget
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/task/coop/mod.rs:167:5
49: tokio::task::coop::budget
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/task/coop/mod.rs:133:5
50: tokio::runtime::scheduler::multi_thread::worker::Context::run_task
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/scheduler/multi_thread/worker.rs:638:9
51: tokio::runtime::scheduler::multi_thread::worker::Context::run
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/scheduler/multi_thread/worker.rs:571:29
52: tokio::runtime::scheduler::multi_thread::worker::run::{{closure}}::{{closure}}
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/scheduler/multi_thread/worker.rs:536:24
53: tokio::runtime::context::scoped::Scoped<T>::set
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/context/scoped.rs:40:9
54: tokio::runtime::context::set_scheduler::{{closure}}
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/context.rs:176:38
55: std::thread::local::LocalKey<T>::try_with
           at /home/***/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:513:12
56: std::thread::local::LocalKey<T>::with
           at /home/***/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:477:20
57: tokio::runtime::context::set_scheduler
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/context.rs:176:17
58: tokio::runtime::scheduler::multi_thread::worker::run::{{closure}}
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/scheduler/multi_thread/worker.rs:531:9
59: tokio::runtime::context::runtime::enter_runtime
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/context/runtime.rs:65:16
60: tokio::runtime::scheduler::multi_thread::worker::run
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/scheduler/multi_thread/worker.rs:523:5
61: tokio::runtime::scheduler::multi_thread::worker::Launch::launch::{{closure}}
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/scheduler/multi_thread/worker.rs:489:45
62: <tokio::runtime::blocking::task::BlockingTask<T> as core::future::future::Future>::poll
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/blocking/task.rs:42:21
63: tokio::runtime::task::core::Core<T,S>::poll::{{closure}}
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/task/core.rs:375:24
64: tokio::loom::std::unsafe_cell::UnsafeCell<T>::with_mut
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/loom/std/unsafe_cell.rs:16:9
65: tokio::runtime::task::core::Core<T,S>::poll
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/task/core.rs:364:30
66: tokio::runtime::task::harness::poll_future::{{closure}}
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/task/harness.rs:535:30
67: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
           at /home/***/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/panic/unwind_safe.rs:274:9
68: std::panicking::catch_unwind::do_call
           at /home/***/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:581:40
69: __rust_try
70: std::panicking::catch_unwind
           at /home/***/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:544:19
71: std::panic::catch_unwind
           at /home/***/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panic.rs:359:14
72: tokio::runtime::task::harness::poll_future
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/task/harness.rs:523:18
73: tokio::runtime::task::harness::Harness<T,S>::poll_inner
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/task/harness.rs:210:27
74: tokio::runtime::task::harness::Harness<T,S>::poll
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/task/harness.rs:155:20
75: tokio::runtime::task::raw::poll
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/task/raw.rs:337:13
76: tokio::runtime::task::raw::RawTask::poll
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/task/raw.rs:267:18
77: tokio::runtime::task::UnownedTask<S>::run
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/task/mod.rs:547:13
78: tokio::runtime::blocking::pool::Task::run
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/blocking/pool.rs:161:19
79: tokio::runtime::blocking::pool::Inner::run
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/blocking/pool.rs:518:22
80: tokio::runtime::blocking::pool::Spawner::spawn_thread::{{closure}}
           at /home/***/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/runtime/blocking/pool.rs:474:47
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

Please let me know if I'm doing anything wrong here or missing a feature that would fix this behaviour.

Edit: A temporary workaround is changing #[tokio::main] to #[tokio::main(flavor = "current_thread")] in main.rs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions