rust-windowing / rust-windowing/winit
MacOS panic: "tried to handle event while another event is currently being handled"
Nobody has claimed this yet.
- 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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