Skip to content

mpv callback exceptions terminate event dispatch #5527

Description

@hyetigran

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:

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:

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

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions