Let recorder worker close encoder stdin

This commit is contained in:
Brandon McGinty (chatgpt)
2026-08-09 14:50:29 -04:00
committed by Brandon McGinty
parent d07d7342da
commit e309d22137
3 changed files with 26 additions and 4 deletions
+1 -1
View File
@@ -108,7 +108,7 @@ Priority 1: transport, lifecycle, and correctness
context, stop channel, output channel, and WaitGroup. Stop must cancel and context, stop channel, output channel, and WaitGroup. Stop must cancel and
join that session before another begins. join that session before another begins.
13. Recorder Stop races the encoder writer [x] 13. Recorder Stop races the encoder writer
File: recording/recorder.go File: recording/recorder.go
Stop closes stdin while run may be writing. A normal stop can therefore Stop closes stdin while run may be writing. A normal stop can therefore
record a closed-pipe error and be reported as failed. Have run own stdin record a closed-pipe error and be reported as failed. Have run own stdin
+2 -3
View File
@@ -128,10 +128,9 @@ func (r *Recorder) Stop() error {
return nil return nil
} }
r.once.Do(func() { r.once.Do(func() {
// run owns stdin and closes it only after it has stopped writing.
// Closing it here races writePCM and turns a normal stop into EPIPE.
close(r.stop) close(r.stop)
if r.stdin != nil {
r.stdin.Close()
}
}) })
select { select {
case <-r.done: case <-r.done:
+23
View File
@@ -1,12 +1,35 @@
package recording package recording
import ( import (
"io"
"os" "os"
"path/filepath" "path/filepath"
"testing" "testing"
"time" "time"
) )
type trackingWriteCloser struct{ closed bool }
func (w *trackingWriteCloser) Write([]byte) (int, error) { return 0, nil }
func (w *trackingWriteCloser) Close() error { w.closed = true; return nil }
var _ io.WriteCloser = (*trackingWriteCloser)(nil)
// Regression: Stop closed ffmpeg stdin while the worker could still write,
// creating a spurious closed-pipe recording failure.
func TestStopLeavesEncoderClosureToWorker(t *testing.T) {
stdin := &trackingWriteCloser{}
done := make(chan struct{})
close(done)
r := &Recorder{stdin: stdin, stop: make(chan struct{}), done: done}
if err := r.Stop(); err != nil {
t.Fatal(err)
}
if stdin.closed {
t.Fatal("Stop closed stdin instead of the worker")
}
}
func TestNormalizeFormat(t *testing.T) { func TestNormalizeFormat(t *testing.T) {
tests := map[string]string{ tests := map[string]string{
"": "flac", "": "flac",