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

[OSX] Crash when moving OpenGL context to another thread #1300

Closed
syrel opened this issue May 19, 2020 · 4 comments
Closed

[OSX] Crash when moving OpenGL context to another thread #1300

syrel opened this issue May 19, 2020 · 4 comments

Comments

@syrel
Copy link

syrel commented May 19, 2020

I can't seem to be able to move an OpenGL context to another thread on OSX.

Calling make_current() on a NotCurrent context (even splitted) from a non-main thread results in an illegal hardware instruction.

Any ideas?

Here is a modified window.rs example:

mod support;

use glutin::event::{Event, WindowEvent};
use glutin::event_loop::{ControlFlow, EventLoop};
use glutin::window::WindowBuilder;
use glutin::ContextBuilder;

use std::{thread, time};

fn main() {
    let el = EventLoop::new();
    let wb = WindowBuilder::new().with_title("A fantastic window!");

    let windowed_context =
        ContextBuilder::new().build_windowed(wb, &el).unwrap();

    thread::spawn(move || {
        thread::sleep(time::Duration::from_secs(1));
        let windowed_context =
            unsafe { windowed_context.make_current().unwrap() };

        println!(
            "Pixel format of the window's GL context: {:?}",
            windowed_context.get_pixel_format()
        );
    });

    el.run(move |event, _, control_flow| {
        println!("{:?}", event);
        *control_flow = ControlFlow::Wait;

        match event {
            Event::LoopDestroyed => return,
            Event::WindowEvent { event, .. } => match event {
                WindowEvent::CloseRequested => {
                    *control_flow = ControlFlow::Exit
                }
                _ => (),
            },
            _ => (),
        }
    });
}
@syrel
Copy link
Author

syrel commented May 20, 2020

It appears to crash during NSOpenGLContext update being called from a non-ui thread.
macOS Catalina 10.15.5 Beta (19F62f)

Process 5385 stopped
* thread #8, stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
    frame #0: 0x00007fff32709c3d AppKit`-[NSOpenGLContext update] + 525
AppKit`-[NSOpenGLContext update]:
->  0x7fff32709c3d <+525>: ud2    
    0x7fff32709c3f <+527>: movq   %rax, %r14
    0x7fff32709c42 <+530>: jmp    0x7fff32709c4b            ; <+539>
    0x7fff32709c44 <+532>: movq   %rax, %r14

@kchibisov
Copy link
Member

kchibisov commented Sep 3, 2022

I'd need to retest it with macOS, but I think the issue should be there after #1435. Solving it should be possibly though, given that we can use libdispatch to transfer update.

@kchibisov
Copy link
Member

I've looked in apple docs for that and it seems that it's fine https://developer.apple.com/documentation/appkit/nsopenglcontext/1436135-update?language=objc

@madsmtm
Copy link
Member

madsmtm commented Sep 3, 2022

We discussed this on Matrix, I could not reproduce the original issue on my machine (running macOS 10.14.6), neither on v0.24.1 nor v0.30.0-beta.1.

Even with the following diff (which is not safe, but for illustration) I did not get the crash:

diff --git a/glutin_examples/examples/window.rs b/glutin_examples/examples/window.rs
index 0b09a8a..0b1e596 100644
--- a/glutin_examples/examples/window.rs
+++ b/glutin_examples/examples/window.rs
@@ -66,17 +66,22 @@ fn main() {
         match event {
             Event::WindowEvent { event, .. } => match event {
                 WindowEvent::Resized(size) => {
-                    if size.width != 0 && size.height != 0 {
-                        // Some platforms like EGL require resizing GL surface to update the size
-                        // Notable platforms here are Wayland and macOS, other don't require it
-                        // and the function is no-op, but it's wise to resize it for portability
-                        // reasons.
-                        gl_window.surface.resize(
-                            &gl_context,
-                            NonZeroU32::new(size.width).unwrap(),
-                            NonZeroU32::new(size.height).unwrap(),
-                        );
-                    }
+                    use glutin::context::{AsRawContext, RawContext};
+                    // `objc = "0.2.7"`
+                    use objc::{msg_send, sel, sel_impl};
+
+                    dbg!(size);
+                    struct ThreadSafe<T>(T);
+                    unsafe impl<T> Send for ThreadSafe<T> {}
+                    let raw = ThreadSafe(gl_context.raw_context());
+                    std::thread::spawn(|| {
+                        let raw = raw;
+                        let raw: *const objc::runtime::Object = match raw.0 {
+                            RawContext::Cgl(x) => x.cast(),
+                        };
+
+                        let _: () = unsafe { msg_send![raw, update] };
+                    });
                 },
                 WindowEvent::CloseRequested => {
                     *control_flow = ControlFlow::Exit;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants