return sn >= 0 && signalIgnored(sn)
}
+var (
+ // watchSignalLoopOnce guards calling the conditionally
+ // initialized watchSignalLoop. If watchSignalLoop is non-nil,
+ // it will be run in a goroutine lazily once Notify is invoked.
+ // See Issue 21576.
+ watchSignalLoopOnce sync.Once
+ watchSignalLoop func()
+)
+
// Notify causes package signal to relay incoming signals to c.
// If no signals are provided, all incoming signals will be relayed to c.
// Otherwise, just the provided signals will.
panic("os/signal: Notify using nil channel")
}
+ watchSignalLoopOnce.Do(func() {
+ if watchSignalLoop != nil {
+ go watchSignalLoop()
+ }
+ })
+
handlers.Lock()
defer handlers.Unlock()
// Test that there are just the expected number of goroutines
// running. Specifically, test that the spare M's goroutine
// doesn't show up.
- //
- // On non-Windows platforms there's a signal handling thread
- // started by os/signal.init in addition to the main
- // goroutine.
- if runtime.GOOS != "windows" {
- baseGoroutines = 1
- }
if _, ok := checkNumGoroutine("first", 1+baseGoroutines); !ok {
return
}
--- /dev/null
+// +build !nacl,!js
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+//
+// Ensure that deadlock detection can still
+// run even with an import of "_ os/signal".
+
+package main
+
+import (
+ "bytes"
+ "context"
+ "io/ioutil"
+ "log"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "time"
+)
+
+const prog = `
+package main
+
+import _ "os/signal"
+
+func main() {
+ c := make(chan int)
+ c <- 1
+}
+`
+
+func main() {
+ dir, err := ioutil.TempDir("", "21576")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer os.RemoveAll(dir)
+
+ file := filepath.Join(dir, "main.go")
+ if err := ioutil.WriteFile(file, []byte(prog), 0655); err != nil {
+ log.Fatalf("Write error %v", err)
+ }
+
+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+ defer cancel()
+
+ cmd := exec.CommandContext(ctx, "go", "run", file)
+ output, err := cmd.CombinedOutput()
+ if err == nil {
+ log.Fatalf("Passed, expected an error")
+ }
+
+ want := []byte("fatal error: all goroutines are asleep - deadlock!")
+ if !bytes.Contains(output, want) {
+ log.Fatalf("Unmatched error message %q:\nin\n%s", want, output)
+ }
+}