Source file src/net/write_unix_test.go

     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  
     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  }
    67  

View as plain text