Black Lives Matter. Support the Equal Justice Initiative.

Source file src/runtime/semasleep_test.go

Documentation: runtime

     1  // Copyright 2018 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 !plan9 && !windows && !js
     6  // +build !plan9,!windows,!js
     7  
     8  package runtime_test
     9  
    10  import (
    11  	"os/exec"
    12  	"syscall"
    13  	"testing"
    14  	"time"
    15  )
    16  
    17  // Issue #27250. Spurious wakeups to pthread_cond_timedwait_relative_np
    18  // shouldn't cause semasleep to retry with the same timeout which would
    19  // cause indefinite spinning.
    20  func TestSpuriousWakeupsNeverHangSemasleep(t *testing.T) {
    21  	if *flagQuick {
    22  		t.Skip("-quick")
    23  	}
    24  
    25  	exe, err := buildTestProg(t, "testprog")
    26  	if err != nil {
    27  		t.Fatal(err)
    28  	}
    29  
    30  	start := time.Now()
    31  	cmd := exec.Command(exe, "After1")
    32  	if err := cmd.Start(); err != nil {
    33  		t.Fatalf("Failed to start command: %v", err)
    34  	}
    35  	doneCh := make(chan error, 1)
    36  	go func() {
    37  		doneCh <- cmd.Wait()
    38  	}()
    39  
    40  	// With the repro running, we can continuously send to it
    41  	// a non-terminal signal such as SIGIO, to spuriously
    42  	// wakeup pthread_cond_timedwait_relative_np.
    43  	unfixedTimer := time.NewTimer(2 * time.Second)
    44  	for {
    45  		select {
    46  		case <-time.After(200 * time.Millisecond):
    47  			// Send the pesky signal that toggles spinning
    48  			// indefinitely if #27520 is not fixed.
    49  			cmd.Process.Signal(syscall.SIGIO)
    50  
    51  		case <-unfixedTimer.C:
    52  			t.Error("Program failed to return on time and has to be killed, issue #27520 still exists")
    53  			cmd.Process.Signal(syscall.SIGKILL)
    54  			return
    55  
    56  		case err := <-doneCh:
    57  			if err != nil {
    58  				t.Fatalf("The program returned but unfortunately with an error: %v", err)
    59  			}
    60  			if time.Since(start) < 100*time.Millisecond {
    61  				t.Fatalf("The program stopped too quickly.")
    62  			}
    63  			return
    64  		}
    65  	}
    66  }
    67  

View as plain text