Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AppHandle is not Send + Sync on Windows #2343

Closed
TheCallSign opened this issue Aug 3, 2021 · 11 comments
Closed

AppHandle is not Send + Sync on Windows #2343

TheCallSign opened this issue Aug 3, 2021 · 11 comments

Comments

@TheCallSign
Copy link

TheCallSign commented Aug 3, 2021

Hello,

My Cargo.toml:

...
[dependencies]
tauri = { version = "1.0.0-beta.5", features = ["api-all"] }

I have a tauri application that compiles fine on Linux but when cross compiling to Windows I get the following error:

error[E0277]: `std::sync::mpsc::Sender<tauri_runtime_wry::Message>` cannot be shared between threads safely
  --> src-tauri/src/commands/device.rs:52:12
   |
52 |     state: State<'_, App>,
   |            ^^^^^^^^^^^^^^^^^^^^^^ `std::sync::mpsc::Sender<tauri_runtime_wry::Message>` cannot be shared between threads safely
   |
  ::: /home/thecallsign/.cargo/registry/src/github.jparrowsec.cn-1ecc6299db9ec823/tauri-1.0.0-beta.5/src/state.rs:13:32
   |
13 | pub struct State<'r, T: Send + Sync + 'static>(&'r T);
   |                                ---- required by this bound in `tauri::State`
   |
   = help: within `AppHandle`, the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Sender<tauri_runtime_wry::Message>`
   = note: required because it appears within the type `tao::platform_impl::platform::event_loop::EventLoopProxy<tauri_runtime_wry::Message>`
   = note: required because it appears within the type `tao::event_loop::EventLoopProxy<tauri_runtime_wry::Message>`
   = note: required because it appears within the type `tauri_runtime_wry::DispatcherContext`
   = note: required because it appears within the type `tauri_runtime_wry::WryHandle`
   = note: required because it appears within the type `AppHandle`
   = note: required because of the requirements on the impl of `std::marker::Sync` for `once_cell::imp::OnceCell<AppHandle>`
   = note: required because it appears within the type `once_cell::sync::OnceCell<AppHandle>`

and

error[E0277]: `*mut winapi::shared::windef::HWND__` cannot be shared between threads safely
  --> src-tauri/src/commands/serial.rs:6:41
   |
6  | pub(crate) async fn rescan_ports(state: State<'_, App>) -> Result<(), AppError> {
   |                                         ^^^^^^^^^^^^^^^^^^^^^^ `*mut winapi::shared::windef::HWND__` cannot be shared between threads safely
   |
  ::: /home/thecallsign/.cargo/registry/src/github.jparrowsec.cn-1ecc6299db9ec823/tauri-1.0.0-beta.5/src/state.rs:13:32
   |
13 | pub struct State<'r, T: Send + Sync + 'static>(&'r T);
   |                                ---- required by this bound in `tauri::State`
   |
   = help: within `AppHandle`, the trait `std::marker::Sync` is not implemented for `*mut winapi::shared::windef::HWND__`
   = note: required because it appears within the type `tao::platform_impl::platform::event_loop::EventLoopProxy<tauri_runtime_wry::Message>`
   = note: required because it appears within the type `tao::event_loop::EventLoopProxy<tauri_runtime_wry::Message>`
   = note: required because it appears within the type `tauri_runtime_wry::DispatcherContext`
   = note: required because it appears within the type `tauri_runtime_wry::WryHandle`
   = note: required because it appears within the type `AppHandle`
   = note: required because of the requirements on the impl of `std::marker::Sync` for `once_cell::imp::OnceCell<AppHandle>`
   = note: required because it appears within the type `once_cell::sync::OnceCell<AppHandle>`

I am holding on to a tauri AppHandle in my application state. My application state is managed with a tauri Application via manage().

Also, as far as I can tell tao::event_loop::EventLoopProxy is Send + Sync on Linux but only Send on Windows.

Windows:

https://github.com/tauri-apps/tao/blob/0d6fcde47a1dd587a7ac2c209d330169496d4c46/src/platform_impl/windows/event_loop.rs#L491

Linux:

https://github.com/tauri-apps/tao/blob/0d6fcde47a1dd587a7ac2c209d330169496d4c46/src/platform_impl/linux/event_loop.rs#L795

I'm not too phased about whether the AppHandle can be kept within tauri managed state but the bahaviour should be consistent across platform.

@TheCallSign
Copy link
Author

I've since refactored my code to work around this issue but the inconsistent behaviour remains...

@TheCallSign
Copy link
Author

TheCallSign commented Aug 3, 2021

Nevermind, cross compilation still fails. I cannot send the AppHandle to long running background tokio tasks.

Here are some more compiler errors:

Note that ConnectionManager contains an AppHandle, but it is instantiated and sent to a newly spawned async task.

The error wrt to tracing is because I am forwarding tracing log messages to the developer console in the tauri window. For that to work I really need the AppHandle to be Send + Sync.

error: future cannot be sent between threads safely
   --> src-tauri/src/app.rs:78:21
    |
78  |                     tokio::task::spawn(async move {
    |                     ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
    |
   ::: /home/thecallsign/.cargo/registry/src/github.jparrowsec.cn-1ecc6299db9ec823/tokio-1.9.0/src/task/spawn.rs:127:21
    |
127 |         T: Future + Send + 'static,
    |                     ---- required by this bound in `tokio::spawn`
    |
    = help: within `ConnectionManager`, the trait `std::marker::Sync` is not implemented for `*mut winapi::shared::windef::HWND__`
note: captured value is not `Send`
   --> src-tauri/src/app.rs:84:33
    |
84  | ...                   manager.close(&name);
    |                       ^^^^^^^ has type `Arc<ConnectionManager>` which is not `Send`

error: future cannot be sent between threads safely
   --> src-tauri/src/app.rs:78:21
    |
78  |                     tokio::task::spawn(async move {
    |                     ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
    |
   ::: /home/thecallsign/.cargo/registry/src/github.jparrowsec.cn-1ecc6299db9ec823/tokio-1.9.0/src/task/spawn.rs:127:21
    |
127 |         T: Future + Send + 'static,
    |                     ---- required by this bound in `tokio::spawn`
    |
    = help: within `ConnectionManager`, the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Sender<tauri_runtime_wry::Message>`
note: captured value is not `Send`
   --> src-tauri/src/app.rs:84:33
    |
84  | ...                   manager.close(&name);
    |                       ^^^^^^^ has type `Arc<ConnectionManager>` which is not `Send`

error[E0277]: `*mut winapi::shared::windef::HWND__` cannot be shared between threads safely
  --> src-tauri/src/logging.rs:83:5
   |
83 |     tracing::subscriber::set_global_default(subscriber).expect("Set global default log subscriber");
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*mut winapi::shared::windef::HWND__` cannot be shared between threads safely
   |
  ::: /home/thecallsign/.cargo/registry/src/github.jparrowsec.cn-1ecc6299db9ec823/tracing-0.1.26/src/subscriber.rs:41:28
   |
41 |     S: Subscriber + Send + Sync + 'static,
   |                            ---- required by this bound in `tracing::subscriber::set_global_default`
   |
   = help: within `Layered<BunyanFormattingLayer<FrontendLogger>, Layered<BunyanFormattingLayer<NonBlocking>, Layered<tracing_subscriber::fmt::Layer<Registry, DefaultFields, Format, NonBlocking>, Registry>>>`, the trait `std::marker::Sync` is not implemented for `*mut winapi::shared::windef::HWND__`
   = note: required because it appears within the type `tao::platform_impl::platform::event_loop::EventLoopProxy<tauri_runtime_wry::Message>`
   = note: required because it appears within the type `tao::event_loop::EventLoopProxy<tauri_runtime_wry::Message>`
   = note: required because it appears within the type `tauri_runtime_wry::DispatcherContext`
   = note: required because it appears within the type `tauri_runtime_wry::WryHandle`
   = note: required because it appears within the type `AppHandle`
   

@TheCallSign
Copy link
Author

With regards to this error:

error[E0277]: `*mut winapi::shared::windef::HWND__` cannot be shared between threads safely
  --> src-tauri/src/logging.rs:83:5
   |
83 |     tracing::subscriber::set_global_default(subscriber).expect("Set global default log subscriber");
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*mut winapi::shared::windef::HWND__` cannot be shared between threads safely
   |
  ::: /home/thecallsign/.cargo/registry/src/github.jparrowsec.cn-1ecc6299db9ec823/tracing-0.1.26/src/subscriber.rs:41:28
   |
41 |     S: Subscriber + Send + Sync + 'static,
   |                            ---- required by this bound in `tracing::subscriber::set_global_default`
   |
   = help: within `Layered<BunyanFormattingLayer<FrontendLogger>, Layered<BunyanFormattingLayer<NonBlocking>, Layered<tracing_subscriber::fmt::Layer<Registry, DefaultFields, Format, NonBlocking>, Registry>>>`, the trait `std::marker::Sync` is not implemented for `*mut winapi::shared::windef::HWND__`
   = note: required because it appears within the type `tao::platform_impl::platform::event_loop::EventLoopProxy<tauri_runtime_wry::Message>`
   = note: required because it appears within the type `tao::event_loop::EventLoopProxy<tauri_runtime_wry::Message>`
   = note: required because it appears within the type `tauri_runtime_wry::DispatcherContext`
   = note: required because it appears within the type `tauri_runtime_wry::WryHandle`
   = note: required because it appears within the type `AppHandle`

Wrapping the AppHandle with an Arc<RwLock<T>> does not work (tauri_runtime_wry::Message does not impl Send):

error[E0277]: `std::sync::mpsc::Sender<tauri_runtime_wry::Message>` cannot be shared between threads safely
  --> src-tauri/src/logging.rs:87:5
   |
87 |     tracing::subscriber::set_global_default(subscriber).expect("Set global default log subscriber");
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::sync::mpsc::Sender<tauri_runtime_wry::Message>` cannot be shared between threads safely
   |
  ::: /home/thecallsign/.cargo/registry/src/github.jparrowsec.cn-1ecc6299db9ec823/tracing-0.1.26/src/subscriber.rs:41:21
   |
41 |     S: Subscriber + Send + Sync + 'static,
   |                     ---- required by this bound in `tracing::subscriber::set_global_default`
   |
   = help: within `AppHandle`, the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Sender<tauri_runtime_wry::Message>`
   = note: required because it appears within the type `tao::platform_impl::platform::event_loop::EventLoopProxy<tauri_runtime_wry::Message>`
   = note: required because it appears within the type `tao::event_loop::EventLoopProxy<tauri_runtime_wry::Message>`
   = note: required because it appears within the type `tauri_runtime_wry::DispatcherContext`
   = note: required because it appears within the type `tauri_runtime_wry::WryHandle`
   = note: required because it appears within the type `AppHandle`
   = note: required because of the requirements on the impl of `std::marker::Sync` for `parking_lot::lock_api::RwLock<parking_lot::RawRwLock, AppHandle>`
   = note: required because of the requirements on the impl of `std::marker::Send` for `Arc<parking_lot::lock_api::RwLock<parking_lot::RawRwLock, AppHandle>>`

@TheCallSign TheCallSign changed the title AppHandle is not Sync on Windows AppHandle is not Send + Sync on Windows Aug 3, 2021
@wusyong
Copy link
Member

wusyong commented Aug 8, 2021

I believe tao::event_loop::EventLoopProxy should be Send only.
It turns out glib::Sender is actually Send + Sync.
Thanks for notifying this!
@lucasfernog Should AppHandle be Send + Sync? Or it just needs Send to send the messages?

@lucasfernog
Copy link
Member

I think AppHandle only needs to be Send since it implements Clone so it's easy to manage it. But it needs to be consistent across platforms.

@wusyong
Copy link
Member

wusyong commented Aug 8, 2021

For EventLoopProxy it should be Send only imho.
So if that's the only thing that affect AppHandle, I think it should be Send only too.
I'll check it across platform later.

@lucasfernog
Copy link
Member

I'll take a look on Windows.

@lucasfernog
Copy link
Member

I just checked https://docs.rs/tao/0.4.0/tao/event_loop/struct.EventLoopProxy.html and https://docs.rs/tao/0.4.0/x86_64-pc-windows-msvc/tao/event_loop/struct.EventLoopProxy.html
the proxy is Sync on Linux, and !Sync on Windows. Maybe we should force them to be !Sync on all platforms (the proxy and also AppHandle).

@wusyong
Copy link
Member

wusyong commented Aug 10, 2021

I'm thinking about maybe we could use channel from crossbeam since the performance from std is quite slow anyway.
It's sender is also Send + Sync that could ease our pain a lot

@lucasfernog
Copy link
Member

@wusyong can you patch it in tao? Yesterday I saw that tao 0.5 has a breaking change on macOS because it's no longer Sync (it used to work, now the same code only works on Linux and I had to make some changes).

@lucasfernog
Copy link
Member

AppHandle will be Sync on Windows on the next release, @wusyong fixed it here: tauri-apps/tao#181

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants