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

SIGSEGV on MacOS #11

Open
sagacity opened this issue May 15, 2020 · 7 comments
Open

SIGSEGV on MacOS #11

sagacity opened this issue May 15, 2020 · 7 comments
Labels
bug Something isn't working

Comments

@sagacity
Copy link

sagacity commented May 15, 2020

I'm seeing crashes on MacOS Catalina (10.15.3) with Rust 1.43.1. This happens in the original clipboard crate as well, but since that seems unmaintained I'm reporting it here.

You can reproduce the crash by running cargo test in my fork.

You may need to run it a few times, but you will get different errors such as:

failing-517cc89e9cb2a459(35714,0x70000ebe5000) malloc: *** error for object 0x7f8eb170a6e0: pointer being freed was not allocated
failing-517cc89e9cb2a459(35714,0x70000ebe5000) malloc: *** set a breakpoint in malloc_error_break to debug

Or:

failing-517cc89e9cb2a459(35969,0x700000ae7000) malloc: Double free of object 0x7fe935c10a50
failing-517cc89e9cb2a459(35969,0x700000ae7000) malloc: *** set a breakpoint in malloc_error_break to debug

I'm unfortunately no MacOS developer so I have no idea what causes this, but it only seems to occur when I'm accessing the clipboard from both my test code and my regular (under test) code, like in some_other_fn in the code below. Moving the ClipboardContext to a shared static using something like lazy_static! does not help.

The test is fairly simple:

use copypasta::{ClipboardContext, ClipboardProvider};

fn some_other_fn() {
    let mut ctx = ClipboardContext::new().unwrap();
    ctx.get_contents().unwrap();
}

#[cfg(test)]
mod tests {
    use super::*;

    fn clear_clipboard() {
        let mut clipboard: ClipboardContext = ClipboardContext::new().unwrap();
        clipboard.set_contents("".into()).unwrap();
    }

    #[test]
    fn foo() {
        clear_clipboard();

        let mut ctx = ClipboardContext::new().unwrap();
        ctx.set_contents("Dummy".into()).unwrap();
        ctx.get_contents().unwrap();

        some_other_fn();
    }

    #[test]
    fn bar() {
        clear_clipboard();

        let mut ctx = ClipboardContext::new().unwrap();
        ctx.set_contents("Dummy".into()).unwrap();
        ctx.get_contents().unwrap();

        some_other_fn();
    }
}
@sagacity
Copy link
Author

Ah, I've tested it now with cargo test -- --test-threads=1 and that works so it's probably a concurrency issue. I guess the MacOS code needs a RwLock. I'll see if I can contribute.

@chrisduerr chrisduerr added the bug Something isn't working label May 15, 2020
@chrisduerr
Copy link
Member

chrisduerr commented May 15, 2020

I'll see if I can contribute.

That would be great, since I'm not much of a macOS developer either. It's probably also a good idea to check why exactly this is crashing, rather than just putting an RwLock on it without having a clear understanding of what exactly is going wrong.

@sagacity
Copy link
Author

Fair enough, the PR was a bit premature :)

According to https://developer.apple.com/documentation/appkit/nspasteboard there is a general pasteboard that is shared by all applications. I'm not sure how the release works (when the Id goes out of scope), but the docs mention that releaseGlobally() on the pasteboard Releases the receiver’s resources in the pasteboard server. Could it be that the contents that I set in one instance of ClipboardContext are released when I try to retrieve it from another ClipboardContext?

@chrisduerr
Copy link
Member

Could it be that the contents that I set in one instance of ClipboardContext are released when I try to retrieve it from another ClipboardContext?

I don't know how it works, sure it could be. However this needs to work cross-application too, so that would mean that if I free something in my application while you try to read in your application, it would segfault, which seems unlikely? Unless I understood you incorrectly.

@sagacity
Copy link
Author

I meant I was wondering that maybe dropping the OSXClipboardContext struct is releasing the pasteboard for my entire running application instead of just for that OSXClipboardContext instance. But, again, that's mostly speculation on my end.

@MattX
Copy link

MattX commented Jul 11, 2021

According to this SO thread and Apple documentation on the topic, in Cocoa, "mutable objects are generally not thread-safe". I think this justifies putting the NSPasteboard in an RwLock at least?

I don't think releaseGlobally matters here—copypasta only uses the general pasteboard, and the Apple doc says

Although you must call this method to release a temporary, privately named pasteboard to avoid leaks, you should never call it on a standard pasteboard.

MattX added a commit to MattX/copypasta that referenced this issue Jul 13, 2021
@madsmtm
Copy link
Contributor

madsmtm commented Apr 30, 2024

I suspect the proper solution here is to only access the generalPasteboard from the main thread, as that's where all other macOS code would access it from as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Development

No branches or pull requests

4 participants