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

Segmentation Fault while using 0.2.1 version #29

Closed
Pranav2612000 opened this issue Jan 15, 2024 · 7 comments · Fixed by #31
Closed

Segmentation Fault while using 0.2.1 version #29

Pranav2612000 opened this issue Jan 15, 2024 · 7 comments · Fixed by #31

Comments

@Pranav2612000
Copy link
Contributor

Previously, I was using a older version of the library and the screen capturing logic was working as expected. I've recently updated my code to use the latest version of screencapturekit-rs ( 0.2.1 ) and I've started seeing a Segmentation Fault.

Here's a sample code which reproduces the issue -

use std::{path::PathBuf, time, thread};

use core_graphics::display::{CGMainDisplayID, CGDisplay};
use screencapturekit::{sc_error_handler::StreamErrorHandler, sc_output_handler::{StreamOutput, SCStreamOutputType}, cm_sample_buffer::CMSampleBuffer, sc_content_filter::{InitParams, SCContentFilter}, sc_stream_configuration::SCStreamConfiguration, sc_stream::SCStream, sc_shareable_content::SCShareableContent};
use screencapturekit_sys::os_types::geometry::{CGRect, CGPoint, CGSize};

struct ErrorHandler;
impl StreamErrorHandler for ErrorHandler {
    fn on_error(&self) {
        println!("Error!");
    }
}

pub struct Capturer {
}

impl Capturer {
    pub fn new() -> Self {
        println!("Capturer initialized");
        Capturer {}
    }
}

impl StreamErrorHandler for Capturer {
    fn on_error(&self) {
        eprintln!("ERROR!");
    }
}

impl StreamOutput for Capturer {
    fn did_output_sample_buffer(&self, sample: CMSampleBuffer, of_type: SCStreamOutputType) {
        println!("New frame recvd");
    }
}
fn main() {
    println!("Starting");

    let content = SCShareableContent::current();
    let displays = content.displays;

    let display_id = unsafe { CGMainDisplayID() };
    let display = displays
        .iter()
        .find(|display| display.display_id == display_id)
        .unwrap_or_else(|| {
            panic!("Main display not found");
        });
    let display = display.to_owned();


    let mode = CGDisplay::new(display_id).display_mode().unwrap();
    let scale = (mode.pixel_width() / mode.width()) as u32;
    let width = display.width * scale;
    let height = display.height * scale;

    let params = InitParams::Display(display);
    let filter = SCContentFilter::new(params);

    let stream_config = SCStreamConfiguration {
        width,
        height,
        ..Default::default()
    };

    let mut stream = SCStream::new(filter, stream_config, ErrorHandler);
    stream.add_output(Capturer::new(), SCStreamOutputType::Screen);

    stream.start_capture();

    let ten_millis = time::Duration::from_millis(10000);

    thread::sleep(ten_millis);

    stream.stop_capture();

    println!("Ended");

}

This is the output I see
image

Maybe I'm using some part incorrectly but would be great if someone could look into this and help me out. Let me know if you need more help with the reproduction.

@1313
Copy link
Collaborator

1313 commented Jan 15, 2024

Oh I will look into it.

If you set the rust flags like this:

$ export RUSTFLAGS=-Zsanitizer=address RUSTDOCFLAGS=-Zsanitizer=address

And run your code with the nightly version, what does the dump say?

@Pranav2612000
Copy link
Contributor Author

Pranav2612000 commented Jan 16, 2024

Tried doing this. But was unable to get the Sanitizer to work. I see the following issue
image

Specifically the Please launch the executable with: .... .
Tried a couple of things but was not able to get rid of it. Do you know how I can get the Address Sanitizer working?

I was able to get the AddressSanitizer to work by explicitly passing in the --target option. Here's the output -
image

@Pranav2612000
Copy link
Contributor Author

I also forked the repo and tried running the tests in screencapturekit/src/sc_stream.rs. Those tests look almost the same as the above code, but those tests pass and work as expected.

@1313
Copy link
Collaborator

1313 commented Jan 16, 2024

Cool that helps!

It's an issue with how something being dropped with the wrong refcount. This will be fixed with my core-foundation pr. but I can fix it here too.

Thanks

@Pranav2612000
Copy link
Contributor Author

Great! Do you have an estimate on by when this'll be available?
Is there some workaround I can try in the meantime?

Also, out of curiosity, how did you figure It's an issue with how something being dropped with the wrong refcount.?

@1313
Copy link
Collaborator

1313 commented Jan 16, 2024

Fixed and pushed a new version v0.2.2

@1313
Copy link
Collaborator

1313 commented Jan 16, 2024

It was the call to CFRelease at the top which is called via the Id/ShareId traits which calls the CFRelease via its drop trait.

Objective C uses refcounting a similar model as RC and ARC.

The segfault happened in the CMSampleBuffer as it hold references to underlying image/pixelbuffers which was created in a bad way messing up the ref count.

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

Successfully merging a pull request may close this issue.

2 participants