Black Lives Matter. Support the Equal Justice Initiative.

Source file src/net/write_unix_test.go

Documentation: net

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

View as plain text