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