rust-windowing / rust-windowing/winit

macOS: IME insertText panics during window teardown with active marked text

Open
#4,626 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

Description

Description

With an active marked-text composition, dropping a macOS winit 0.30.13 window can synchronously call NSTextInputClient::insertText while the WinitView no longer has a WinitWindow. insert_text calls queue_event, whose weak window lookup panics with view to have a window. Because the Rust method is an Objective-C callback, the panic cannot unwind and the process aborts.

This is the insertText variant of the lifecycle family reported in #4333. The guard added by #4334 covers firstRectForCharacterRange, not this path.

Calling Window::set_ime_allowed(false) while the window is still alive, immediately before requesting event-loop exit, prevents the abort in 20/20 runs because winit clears its marked-text state. That is a usable application workaround, but a late insertText callback should not be able to abort inside winit after the view detaches.

Minimal reproduction
use std::time::{Duration, Instant};

use winit::application::ApplicationHandler;
use winit::event::WindowEvent;
use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
use winit::window::{Window, WindowId};

struct App {
    started: Instant,
    window: Option<Window>,
}

impl ApplicationHandler for App {
    fn resumed(&mut self, event_loop: &ActiveEventLoop) {
        let window = event_loop
            .create_window(Window::default_attributes().with_title("winit IME teardown repro"))
            .unwrap();
        window.set_ime_allowed(true);
        window.request_redraw();
        self.window = Some(window);
    }

    fn window_event(
        &mut self,
        event_loop: &ActiveEventLoop,
        _window_id: WindowId,
        event: WindowEvent,
    ) {
        match event {
            WindowEvent::RedrawRequested => self.window.as_ref().unwrap().focus_window(),
            WindowEvent::CloseRequested => event_loop.exit(),
            _ => {}
        }
    }

    fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) {
        if self.started.elapsed() >= Duration::from_millis(1800) {
            // Deliberately exit with IME enabled and marked text active.
            event_loop.exit();
        } else {
            event_loop.set_control_flow(ControlFlow::WaitUntil(
                self.started + Duration::from_millis(1800),
            ));
        }
    }
}

fn main() {
    let event_loop = EventLoop::new().unwrap();
    event_loop.set_control_flow(ControlFlow::Wait);
    let mut app = App { started: Instant::now(), window: None };
    event_loop.run_app(&mut app).unwrap();
}

Use winit = "=0.30.13", run the program, focus its window, switch to a Pinyin IME, and type zhongwen without committing before the 1.8-second exit. The process aborts deterministically on the tested input source.

Panic
thread 'main' panicked at .../winit-0.30.13/src/platform_impl/macos/view.rs:835:40:
view to have a window
...
WinitView::queue_event
WinitView::insert_text
...
WindowDelegate::dealloc
drop_glue<winit::window::Window>
thread caused non-unwinding panic. aborting.
Environment
  • macOS 15.7.5 (24G612), arm64
  • winit 0.30.13
  • Tencent Wetype Pinyin (com.tencent.inputmethod.wetype.pinyin)
  • Rust 1.97.0

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 in src/platform_impl/macos/view.rs around insert_text and queue_event, then run the minimal reproduction with winit 0.30.13 and an active Pinyin composition. Trace the teardown path where WinitView no longer has a WinitWindow; done means the late insertText callback no longer panics or aborts the process.

Written by the indexing model from the issue text.

Assessment

Tech stack
macos, rust
Domain
desktop, operating-systems
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.