rust-windowing / rust-windowing/winit

MacOS panic: "tried to handle event while another event is currently being handled"

Open
#3,992 3 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

B - crash DS - appkit
Dominant language
Rust
Stars
6.2k
Forks
1.3k
Avg merge
2d 19h
Merged PRs (30d)
9

Description

Discussed in https://github.com/rust-windowing/winit/discussions/3990 by @AlexanderHarrison

Originally posted by AlexanderHarrison November 9, 2024
Hi! I'm running into the aforementioned error on startup on macos. Linux and windows both work fine. I couldn't find any information about this error, or find anyone who has run into it before.

Unfortunately, I am relying on the help of a volunteer to compile on macos, so I am very limited in the amount of debugging I can do myself.

From looking at the winit source, it looks like each event call borrows a RefCell of the EventHandlerData, and somehow we are not dropping the RefMut before handing another event. The comment states that the panic "avoids re-entrancy". I assume that one of my handled events is somehow causing the event loop to handle another event, before dropping RefMut. Would this be caused by a method call into the event loop? Or a some method on the window? Not sure, I would love a pointer as to how this panic could come about.

Here's the (abridged) structure of my app. I don't think I'm doing anything crazy.

enum WinitRunner<'a> {
    // avoid lifetime issues
    None,

    Uninit {
        window: &'a mut Option<Window>,
    },
    Init {
        st: State,
        ctx: Ctx<'a>,
    },
}

impl<'a> ApplicationHandler<Update> for WinitRunner<'a> {
    fn resumed(&mut self, event_loop: &ActiveEventLoop) {
        if matches!(self, WinitRunner::Init { .. }) { return }

        env_logger::init();

        // avoid lifetime issues
        let s = std::mem::replace(self, WinitRunner::None);

        let window = match s {
            WinitRunner::Uninit { window } => window,
            _ => unreachable!(),
        };

        let window: &Window = window.insert(event_loop.create_window(
            Window::default_attributes()
                .with_min_inner_size(winit::dpi::PhysicalSize::new(MIN_WIDTH, MIN_HEIGHT))
                .with_title("title!")
        ).unwrap());

        let mut ctx = Ctx::new(window);
        let st = State::new(&mut ctx);

        *self = WinitRunner::Init { st, ctx }
    }
    
    fn window_event(&mut self, event_loop: &ActiveEventLoop, window_id: WindowId, event: WindowEvent) {
        let (st, ctx) = match self {
            WinitRunner::Init { st, ctx } => (st, ctx),
            _ => return,
        };

        st.window_event(ctx, event_loop, window_id, event);
    }

    fn user_event(&mut self, event_loop: &ActiveEventLoop, _event: Update) {
        let (st, ctx) = match self {
            WinitRunner::Init { st, ctx } => (st, ctx),
            _ => return,
        };

        st.user_event(ctx, event_loop);
    }
}

fn main() {
    let event_loop = EventLoop::with_user_event().build().unwrap();
    let event_sender = event_loop.create_proxy();
    std::thread::spawn(move || {
        loop {
            let _ = event_sender.send_event(Update);
            std::thread::sleep(UPDATE_PERIOD);
        }
    });

    let mut window = None;
    let mut runner: WinitRunner = WinitRunner::Uninit { window: &mut window };
    event_loop.run_app(&mut runner).unwrap();
}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at EventLoop::run_app and the ApplicationHandler callbacks shown, then inspect the macOS EventHandlerData RefCell path mentioned in the report. Reproduce the startup panic with the abridged runner and determine which callback or window operation causes re-entrancy. Done means the trigger is understood and the macOS startup path no longer panics.

Written by the indexing model from the issue text.

Assessment

Tech stack
macos, rust
Domain
desktop, operating-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.