ankitects / ankitects/anki

mpv callback exceptions terminate event dispatch

未关闭
#5,527 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看
主要语言
Rust
星标
30.5k
派生
3.2k
PR 合并指标
PR 指标待抓取

描述

## Problem

An exception raised by an mpv event callback escapes `MPV._handle_event()`. The remaining callbacks for that event are skipped, and the exception propagates out of `_event_reader()`, terminating the event-dispatch thread.

`MpvManager.on_property_idle_active()` also assumes `aqt.mw` is available. If an idle notification arrives after it has been cleared during teardown, the callback raises `AttributeError`.

## Reproduction

This is a deterministic callback-level reproduction, not a report of a normal-review playback failure. In an Anki development Python environment with `aqt` importable, run:

```python
from aqt.mpv import MPV

player = MPV.__new__(MPV)
player._callbacks_initialized = True
calls = []

def failing_callback():
raise RuntimeError("callback failed")

player._callbacks = {
"file-loaded": [failing_callback, lambda: calls.append("handled")]
}
player._handle_event({"event": "file-loaded"})
assert calls == ["handled"]
```

Before the fix, the call raises `RuntimeError` and the second callback is not invoked. Property-change callbacks have the same problem.

The teardown case can be reproduced in an isolated test by creating an uninitialized `MpvManager`, assigning a completion callback, monkeypatching `aqt.mw` to `None`, and calling `on_property_idle_active(True)`. Before the fix, this raises `AttributeError: 'NoneType' object has no attribute 'taskman'`.

## Expected behavior

- A failing callback is reported without preventing other callbacks or later events from being processed.
- An idle notification received after the main window has been cleared does not try to schedule work through it.
- With a live main window, completion still runs through `taskman.run_on_main()`.

## Impact and evidence

If a callback raises during event dispatch, subsequent mpv completion/property notifications are no longer handled by that event thread. This could leave playback bookkeeping or a queued playback sequence stuck. That downstream playback consequence has not been reproduced during normal review; the exception paths are covered by deterministic regression tests. No data loss is claimed.

Relevant code at the tested baseline:

- [Event reader and callback dispatch](https://github.com/ankitects/anki/blob/5edc31694f07487266bb8c4725508f6c5f5c198d/qt/aqt/mpv.py#L521-L548)
- [Idle completion callback](https://github.com/ankitects/anki/blob/5edc31694f07487266bb8c4725508f6c5f5c198d/qt/aqt/sound.py#L499-L504)

Tested against `main` at `5edc31694` on macOS with Python 3.13.13. A small fix with regression tests is ready.

贡献指南

打开贡献指南

评估

这个 Issue 还没有评估数据。

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。