Skip to content

fix: SIGTERM stops the audio player instead of orphaning it - #22

Merged
DavidTbilisi merged 1 commit into
masterfrom
fix/sigterm-stops-player
Oct 23, 2026
Merged

DavidTbilisi merged 1 commit into
masterfrom
fix/sigterm-stops-player

Conversation

@DavidTbilisi

Copy link
Copy Markdown
Owner

Summary

Sending kill (SIGTERM) to tts-ka mid-stream left mpv running. Python's default SIGTERM exits at once with no cleanup, so a headless mpv (--idle, driven over IPC) plays out its queued chunk and then idles forever. With a flatpak mpv, bwrap also moves mpv into its own process group, so even kill -- -PGID on the caller's group doesn't reach it. TTS_ka is the only thing that can stop it.

main() now turns SIGTERM into Terminated, a KeyboardInterrupt subclass, so it takes the existing Ctrl+C path (stop_active_streaming_player) and exits 143. If the parent process set SIGTERM to be ignored, it stays ignored.

The bug showed up in a Claude Code Stop hook that speaks each turn and interrupts the previous turn with kill -- -PGID: every interrupted turn left an mpv behind.

Test plan

  • New tests: SIGTERM during a run stops the player and exits 143 (normal and --live), and an ignored SIGTERM stays ignored. Without the fix, the SIGTERM kills pytest itself.
  • A conftest fixture restores the SIGTERM handler, so main() can't leave it installed in pytest.
  • Full pytest suite passes
  • Manual: tts-ka -s --no-gui with a flatpak mpv, SIGTERM to the group mid-playback → mpv exits (before the fix it kept running)

🤖 Generated with Claude Code

Python's default SIGTERM exits on the spot, with no cleanup. A headless mpv
(--idle, driven over IPC) then plays out the queued chunk and idles forever.
Under flatpak, mpv also sits in its own process group (bwrap moves it), so a
caller's `kill -- -PGID` can't reach it either: TTS_ka is the only thing that
can stop it.

main() now turns SIGTERM into Terminated, a KeyboardInterrupt subclass, so it
takes the existing Ctrl+C path (stop_active_streaming_player) and exits 143.
A SIGTERM that the parent set to SIG_IGN stays ignored.

Found through a Claude Code Stop hook that interrupts the previous turn with
`kill -- -PGID`: each interrupted turn left an mpv running.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@DavidTbilisi
DavidTbilisi merged commit 72bf67f into master Oct 23, 2026
6 checks passed
@DavidTbilisi
DavidTbilisi deleted the fix/sigterm-stops-player branch October 23, 2026 11:59
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