When writing a test for #16983, I encountered what looks like perhaps a liveness bug with variadic calls.
If I set "const useVariadic" to true below, the test fails (buf1 is never collected), but if I set it to false, buf1 is collected.
func twoReader(b1, b2 *bytes.Reader) Reader {
return MultiReader(b1, b2)
}
func TestMultiReaderFreesExhaustedReaders(t *testing.T) {
var mr Reader
closed := make(chan struct{})
{
buf1 := bytes.NewReader([]byte("foo"))
buf2 := bytes.NewReader([]byte("bar"))
const useVariadic = true // set to true to see the bug; false to see the workaround
if useVariadic {
mr = MultiReader(buf1, buf2)
} else {
mr = twoReader(buf1, buf2)
}
runtime.SetFinalizer(buf1, func(*bytes.Reader) {
close(closed)
})
}
buf := make([]byte, 4)
if n, err := ReadFull(mr, buf); err != nil || string(buf) != "foob" {
t.Fatalf(`ReadFull = %d (%q), %v; want 3, "foo", nil`, n, buf[:n], err)
}
println("runtime.GC...")
runtime.GC()
println("waiting...")
select {
case <-closed:
case <-time.After(5 * time.Second):
t.Fatal("timeout waiting for collection of buf1")
}
if n, err := ReadFull(mr, buf[:2]); err != nil || string(buf[:2]) != "ar" {
t.Fatalf(`ReadFull = %d (%q), %v; want 2, "ar", nil`, n, buf[:n], err)
}
}
/cc @randall77 @josharian @minux @cherrymui
When writing a test for #16983, I encountered what looks like perhaps a liveness bug with variadic calls.
If I set "const useVariadic" to true below, the test fails (buf1 is never collected), but if I set it to false, buf1 is collected.
/cc @randall77 @josharian @minux @cherrymui