AugmendTech / CrabGrab

🦀 🖥️ 🦀
Apache License 2.0
153 stars 11 forks source link

bug: panic when close the window which is capturing. #45

Open qzd1989 opened 2 months ago

qzd1989 commented 2 months ago

when I capture window: com.apple.calculator the program will 100% crush when I close the calculator window. the panic line is : crabgrab::platform::macos::objc_wrap::sc_stream_handler_did_stop_with_error panic log is:

thread '<unnamed>' panicked at core/src/panicking.rs:221:5:
panic in a function that cannot unwind
stack backtrace:
   0:        0x100e3efa8 - std::backtrace_rs::backtrace::libunwind::trace::hf12c30de7d9f723f
                               at /rustc/13a52890dde8cfeb95069d77c223ac37c0cf3a46/library/std/src/../../backtrace/src/backtrace/libunwind.rs:116:5
   1:        0x100e3efa8 - std::backtrace_rs::backtrace::trace_unsynchronized::hc2cf75e76296c984
                               at /rustc/13a52890dde8cfeb95069d77c223ac37c0cf3a46/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
   2:        0x100e3efa8 - std::sys::backtrace::_print_fmt::h837e47390db4e5f0
                               at /rustc/13a52890dde8cfeb95069d77c223ac37c0cf3a46/library/std/src/sys/backtrace.rs:66:9
   3:        0x100e3efa8 - <std::sys::backtrace::BacktraceLock::print::DisplayBacktrace as core::fmt::Display>::fmt::h5d78773155c0128d
                               at /rustc/13a52890dde8cfeb95069d77c223ac37c0cf3a46/library/std/src/sys/backtrace.rs:39:26
   4:        0x100e587dc - core::fmt::rt::Argument::fmt::h7f82efcac3f22279
                               at /rustc/13a52890dde8cfeb95069d77c223ac37c0cf3a46/library/core/src/fmt/rt.rs:173:76
   5:        0x100e587dc - core::fmt::write::h45d9e479f0390895
                               at /rustc/13a52890dde8cfeb95069d77c223ac37c0cf3a46/library/core/src/fmt/mod.rs:1178:21
   6:        0x100e3c9a8 - std::io::Write::write_fmt::h328e2fb8c208629c
                               at /rustc/13a52890dde8cfeb95069d77c223ac37c0cf3a46/library/std/src/io/mod.rs:1823:15
   7:        0x100e4012c - std::sys::backtrace::BacktraceLock::print::h11800baffc35bd77
                               at /rustc/13a52890dde8cfeb95069d77c223ac37c0cf3a46/library/std/src/sys/backtrace.rs:42:9
   8:        0x100e4012c - std::panicking::default_hook::{{closure}}::hfe183d5a22bc03d7
                               at /rustc/13a52890dde8cfeb95069d77c223ac37c0cf3a46/library/std/src/panicking.rs:266:22
   9:        0x100e3fcdc - std::panicking::default_hook::he287f7c2fe1febec
                               at /rustc/13a52890dde8cfeb95069d77c223ac37c0cf3a46/library/std/src/panicking.rs:293:9
  10:        0x100e40ba8 - std::panicking::rust_panic_with_hook::h13dc8e155d05779d
                               at /rustc/13a52890dde8cfeb95069d77c223ac37c0cf3a46/library/std/src/panicking.rs:797:13
  11:        0x100e405ac - std::panicking::begin_panic_handler::{{closure}}::h8125ad377853d789
                               at /rustc/13a52890dde8cfeb95069d77c223ac37c0cf3a46/library/std/src/panicking.rs:664:13
  12:        0x100e3f46c - std::sys::backtrace::__rust_end_short_backtrace::hb9811b846059b12e
                               at /rustc/13a52890dde8cfeb95069d77c223ac37c0cf3a46/library/std/src/sys/backtrace.rs:170:18
  13:        0x100e4029c - rust_begin_unwind
                               at /rustc/13a52890dde8cfeb95069d77c223ac37c0cf3a46/library/std/src/panicking.rs:662:5
  14:        0x100e66da4 - core::panicking::panic_nounwind_fmt::runtime::hd5f6fcfb21f88a1e
                               at /rustc/13a52890dde8cfeb95069d77c223ac37c0cf3a46/library/core/src/panicking.rs:112:18
  15:        0x100e66da4 - core::panicking::panic_nounwind_fmt::h70b25dcf035c785b
                               at /rustc/13a52890dde8cfeb95069d77c223ac37c0cf3a46/library/core/src/panicking.rs:122:5
  16:        0x100e66e1c - core::panicking::panic_nounwind::ha80ca26d58d7ed65
                               at /rustc/13a52890dde8cfeb95069d77c223ac37c0cf3a46/library/core/src/panicking.rs:221:5
  17:        0x100e66f94 - core::panicking::panic_cannot_unwind::h2e86871258063559
                               at /rustc/13a52890dde8cfeb95069d77c223ac37c0cf3a46/library/core/src/panicking.rs:310:5
  18:        0x100de2354 - crabgrab::platform::macos::objc_wrap::sc_stream_handler_did_stop_with_error::hdc9b45b0d58c3aee
                               at /Users/kiwi/Documents/Rust/wise-key/src-tauri/libs/crabgrab/src/platform/macos/objc_wrap.rs:1322:1
  19:        0x1f4e6e170 - <unknown>
  20:        0x1f4e6a574 - <unknown>
  21:        0x195260750 - <unknown>
  22:        0x1952623e8 - <unknown>
  23:        0x195269a14 - <unknown>
  24:        0x19526a544 - <unknown>
  25:        0x1952752d0 - <unknown>
  26:        0x195274b44 - <unknown>
  27:        0x19540f00c - _pthread_mach_thread_np
