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

Strange conflict between NSProcessInfo and NSScreen, causing segmentation fault. #107

Open
wspl opened this issue Oct 11, 2021 · 1 comment

Comments

@wspl
Copy link

wspl commented Oct 11, 2021

I found a strange conflict issue between NSScreen and NSProcessInfo. Using both NSProcessInfo.operatingSystemVersion and UIScreen.mainScreen will cause the application to crash with "segmentation fault". But I can't imagine the relation between them.

Minimal Example:

#[macro_use]
extern crate objc;

use cocoa::{appkit::NSScreen, base::nil};
use objc::{runtime::Object};

fn main() {
    unsafe {
        let ns_process_info = class!(NSProcessInfo);
        let process_info: *mut Object = msg_send![ns_process_info, processInfo];
        // Deleting either of the following two lines will avoid the crash.
        let os_version: *const Object = msg_send![process_info, operatingSystemVersion];
        let screen = NSScreen::mainScreen(nil);
    }
}
[package]
name = "rsplg"
version = "0.1.0"
edition = "2018"

[dependencies]
cocoa = "0.24"
objc = "0.2.7"
objc-foundation = "0.1"
@madsmtm
Copy link

madsmtm commented Oct 14, 2021

msg_send! has no way to know what sending the operatingSystemVersion selector to NSProcessInfo could possibly return, so when you write let os_version: *const Object, you have the responsibility to ensure that the return type is correct. When it isn't you get to keep both pieces (this is unsafe code after all).

In this case, operatingSystemVersion does not return an instance pointer (*const Object), the return type is a struct NSOperatingSystemVersion with three integers (found out by looking at C header files and the documentation).

So the correct usage would be:

use cocoa::foundation::NSInteger;

#[repr(C)]
struct NSOperatingSystemVersion {
    major_version: NSInteger;
    minor_version: NSInteger;
    patch_version: NSInteger;
}

let os_version: NSOperatingSystemVersion = msg_send![process_info, operatingSystemVersion];

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

2 participants