Open agg23 opened 11 months ago
Hmmm, can you throw together a repo or test case? It's probably a straightforward (as you say) case, but I've run async-std
in the background of a cacao app without any issues. It should work so I'm wondering if there's something I'm missing.
(I was building a magic-wormhole for macOS app before I got... sidetracked... by life, lol: https://twitter.com/ryanmcgrath/status/1657967789142069249)
Most likely it's my inexperience with Rust runtimes (including Tokio), but here's a simple example of Tokio functioning normally, but nothing happening from AppKit:
use std::time::Duration;
use cacao::appkit::{App, AppDelegate};
struct MacApp;
impl AppDelegate for MacApp {
fn did_finish_launching(&self) {
println!("AppKit running");
}
}
#[tokio::main]
async fn main() {
tokio::task::spawn(async {
loop {
tokio::time::sleep(Duration::from_secs(1)).await;
println!("Timer");
}
});
println!("Starting AppKit");
tokio::task::spawn_blocking(|| {
App::new("com.example.cacao_runtime", MacApp).run();
});
println!("After AppKit");
// We await this to keep the runtime alive/in scope
let _ = tokio::task::spawn_blocking(|| {
let mut spin_count: u128 = 0;
loop {
if spin_count % 100_000_000 == 0 {
println!("Tick");
}
spin_count += 1;
}
})
.await;
}
[package]
name = "cacao_runtime"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cacao = "0.3.2"
tokio = { version = "1.29.1", features = ["rt-multi-thread", "macros", "time"] }
Expected output would be something like:
Starting AppKit
After AppKit
AppKit running
Tick
Tick
Tick
Tick
Tick
Tick
Timer
Tick
Tick
but what we actually get is:
Starting AppKit
After AppKit
Tick
Tick
Tick
Tick
Tick
Tick
Timer
Tick
Tick
That is, just missing the applicationDidFinishLaunching
callback. I've tried stepping through to see where it is getting hung up, but as you know debugging Rust and mixing that with weird Obj-C bridging makes it difficult to tell.
I neglected to check Console (it's been a while since I've done native Mac dev) and it has the errors I would expect to see:
nextEventMatchingMask should only be called from the Main Thread!
0 CoreFoundation 0x00000001849bf154 __exceptionPreprocess + 176
1 libobjc.A.dylib 0x00000001844de4d4 objc_exception_throw + 60
2 AppKit 0x0000000187b65730 -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 2844
3 AppKit 0x0000000187b59344 -[NSApplication run] + 464
4 cacao_runtime 0x0000000102e17d00 _ZN60_$LT$$LP$$RP$$u20$as$u20$objc..message..MessageArguments$GT$6invoke17h12be76bf795947fcE + 64
5 cacao_runtime 0x0000000102e1540c _ZN4objc7message8platform15send_unverified17ha796ec4ed66cc196E + 132
6 cacao_runtime 0x0000000102d9cc78 _ZN5cacao6appkit3app12App$LT$T$GT$3run17hf58e0486b6006dd4E + 1128
7 cacao_runtime 0x0000000102d9a2e4 _ZN13cacao_runtime4main28_$u7b$$u7b$closure$u7d$$u7d$28_$u7b$$u7b$closure$u7d$$u7d$17hd8172443011b6a22E + 48
8 cacao_runtime 0x0000000102d8f1b8 _ZN102_$LT$tokio..runtime..blocking..task..BlockingTask$LT$T$GT$$u20$as$u20$core..future..future..Future$GT$4poll17hb9c9f029929224eaE + 132
9 cacao_runtime 0x0000000102da8304 _ZN5tokio7runtime4task4core17Core$LT$T$C$S$GT$4poll28_$u7b$$u7b$closure$u7d$$u7d$17h7f5a88512ab017caE + 212
10 cacao_runtime 0x0000000102dad7f0 _ZN5tokio4loom3std11unsafe_cell19UnsafeCell$LT$T$GT$8with_mut17hde88e3fb917c4a1fE + 116
11 cacao_runtime 0x0000000102da7948 _ZN5tokio7runtime4task4core17Core$LT$T$C$S$GT$4poll17hda124c6f292a9904E + 60
12 cacao_runtime 0x0000000102d8a8e8 _ZN5tokio7runtime4task7harness11poll_future28_$u7b$$u7b$closure$u7d$$u7d$17h17a69bd3afb875b7E + 52
13 cacao_runtime 0x0000000102daa5c4 _ZN115_$LT$core..panic..unwind_safe..AssertUnwindSafe$LT$F$GT$$u20$as$u20$core..ops..function..FnOnce$LT$$LP$$RP$$GT$$GT$9call_once17h377b375a72208ef4E + 32
14 cacao_runtime 0x0000000102d84a30 _ZN3std9panicking3try7do_call17h7121ce0bd98866e0E + 80
15 cacao_runtime 0x0000000102d86abc __rust_try + 32
16 cacao_runtime 0x0000000102d83220 _ZN3std9panicking3try17h50c99e988ef95498E + 88
17 cacao_runtime 0x0000000102d9abb4 _ZN3std5panic12catch_unwind17h21c3e78dabca9ef9E + 32
18 cacao_runtime 0x0000000102d895ec _ZN5tokio7runtime4task7harness11poll_future17h0920160fd41ff4f6E + 88
19 cacao_runtime 0x0000000102d8b37c _ZN5tokio7runtime4task7harness20Harness$LT$T$C$S$GT$10poll_inner17h17b2d0168c33e1b8E + 152
20 cacao_runtime 0x0000000102d8cf00 _ZN5tokio7runtime4task7harness20Harness$LT$T$C$S$GT$4poll17h645251064a14bfbaE + 28
21 cacao_runtime 0x0000000102d90e7c _ZN5tokio7runtime4task3raw4poll17h0d21aba4197c8f20E + 36
22 cacao_runtime 0x0000000102deefec _ZN5tokio7runtime4task3raw7RawTask4poll17h8a889579cb74c1a9E + 52
23 cacao_runtime 0x0000000102e144d8 _ZN5tokio7runtime4task20UnownedTask$LT$S$GT$3run17h548292c9c263f839E + 64
24 cacao_runtime 0x0000000102de36f4 _ZN5tokio7runtime8blocking4pool4Task3run17h5490f2426d23d212E + 32
25 cacao_runtime 0x0000000102de5a20 _ZN5tokio7runtime8blocking4pool5Inner3run17hc7336af942a1a08bE + 2048
26 cacao_runtime 0x0000000102de5168 _ZN5tokio7runtime8blocking4pool7Spawner12spawn_thread28_$u7b$$u7b$closure$u7d$$u7d$17he87d18d8647265eeE + 144
27 cacao_runtime 0x0000000102df4114 _ZN3std10sys_common9backtrace28__rust_begin_short_backtrace17h969e25d9b1883eefE + 16
28 cacao_runtime 0x0000000102dd6944 _ZN3std6thread7Builder16spawn_unchecked_28_$u7b$$u7b$closure$u7d$$u7d$28_$u7b$$u7b$closure$u7d$$u7d$17h99843e47d788cba7E + 40
29 cacao_runtime 0x0000000102df40a0 _ZN115_$LT$core..panic..unwind_safe..AssertUnwindSafe$LT$F$GT$$u20$as$u20$core..ops..function..FnOnce$LT$$LP$$RP$$GT$$GT$9call_once17hf6e8443d19a8f93dE + 40
30 cacao_runtime 0x0000000102df5328 _ZN3std9panicking3try7do_call17h8a1e22ca148ae7c5E + 80
31 cacao_runtime 0x0000000102dfb0f4 __rust_try + 32
32 cacao_runtime 0x0000000102df481c _ZN3std9panicking3try17h7145ca67fa1682d1E + 76
33 cacao_runtime 0x0000000102dd67d0 _ZN3std6thread7Builder16spawn_unchecked_28_$u7b$$u7b$closure$u7d$$u7d$17hd8478c3e6c7d96a7E + 396
34 cacao_runtime 0x0000000102ddb0c8 _ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17h28bbec7738f2b412E + 24
35 cacao_runtime 0x0000000102e80f00 _ZN3std3sys4unix6thread6Thread3new12thread_start17h999abeaf027c3bbaE + 48
36 libsystem_pthread.dylib 0x0000000184867fa8 _pthread_start + 148
37 libsystem_pthread.dylib 0x0000000184862da0 thread_start + 8
I'm not horribly surprised at this, but I am curious how it knows that it is not running in the main thread (is it grabbing the process's thread list and ordering them, instead of just marking the thread it started on as main?). I'm guessing the trivial solution is to start the Tokio runtime from within AppKit's, which would be more traditional for Apple apps.
Yeah, so what I've done is just start a new thread inside of did_finish_launching
for the async stuff to live in, then pass things over to be handled.
The Elm-style of messaging is still optimal for running the UI flow in cacao, so just message pass back when things are done. I can try to clean up and open source my example code for this if it'd be helpful.
I'm interested in how others may have mixed the AppKit runtime with something Rust-centric, whether
async-std
,tokio
, or something else. Use cases are primarily in mixed platform systems, the core Rust code can't be designed around the standard Apple runtime, and needs something from the Rust ecosystem to actually be usable.I have found that naively calling
NSApplication.run()
withintokio::task::spawn_blocking
results in the event loop hanging.