github.com/ltltlt/go-source-code@v0.0.0-20190830023027-95be009773aa/net/write_unix_test.go (about) 1 // Copyright 2017 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build darwin dragonfly freebsd linux netbsd openbsd solaris 6 7 package net 8 9 import ( 10 "bytes" 11 "syscall" 12 "testing" 13 "time" 14 ) 15 16 // Test that a client can't trigger an endless loop of write system 17 // calls on the server by shutting down the write side on the client. 18 // Possibility raised in the discussion of https://golang.org/cl/71973. 19 func TestEndlessWrite(t *testing.T) { 20 t.Parallel() 21 c := make(chan bool) 22 server := func(cs *TCPConn) error { 23 cs.CloseWrite() 24 <-c 25 return nil 26 } 27 client := func(ss *TCPConn) error { 28 // Tell the server to return when we return. 29 defer close(c) 30 31 // Loop writing to the server. The server is not reading 32 // anything, so this will eventually block, and then time out. 33 b := bytes.Repeat([]byte{'a'}, 8192) 34 cagain := 0 35 for { 36 n, err := ss.conn.fd.pfd.WriteOnce(b) 37 if n > 0 { 38 cagain = 0 39 } 40 switch err { 41 case nil: 42 case syscall.EAGAIN: 43 if cagain == 0 { 44 // We've written enough data to 45 // start blocking. Set a deadline 46 // so that we will stop. 47 ss.SetWriteDeadline(time.Now().Add(5 * time.Millisecond)) 48 } 49 cagain++ 50 if cagain > 20 { 51 t.Error("looping on EAGAIN") 52 return nil 53 } 54 if err = ss.conn.fd.pfd.WaitWrite(); err != nil { 55 t.Logf("client WaitWrite: %v", err) 56 return nil 57 } 58 default: 59 // We expect to eventually get an error. 60 t.Logf("client WriteOnce: %v", err) 61 return nil 62 } 63 } 64 } 65 withTCPConnPair(t, client, server) 66 }