ssh/agent: fix TestServerResponseTooLarge on Plan 9

First, modify the test to report a better error by waiting for the
Marshal+Write goroutine to finish before returning from the test. If we
return too early, a failure inside that goroutine can generate a panic.

Second, we workaround plan9 not returning the actual number of bytes
written on the connection in case of a hangup (due to closed
connection). I've verified that syscall.Pwrite returns -1 on hangup in
this particular case even when some data did get written.

Fixes golang/go#35888

Change-Id: I7998cff926295f0d577b125c137021a9adc1be5a
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/209298
Reviewed-by: Han-Wen Nienhuys <hanwen@google.com>
Run-TryBot: Han-Wen Nienhuys <hanwen@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/ssh/agent/client_test.go b/ssh/agent/client_test.go
index 71e9db1..de1c783 100644
--- a/ssh/agent/client_test.go
+++ b/ssh/agent/client_test.go
@@ -13,6 +13,7 @@
 	"os"
 	"os/exec"
 	"path/filepath"
+	"runtime"
 	"strconv"
 	"strings"
 	"sync"
@@ -317,6 +318,8 @@
 	if err != nil {
 		t.Fatalf("netPipe: %v", err)
 	}
+	done := make(chan struct{})
+	defer func() { <-done }()
 
 	defer a.Close()
 	defer b.Close()
@@ -327,9 +330,21 @@
 
 	agent := NewClient(a)
 	go func() {
-		n, _ := b.Write(ssh.Marshal(response))
+		defer close(done)
+		n, err := b.Write(ssh.Marshal(response))
 		if n < 4 {
-			t.Fatalf("At least 4 bytes (the response size) should have been successfully written: %d < 4", n)
+			if runtime.GOOS == "plan9" {
+				if e1, ok := err.(*net.OpError); ok {
+					if e2, ok := e1.Err.(*os.PathError); ok {
+						switch e2.Err.Error() {
+						case "Hangup", "i/o on hungup channel":
+							// syscall.Pwrite returns -1 in this case even when some data did get written.
+							return
+						}
+					}
+				}
+			}
+			t.Errorf("At least 4 bytes (the response size) should have been successfully written: %d < 4: %v", n, err)
 		}
 	}()
 	_, err = agent.List()