test(runtime): keep the Xvfb displayfd read end open until cleanup
Closing it right after the first read made Xvfb's later displayfd write fail on a server reset ('Cannot write display number to fd 3'), killing the server under load. Reproduced on ubuntu:26.04 Xvfb 21.1.22 with CPU contention: 8/200 failures before, 0/200 after.2 files · +6 -2
M conn_xserver_test.go +3 -1
| @@ -31,7 +31,9 @@ func startXvfb(t *testing.T, authFile string) string { | |||
| 31 | 31 | if err != nil { | |
| 32 | 32 | t.Fatal(err) | |
| 33 | 33 | } | |
| 34 | - | defer r.Close() | |
| 34 | + | // Xvfb may write to -displayfd again (e.g. after a server reset); closing | |
| 35 | + | // the read end early makes that write fail and kills the server. | |
| 36 | + | t.Cleanup(func() { _ = r.Close() }) | |
| 35 | 37 | cmd := exec.Command("Xvfb", "-displayfd", "3", "-screen", "0", "800x600x24", "-nolisten", "tcp", "-auth", authFile) | |
| 36 | 38 | cmd.ExtraFiles = []*os.File{w} | |
| 37 | 39 | var log bytes.Buffer | |
| @@ -31,7 +31,9 @@ func startXvfb(t *testing.T, authFile string) string { | |||||
| 31 | if err != nil { | 31 | if err != nil { | ||
| 32 | t.Fatal(err) | 32 | t.Fatal(err) | ||
| 33 | } | 33 | } | ||
| 34 | - | defer r.Close() | 34 | + | // Xvfb may write to -displayfd again (e.g. after a server reset); closing |
| 35 | + | // the read end early makes that write fail and kills the server. | |||
| 36 | + | t.Cleanup(func() { _ = r.Close() }) | |||
| 35 | cmd := exec.Command("Xvfb", "-displayfd", "3", "-screen", "0", "800x600x24", "-nolisten", "tcp", "-auth", authFile) | 37 | cmd := exec.Command("Xvfb", "-displayfd", "3", "-screen", "0", "800x600x24", "-nolisten", "tcp", "-auth", authFile) | ||
| 36 | cmd.ExtraFiles = []*os.File{w} | 38 | cmd.ExtraFiles = []*os.File{w} | ||
| 37 | var log bytes.Buffer | 39 | var log bytes.Buffer | ||
M internal/xtest/capture_test.go +3 -1
| @@ -101,7 +101,9 @@ func TestCaptureRequests(t *testing.T) { | |||
| 101 | 101 | if err != nil { | |
| 102 | 102 | t.Fatal(err) | |
| 103 | 103 | } | |
| 104 | - | defer r.Close() | |
| 104 | + | // Xvfb writes to displayfd again after a server reset; keep the read end | |
| 105 | + | // open until the test ends so that write cannot kill the server. | |
| 106 | + | t.Cleanup(func() { _ = r.Close() }) | |
| 105 | 107 | cmd := exec.Command("Xvfb", xvfbArgs()...) | |
| 106 | 108 | cmd.ExtraFiles = []*os.File{w} | |
| 107 | 109 | var log bytes.Buffer | |
| @@ -101,7 +101,9 @@ func TestCaptureRequests(t *testing.T) { | |||||
| 101 | if err != nil { | 101 | if err != nil { | ||
| 102 | t.Fatal(err) | 102 | t.Fatal(err) | ||
| 103 | } | 103 | } | ||
| 104 | - | defer r.Close() | 104 | + | // Xvfb writes to displayfd again after a server reset; keep the read end |
| 105 | + | // open until the test ends so that write cannot kill the server. | |||
| 106 | + | t.Cleanup(func() { _ = r.Close() }) | |||
| 105 | cmd := exec.Command("Xvfb", xvfbArgs()...) | 107 | cmd := exec.Command("Xvfb", xvfbArgs()...) | ||
| 106 | cmd.ExtraFiles = []*os.File{w} | 108 | cmd.ExtraFiles = []*os.File{w} | ||
| 107 | var log bytes.Buffer | 109 | var log bytes.Buffer | ||