diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-24 04:08:19 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-24 04:08:19 -0500 |
| commit | 556f48a2a0518253015496a618eec9e7a7142dcc (patch) | |
| tree | c24de779d0f780448f1921dcf566a60d32a3e56d /modules | |
| parent | 39795e850f2027a88021307a37de0381996df8a5 (diff) | |
| download | dotemacs-556f48a2a0518253015496a618eec9e7a7142dcc.tar.gz dotemacs-556f48a2a0518253015496a618eec9e7a7142dcc.zip | |
fix(recording): scope wf-recorder stop signal to our own process
Stopping a Wayland recording ran pkill -INT wf-recorder, which signals every wf-recorder on the system — including an unrelated screen capture the user started outside Emacs. The stop path now scopes the producer-first interrupt to the wf-recorder child of our own recording shell via pkill -P <shell-pid>, in the new cj/recording--interrupt-child-wf-recorder helper.
The producer-first ordering is unchanged: wf-recorder still gets SIGINT before the process-group signal so ffmpeg sees a clean EOF on pipe:0 and finalizes the MKV. The orphan-cleanup at recording start stays a broad by-name kill on purpose — those leftover recorders come from crashed sessions whose shells are already dead, so there is no live PID to scope to. Tests cover the scoped call, the nil-PID no-op, and that the bare system-wide form is never used.
Diffstat (limited to 'modules')
| -rw-r--r-- | modules/video-audio-recording.el | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/modules/video-audio-recording.el b/modules/video-audio-recording.el index 6c00a2df..b3c4d47b 100644 --- a/modules/video-audio-recording.el +++ b/modules/video-audio-recording.el @@ -877,7 +877,10 @@ Uses wf-recorder on Wayland, x11grab on X11." (unless cj/video-recording-ffmpeg-process ;; On Wayland, kill any orphan wf-recorder processes left over from ;; previous crashes. Without this, old wf-recorders hold the compositor - ;; capture and new ones fail silently. + ;; capture and new ones fail silently. This one stays a broad by-name + ;; kill on purpose: the orphans' launching shells are already dead, so + ;; there is no live PID to scope to. The stop path, by contrast, scopes + ;; to our own shell's child (see cj/recording--interrupt-child-wf-recorder). (when (cj/recording--wayland-p) (call-process "pkill" nil nil nil "-INT" "wf-recorder") (sit-for 0.1)) @@ -958,6 +961,16 @@ The filter graph mixes two PulseAudio inputs: ;; X11 shutdown: simpler — ffmpeg is the only process, so we just ;; send SIGINT to the process group and wait. +(defun cj/recording--interrupt-child-wf-recorder (shell-pid) + "Send SIGINT to the wf-recorder child of SHELL-PID, if any. +Scopes the producer-first stop to the wf-recorder this module launched +\(a child of our recording shell) via `pkill -P', instead of killing +every wf-recorder on the system by name. Does nothing when SHELL-PID +is nil (the shell already exited, so there is no child to signal)." + (when shell-pid + (call-process "pkill" nil nil nil + "-INT" "-P" (number-to-string shell-pid) "wf-recorder"))) + (defun cj/video-recording-stop () "Stop the video recording, waiting for ffmpeg to finalize the file. On Wayland, kills wf-recorder first so ffmpeg gets a clean EOF on its @@ -973,7 +986,7 @@ for ffmpeg to write container metadata before giving up." ;; Without this, simultaneous SIGINT to both causes ffmpeg to abort ;; without creating a file. (when (cj/recording--wayland-p) - (call-process "pkill" nil nil nil "-INT" "wf-recorder") + (cj/recording--interrupt-child-wf-recorder (process-id proc)) (sit-for 0.3)) ; Brief pause for pipe to close ;; Now send SIGINT to the process group. On Wayland, this reaches ;; ffmpeg (which is already shutting down from the pipe EOF) and @@ -986,9 +999,11 @@ for ffmpeg to write container metadata before giving up." (let ((exited (cj/recording--wait-for-exit proc 5))) (unless exited (message "Warning: recording process did not exit within 5 seconds"))) - ;; Safety net: kill any straggler wf-recorder on Wayland. + ;; Safety net: signal our own straggler wf-recorder on Wayland. + ;; If the shell already exited, process-id returns nil and this is + ;; a no-op (the child is already gone with it). (when (cj/recording--wayland-p) - (call-process "pkill" nil nil nil "-INT" "wf-recorder")) + (cj/recording--interrupt-child-wf-recorder (process-id proc))) ;; The sentinel handles clearing cj/video-recording-ffmpeg-process ;; and updating the modeline. If the process already exited during ;; our wait, the sentinel has already fired. If not, force cleanup. |
