aboutsummaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-05-24 04:08:19 -0500
committerCraig Jennings <c@cjennings.net>2026-05-24 04:08:19 -0500
commit556f48a2a0518253015496a618eec9e7a7142dcc (patch)
treec24de779d0f780448f1921dcf566a60d32a3e56d /modules
parent39795e850f2027a88021307a37de0381996df8a5 (diff)
downloaddotemacs-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.el23
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.