Skip to content

Comments

Fix fatal crash on Windows when window title matches MIDI loopback device name#17

Open
zitongcharliedeng wants to merge 2 commits intoflipcoder:mainfrom
zitongcharliedeng:fix/window-title-midi-crash
Open

Fix fatal crash on Windows when window title matches MIDI loopback device name#17
zitongcharliedeng wants to merge 2 commits intoflipcoder:mainfrom
zitongcharliedeng:fix/window-title-midi-crash

Conversation

@zitongcharliedeng
Copy link

@zitongcharliedeng zitongcharliedeng commented Feb 17, 2026

Summary

Fixes a fatal crash on some Windows setups where midimech silently dies ~1-2 seconds after launch with exit code -1 (0xFFFFFFFF). No Python traceback, no faulthandler output, no Windows Event Viewer entries — just a hard native process termination.

I was trying midimech on an older Windows system — I usually run it on Linux or a different Windows machine where loopMIDI works fine. This particular system has some combination of loopMIDI driver version, audio stack, or Windows configuration that triggers the issue. The exact underlying cause is unknown, but the fix is harmless and prevents the crash entirely.

Root Cause

pygame.display.set_caption("midimech") collides with the MIDI loopback device named "midimech" (created via loopMIDI). On this Windows setup, when an SDL window title matches a MIDI device name (case-insensitive), something in the MIDI subsystem fatally terminates the process approximately 1-2 seconds after the window is created. The crash happens during pygame.event.get() on the first frame of the main loop.

This only affects some Windows configurations — the exact mechanism is unknown. It does not appear to affect all Windows systems with loopMIDI.

How it was found

This took extensive bisection testing (~30 test scripts) over multiple sessions to isolate:

  1. Initial hypothesis (wrong): Python 3.12 bytecode optimization issue with the ~600-line Core.__init__ — the crash disappeared when __init__ was replaced with a standalone function via monkey-patching
  2. Key breakthrough: A bisection test that was identical to the working test except it called pygame.display.set_caption(TITLE) before set_mode() crashed, while the one without set_caption survived
  3. Isolation: Even a bare 10-line pygame program with just set_caption("midimech") + set_mode() + event loop crashed, while set_caption("test") or set_caption("midimech2") survived
  4. Confirmation: The crash is case-insensitive — "midimech", "Midimech", "midiMECH" all crash; "midimech app" or any non-matching string survives

Why the earlier init hypothesis was misleading

The monkey-patched __init__ tests survived because they set up the pygame display manually in the test script without calling set_caption(TITLE). The real Core.__init__ always called set_caption(TITLE), so it always crashed. The correlation with __init__ size was a red herring.

Changes

  • src/constants.py: Changed TITLE from "midimech" to "midimech app" to avoid the MIDI device name collision
  • src/core.py: Added init guard and try/except wrapper to cb_midi_in — prevents potential crashes if the MIDI callback fires before Core is fully initialized
  • midimech.py: Hardened main() cleanup — wrapped del core, pygame.midi.quit(), and pygame.display.quit() in individual try/except blocks so one failure doesn't prevent the others from running

Crash characteristics (for future reference)

If anyone encounters similar issues, here's the signature:

  • Exit code 0xFFFFFFFF (-1), not a Python exception
  • No traceback, faulthandler output, or Windows Event Viewer entries
  • atexit handlers don't run — this is a hard TerminateProcess
  • gc.disable() delays but doesn't prevent the crash
  • Variable timing (1-8 seconds), suggesting a race with a native thread
  • Only occurs on some Windows setups with loopMIDI; exact trigger conditions unknown

Verified

  • App runs stably for 60+ seconds after the fix
  • LinnStrument MIDI input/output working
  • All existing functionality preserved

On certain Windows systems, pygame.display.set_caption('midimech') causes
a fatal native process termination (exit code -1, no traceback) when a MIDI
loopback device named 'midimech' is present. This appears to be a
case-insensitive collision between SDL's window title and the Windows MIDI
subsystem, causing TerminateProcess ~1-2s after the window is created.

Fix: Change TITLE from 'midimech' to 'midimech app' to avoid the name
collision. Also harden the MIDI callback and shutdown cleanup.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant