Let recorder worker close encoder stdin

This commit is contained in:
Brandon McGinty (chatgpt) authored and Brandon McGinty committed 2026-08-09 14:50:29 -04:00
1 parent d07d7342da
commit e309d22137
3 files changed
+26 -4

No files matched your search

+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",