thread caused non-unwinding panic. aborting.
zsh: abort      cargo run --example server
qzd1989 commented 2 months ago

image here is my system info

OutOfTheVoid commented 2 months ago

Hey there @qzd1989, can you share a minimal code example to reproduce this issue? I can't tell much about what's going on with just a stack trace (This does lead me to believe there's some work we can do to handle stream errors more reliably though).

qzd1989 commented 2 months ago

Hey there @qzd1989, can you share a minimal code example to reproduce this issue? I can't tell much about what's going on with just a stack trace (This does lead me to believe there's some work we can do to handle stream errors more reliably though).

Thank you! Yes, I reproduced the BUG 100% by using code below. Before you run this code, you should open the app "calculator" or "chrome" first on mac. :) "calculator" or "chrome" window is showed on the middle display.

image
rustc 1.82.0-nightly (13a52890d 2024-08-14)
[dependencies]
crabgrab = { version = "0.4.0", features = ["bitmap"] }
tokio = { version = "1.39.3", features = ["full", "macros", "rt-multi-thread"] }
use crabgrab::{feature::bitmap::VideoFrameBitmap as _, prelude::*};

fn main() {
    //100% panic when I close them manually
    // let identifier = "com.apple.calculator".to_string();
    let identifier = "com.google.chrome".to_string();
    let runtime = tokio::runtime::Runtime::new().unwrap();
    runtime.block_on(async move {
        let token = match CaptureStream::test_access(false) {
            Some(token) => token,
            None => CaptureStream::request_access(false)
                .await
                .expect("Expected capture access"),
        };
        let config = get_capture_config_by_identifier(identifier.clone()).await;
        if let None = config {
            return;
        }
        let callback = move |stream_event| match stream_event {
            Ok(event) => {
                if let StreamEvent::Video(frame) = event {
                    match frame.get_bitmap() {
                        Ok(bitmap) => match bitmap {
                            FrameBitmap::BgraUnorm8x4(data) => {
                                //Another BUG: data.width/height won't change while I change the window size.
                                //see here: https://github.com/AugmendTech/CrabGrab/issues/44
                                println!("window size: ({:?}, {:?})", data.width, data.height);
                            }
                            _ => {}
                        },
                        Err(_) => {}
                    }
                }
            }
            Err(_) => {}
        };
        let mut stream = CaptureStream::new(token, config.unwrap(), callback).unwrap();
        tokio::task::block_in_place(|| std::thread::sleep(std::time::Duration::from_millis(40000)));
        stream.stop().unwrap();
    });
}

async fn get_window_by_identifier(identifier: String) -> Option<CapturableWindow> {
    let mut monitor: Option<CapturableWindow> = None;
    let filter = CapturableContentFilter::NORMAL_WINDOWS;
    let content = CapturableContent::new(filter).await.unwrap();
    for window in content.windows() {
        if window.application().identifier().to_lowercase() == identifier {
            monitor = Some(window);
        }
    }
    return monitor;
}

async fn get_capture_config_by_identifier(identifier: String) -> Option<CaptureConfig> {
    match get_window_by_identifier(identifier.clone()).await {
        Some(window) => {
            Some(CaptureConfig::with_window(window, CapturePixelFormat::Bgra8888).unwrap())
        }
        None => None,
    }
}

https://github.com/user-attachments/assets/0b3ff2ab-fd06-49a0-806e-a8503f969d1c