1 // Copyright 2009 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.
27 // settleTime is an upper bound on how long we expect signals to take to be
28 // delivered. Lower values make the test faster, but also flakier — especially
29 // on heavily loaded systems.
31 // The current value is set based on flakes observed in the Go builders.
32 var settleTime = 100 * time.Millisecond
34 // fatalWaitingTime is an absurdly long time to wait for signals to be
35 // delivered but, using it, we (hopefully) eliminate test flakes on the
36 // build servers. See #46736 for discussion.
37 var fatalWaitingTime = 30 * time.Second
40 if testenv.Builder() == "solaris-amd64-oraclerel" {
41 // The solaris-amd64-oraclerel builder has been observed to time out in
42 // TestNohup even with a 250ms settle time.
44 // Use a much longer settle time on that builder to try to suss out whether
45 // the test is flaky due to builder slowness (which may mean we need a
46 // longer GO_TEST_TIMEOUT_SCALE) or due to a dropped signal (which may
47 // instead need a test-skip and upstream bug filed against the Solaris
50 // See https://golang.org/issue/33174.
51 settleTime = 5 * time.Second
52 } else if runtime.GOOS == "linux" && strings.HasPrefix(runtime.GOARCH, "ppc64") {
53 // Older linux kernels seem to have some hiccups delivering the signal
54 // in a timely manner on ppc64 and ppc64le. When running on a
55 // ppc64le/ubuntu 16.04/linux 4.4 host the time can vary quite
56 // substantially even on an idle system. 5 seconds is twice any value
57 // observed when running 10000 tests on such a system.
58 settleTime = 5 * time.Second
59 } else if s := os.Getenv("GO_TEST_TIMEOUT_SCALE"); s != "" {
60 if scale, err := strconv.Atoi(s); err == nil {
61 settleTime *= time.Duration(scale)
66 func waitSig(t *testing.T, c <-chan os.Signal, sig os.Signal) {
68 waitSig1(t, c, sig, false)
70 func waitSigAll(t *testing.T, c <-chan os.Signal, sig os.Signal) {
72 waitSig1(t, c, sig, true)
75 func waitSig1(t *testing.T, c <-chan os.Signal, sig os.Signal, all bool) {
78 // Sleep multiple times to give the kernel more tries to
79 // deliver the signal.
81 timer := time.NewTimer(settleTime / 10)
83 // If the caller notified for all signals on c, filter out SIGURG,
84 // which is used for runtime preemption and can come at unpredictable times.
85 // General user code should filter out all unexpected signals instead of just
86 // SIGURG, but since os/signal is tightly coupled to the runtime it seems
87 // appropriate to be stricter here.
88 for time.Since(start) < fatalWaitingTime {
94 if !all || s != syscall.SIGURG {
95 t.Fatalf("signal was %v, want %v", s, sig)
98 timer.Reset(settleTime / 10)
101 t.Fatalf("timeout after %v waiting for %v", fatalWaitingTime, sig)
104 // quiesce waits until we can be reasonably confident that all pending signals
105 // have been delivered by the OS.
107 // The kernel will deliver a signal as a thread returns
108 // from a syscall. If the only active thread is sleeping,
109 // and the system is busy, the kernel may not get around
110 // to waking up a thread to catch the signal.
111 // We try splitting up the sleep to give the kernel
112 // many chances to deliver the signal.
114 for time.Since(start) < settleTime {
115 time.Sleep(settleTime / 10)
119 // Test that basic signal handling works.
120 func TestSignal(t *testing.T) {
122 c := make(chan os.Signal, 1)
123 Notify(c, syscall.SIGHUP)
126 // Send this process a SIGHUP
128 syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
129 waitSig(t, c, syscall.SIGHUP)
131 // Ask for everything we can get. The buffer size has to be
132 // more than 1, since the runtime might send SIGURG signals.
133 // Using 10 is arbitrary.
134 c1 := make(chan os.Signal, 10)
136 // Stop relaying the SIGURG signals. See #49724
137 Reset(syscall.SIGURG)
140 // Send this process a SIGWINCH
141 t.Logf("sigwinch...")
142 syscall.Kill(syscall.Getpid(), syscall.SIGWINCH)
143 waitSigAll(t, c1, syscall.SIGWINCH)
145 // Send two more SIGHUPs, to make sure that
146 // they get delivered on c1 and that not reading
147 // from c does not block everything.
149 syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
150 waitSigAll(t, c1, syscall.SIGHUP)
152 syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
153 waitSigAll(t, c1, syscall.SIGHUP)
155 // The first SIGHUP should be waiting for us on c.
156 waitSig(t, c, syscall.SIGHUP)
159 func TestStress(t *testing.T) {
160 dur := 3 * time.Second
162 dur = 100 * time.Millisecond
164 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
166 sig := make(chan os.Signal, 1)
167 Notify(sig, syscall.SIGUSR1)
170 stop := time.After(dur)
174 // Allow enough time for all signals to be delivered before we stop
175 // listening for them.
178 // According to its documentation, “[w]hen Stop returns, it in
179 // guaranteed that c will receive no more signals.” So we can safely
180 // close sig here: if there is a send-after-close race here, that is a
181 // bug in Stop and we would like to detect it.
186 syscall.Kill(syscall.Getpid(), syscall.SIGUSR1)
193 // Receive signals until the sender closes sig.
197 func testCancel(t *testing.T, ignore bool) {
198 // Ask to be notified on c1 when a SIGWINCH is received.
199 c1 := make(chan os.Signal, 1)
200 Notify(c1, syscall.SIGWINCH)
203 // Ask to be notified on c2 when a SIGHUP is received.
204 c2 := make(chan os.Signal, 1)
205 Notify(c2, syscall.SIGHUP)
208 // Send this process a SIGWINCH and wait for notification on c1.
209 syscall.Kill(syscall.Getpid(), syscall.SIGWINCH)
210 waitSig(t, c1, syscall.SIGWINCH)
212 // Send this process a SIGHUP and wait for notification on c2.
213 syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
214 waitSig(t, c2, syscall.SIGHUP)
216 // Ignore, or reset the signal handlers for, SIGWINCH and SIGHUP.
217 // Either way, this should undo both calls to Notify above.
219 Ignore(syscall.SIGWINCH, syscall.SIGHUP)
220 // Don't bother deferring a call to Reset: it is documented to undo Notify,
221 // but its documentation says nothing about Ignore, and (as of the time of
222 // writing) it empirically does not undo an Ignore.
224 Reset(syscall.SIGWINCH, syscall.SIGHUP)
227 // Send this process a SIGWINCH. It should be ignored.
228 syscall.Kill(syscall.Getpid(), syscall.SIGWINCH)
230 // If ignoring, Send this process a SIGHUP. It should be ignored.
232 syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
239 t.Errorf("unexpected signal %v", s)
241 // nothing to read - good
246 t.Errorf("unexpected signal %v", s)
248 // nothing to read - good
251 // One or both of the signals may have been blocked for this process
252 // by the calling process.
253 // Discard any queued signals now to avoid interfering with other tests.
254 Notify(c1, syscall.SIGWINCH)
255 Notify(c2, syscall.SIGHUP)
259 // Test that Reset cancels registration for listed signals on all channels.
260 func TestReset(t *testing.T) {
264 // Test that Ignore cancels registration for listed signals on all channels.
265 func TestIgnore(t *testing.T) {
269 // Test that Ignored correctly detects changes to the ignored status of a signal.
270 func TestIgnored(t *testing.T) {
271 // Ask to be notified on SIGWINCH.
272 c := make(chan os.Signal, 1)
273 Notify(c, syscall.SIGWINCH)
275 // If we're being notified, then the signal should not be ignored.
276 if Ignored(syscall.SIGWINCH) {
277 t.Errorf("expected SIGWINCH to not be ignored.")
280 Ignore(syscall.SIGWINCH)
282 // We're no longer paying attention to this signal.
283 if !Ignored(syscall.SIGWINCH) {
284 t.Errorf("expected SIGWINCH to be ignored when explicitly ignoring it.")
290 var checkSighupIgnored = flag.Bool("check_sighup_ignored", false, "if true, TestDetectNohup will fail if SIGHUP is not ignored.")
292 // Test that Ignored(SIGHUP) correctly detects whether it is being run under nohup.
293 func TestDetectNohup(t *testing.T) {
294 if *checkSighupIgnored {
295 if !Ignored(syscall.SIGHUP) {
296 t.Fatal("SIGHUP is not ignored.")
298 t.Log("SIGHUP is ignored.")
302 // Ugly: ask for SIGHUP so that child will not have no-hup set
303 // even if test is running under nohup environment.
304 // We have no intention of reading from c.
305 c := make(chan os.Signal, 1)
306 Notify(c, syscall.SIGHUP)
307 if out, err := testenv.Command(t, os.Args[0], "-test.run=^TestDetectNohup$", "-check_sighup_ignored").CombinedOutput(); err == nil {
308 t.Errorf("ran test with -check_sighup_ignored and it succeeded: expected failure.\nOutput:\n%s", out)
312 // Again, this time with nohup, assuming we can find it.
313 _, err := os.Stat("/usr/bin/nohup")
315 t.Skip("cannot find nohup; skipping second half of test")
317 Ignore(syscall.SIGHUP)
318 os.Remove("nohup.out")
319 out, err := testenv.Command(t, "/usr/bin/nohup", os.Args[0], "-test.run=^TestDetectNohup$", "-check_sighup_ignored").CombinedOutput()
321 data, _ := os.ReadFile("nohup.out")
322 os.Remove("nohup.out")
324 // nohup doesn't work on new LUCI darwin builders due to the
325 // type of launchd service the test run under. See
326 // https://go.dev/issue/63875.
327 if runtime.GOOS == "darwin" && strings.Contains(string(out), "nohup: can't detach from console: Inappropriate ioctl for device") {
328 t.Skip("Skipping nohup test due to darwin builder limitation. See https://go.dev/issue/63875.")
331 t.Errorf("ran test with -check_sighup_ignored under nohup and it failed: expected success.\nError: %v\nOutput:\n%s%s", err, out, data)
337 sendUncaughtSighup = flag.Int("send_uncaught_sighup", 0, "send uncaught SIGHUP during TestStop")
338 dieFromSighup = flag.Bool("die_from_sighup", false, "wait to die from uncaught SIGHUP")
341 // Test that Stop cancels the channel's registrations.
342 func TestStop(t *testing.T) {
343 sigs := []syscall.Signal{
349 for _, sig := range sigs {
351 t.Run(fmt.Sprint(sig), func(t *testing.T) {
352 // When calling Notify with a specific signal,
353 // independent signals should not interfere with each other,
354 // and we end up needing to wait for signals to quiesce a lot.
355 // Test the three different signals concurrently.
358 // If the signal is not ignored, send the signal before registering a
359 // channel to verify the behavior of the default Go handler.
360 // If it's SIGWINCH or SIGUSR1 we should not see it.
361 // If it's SIGHUP, maybe we'll die. Let the flag tell us what to do.
362 mayHaveBlockedSignal := false
363 if !Ignored(sig) && (sig != syscall.SIGHUP || *sendUncaughtSighup == 1) {
364 syscall.Kill(syscall.Getpid(), sig)
367 // We don't know whether sig is blocked for this process; see
368 // https://golang.org/issue/38165. Assume that it could be.
369 mayHaveBlockedSignal = true
373 c := make(chan os.Signal, 1)
376 // Send this process the signal again.
377 syscall.Kill(syscall.Getpid(), sig)
380 if mayHaveBlockedSignal {
381 // We may have received a queued initial signal in addition to the one
382 // that we sent after Notify. If so, waitSig may have observed that
383 // initial signal instead of the second one, and we may need to wait for
384 // the second signal to clear. Do that now.
392 // Stop watching for the signal and send it again.
393 // If it's SIGHUP, maybe we'll die. Let the flag tell us what to do.
395 if sig != syscall.SIGHUP || *sendUncaughtSighup == 2 {
396 syscall.Kill(syscall.Getpid(), sig)
401 t.Errorf("unexpected signal %v", s)
403 // nothing to read - good
406 // If we're going to receive a signal, it has almost certainly been
407 // received by now. However, it may have been blocked for this process —
408 // we don't know. Explicitly unblock it and wait for it to clear now.
417 // Test that when run under nohup, an uncaught SIGHUP does not kill the program.
418 func TestNohup(t *testing.T) {
419 // When run without nohup, the test should crash on an uncaught SIGHUP.
420 // When run under nohup, the test should ignore uncaught SIGHUPs,
421 // because the runtime is not supposed to be listening for them.
422 // Either way, TestStop should still be able to catch them when it wants them
423 // and then when it stops wanting them, the original behavior should resume.
425 // send_uncaught_sighup=1 sends the SIGHUP before starting to listen for SIGHUPs.
426 // send_uncaught_sighup=2 sends the SIGHUP after no longer listening for SIGHUPs.
428 // Both should fail without nohup and succeed with nohup.
430 t.Run("uncaught", func(t *testing.T) {
431 // Ugly: ask for SIGHUP so that child will not have no-hup set
432 // even if test is running under nohup environment.
433 // We have no intention of reading from c.
434 c := make(chan os.Signal, 1)
435 Notify(c, syscall.SIGHUP)
436 t.Cleanup(func() { Stop(c) })
438 var subTimeout time.Duration
439 if deadline, ok := t.Deadline(); ok {
440 subTimeout = time.Until(deadline)
441 subTimeout -= subTimeout / 10 // Leave 10% headroom for propagating output.
443 for i := 1; i <= 2; i++ {
445 t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
450 "-test.run=^TestStop$",
451 "-send_uncaught_sighup=" + strconv.Itoa(i),
455 args = append(args, fmt.Sprintf("-test.timeout=%v", subTimeout))
457 out, err := testenv.Command(t, os.Args[0], args...).CombinedOutput()
460 t.Errorf("ran test with -send_uncaught_sighup=%d and it succeeded: expected failure.\nOutput:\n%s", i, out)
462 t.Logf("test with -send_uncaught_sighup=%d failed as expected.\nError: %v\nOutput:\n%s", i, err, out)
468 t.Run("nohup", func(t *testing.T) {
469 // Skip the nohup test below when running in tmux on darwin, since nohup
470 // doesn't work correctly there. See issue #5135.
471 if runtime.GOOS == "darwin" && os.Getenv("TMUX") != "" {
472 t.Skip("Skipping nohup test due to running in tmux on darwin")
475 // Again, this time with nohup, assuming we can find it.
476 _, err := exec.LookPath("nohup")
478 t.Skip("cannot find nohup; skipping second half of test")
481 var subTimeout time.Duration
482 if deadline, ok := t.Deadline(); ok {
483 subTimeout = time.Until(deadline)
484 subTimeout -= subTimeout / 10 // Leave 10% headroom for propagating output.
486 for i := 1; i <= 2; i++ {
488 t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
491 // POSIX specifies that nohup writes to a file named nohup.out if standard
492 // output is a terminal. However, for an exec.Cmd, standard output is
493 // not a terminal — so we don't need to read or remove that file (and,
494 // indeed, cannot even create it if the current user is unable to write to
495 // GOROOT/src, such as when GOROOT is installed and owned by root).
500 "-test.run=^TestStop$",
501 "-send_uncaught_sighup=" + strconv.Itoa(i),
504 args = append(args, fmt.Sprintf("-test.timeout=%v", subTimeout))
506 out, err := testenv.Command(t, "nohup", args...).CombinedOutput()
509 // nohup doesn't work on new LUCI darwin builders due to the
510 // type of launchd service the test run under. See
511 // https://go.dev/issue/63875.
512 if runtime.GOOS == "darwin" && strings.Contains(string(out), "nohup: can't detach from console: Inappropriate ioctl for device") {
513 // TODO(go.dev/issue/63799): A false-positive in vet reports a
514 // t.Skip here as invalid. Switch back to t.Skip once fixed.
515 t.Logf("Skipping nohup test due to darwin builder limitation. See https://go.dev/issue/63875.")
519 t.Errorf("ran test with -send_uncaught_sighup=%d under nohup and it failed: expected success.\nError: %v\nOutput:\n%s", i, err, out)
521 t.Logf("ran test with -send_uncaught_sighup=%d under nohup.\nOutput:\n%s", i, out)
528 // Test that SIGCONT works (issue 8953).
529 func TestSIGCONT(t *testing.T) {
530 c := make(chan os.Signal, 1)
531 Notify(c, syscall.SIGCONT)
533 syscall.Kill(syscall.Getpid(), syscall.SIGCONT)
534 waitSig(t, c, syscall.SIGCONT)
537 // Test race between stopping and receiving a signal (issue 14571).
538 func TestAtomicStop(t *testing.T) {
539 if os.Getenv("GO_TEST_ATOMIC_STOP") != "" {
540 atomicStopTestProgram(t)
541 t.Fatal("atomicStopTestProgram returned")
544 testenv.MustHaveExec(t)
546 // Call Notify for SIGINT before starting the child process.
547 // That ensures that SIGINT is not ignored for the child.
548 // This is necessary because if SIGINT is ignored when a
549 // Go program starts, then it remains ignored, and closing
550 // the last notification channel for SIGINT will switch it
551 // back to being ignored. In that case the assumption of
552 // atomicStopTestProgram, that it will either die from SIGINT
553 // or have it be reported, breaks down, as there is a third
554 // option: SIGINT might be ignored.
555 cs := make(chan os.Signal, 1)
556 Notify(cs, syscall.SIGINT)
560 for i := 0; i < execs; i++ {
562 if deadline, ok := t.Deadline(); ok {
563 timeout = time.Until(deadline).String()
565 cmd := testenv.Command(t, os.Args[0], "-test.run=^TestAtomicStop$", "-test.timeout="+timeout)
566 cmd.Env = append(os.Environ(), "GO_TEST_ATOMIC_STOP=1")
567 out, err := cmd.CombinedOutput()
570 t.Logf("iteration %d: output %s", i, out)
573 t.Logf("iteration %d: exit status %q: output: %s", i, err, out)
576 lost := bytes.Contains(out, []byte("lost signal"))
578 t.Errorf("iteration %d: lost signal", i)
581 // The program should either die due to SIGINT,
582 // or exit with success without printing "lost signal".
584 if len(out) > 0 && !lost {
585 t.Errorf("iteration %d: unexpected output", i)
588 if ee, ok := err.(*exec.ExitError); !ok {
589 t.Errorf("iteration %d: error (%v) has type %T; expected exec.ExitError", i, err, err)
590 } else if ws, ok := ee.Sys().(syscall.WaitStatus); !ok {
591 t.Errorf("iteration %d: error.Sys (%v) has type %T; expected syscall.WaitStatus", i, ee.Sys(), ee.Sys())
592 } else if !ws.Signaled() || ws.Signal() != syscall.SIGINT {
593 t.Errorf("iteration %d: got exit status %v; expected SIGINT", i, ee)
599 // atomicStopTestProgram is run in a subprocess by TestAtomicStop.
600 // It tries to trigger a signal delivery race. This function should
601 // either catch a signal or die from it.
602 func atomicStopTestProgram(t *testing.T) {
603 // This test won't work if SIGINT is ignored here.
604 if Ignored(syscall.SIGINT) {
605 fmt.Println("SIGINT is ignored")
611 timeout := 2 * time.Second
612 if deadline, ok := t.Deadline(); ok {
613 // Give each try an equal slice of the deadline, with one slice to spare for
615 timeout = time.Until(deadline) / (tries + 1)
618 pid := syscall.Getpid()
620 for i := 0; i < tries; i++ {
621 cs := make(chan os.Signal, 1)
622 Notify(cs, syscall.SIGINT)
624 var wg sync.WaitGroup
631 syscall.Kill(pid, syscall.SIGINT)
633 // At this point we should either die from SIGINT or
634 // get a notification on cs. If neither happens, we
635 // dropped the signal. It is given 2 seconds to
636 // deliver, as needed for gccgo on some loaded test systems.
640 case <-time.After(timeout):
642 fmt.Print("lost signal on tries:")
657 func TestTime(t *testing.T) {
658 // Test that signal works fine when we are in a call to get time,
659 // which on some platforms is using VDSO. See issue #34391.
660 dur := 3 * time.Second
662 dur = 100 * time.Millisecond
664 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
666 sig := make(chan os.Signal, 1)
667 Notify(sig, syscall.SIGUSR1)
669 stop := make(chan struct{})
674 // Allow enough time for all signals to be delivered before we stop
675 // listening for them.
678 // According to its documentation, “[w]hen Stop returns, it in
679 // guaranteed that c will receive no more signals.” So we can safely
680 // close sig here: if there is a send-after-close race, that is a bug in
681 // Stop and we would like to detect it.
686 syscall.Kill(syscall.Getpid(), syscall.SIGUSR1)
692 done := make(chan struct{})
695 // Receive signals until the sender closes sig.
701 for t1 := t0; t1.Sub(t0) < dur; t1 = time.Now() {
702 } // hammering on getting time
709 checkNotifyContext = flag.Bool("check_notify_ctx", false, "if true, TestNotifyContext will fail if SIGINT is not received.")
710 ctxNotifyTimes = flag.Int("ctx_notify_times", 1, "number of times a SIGINT signal should be received")
713 func TestNotifyContextNotifications(t *testing.T) {
714 if *checkNotifyContext {
715 ctx, _ := NotifyContext(context.Background(), syscall.SIGINT)
716 // We want to make sure not to be calling Stop() internally on NotifyContext() when processing a received signal.
717 // Being able to wait for a number of received system signals allows us to do so.
718 var wg sync.WaitGroup
721 for i := 0; i < n; i++ {
723 syscall.Kill(syscall.Getpid(), syscall.SIGINT)
729 fmt.Println("received SIGINT")
730 // Sleep to give time to simultaneous signals to reach the process.
731 // These signals must be ignored given stop() is not called on this code.
732 // We want to guarantee a SIGINT doesn't cause a premature termination of the program.
733 time.Sleep(settleTime)
738 testCases := []struct {
740 n int // number of times a SIGINT should be notified.
745 for _, tc := range testCases {
747 t.Run(tc.name, func(t *testing.T) {
750 var subTimeout time.Duration
751 if deadline, ok := t.Deadline(); ok {
752 timeout := time.Until(deadline)
753 if timeout < 2*settleTime {
754 t.Fatalf("starting test with less than %v remaining", 2*settleTime)
756 subTimeout = timeout - (timeout / 10) // Leave 10% headroom for cleaning up subprocess.
761 "-test.run=^TestNotifyContextNotifications$",
763 fmt.Sprintf("-ctx_notify_times=%d", tc.n),
766 args = append(args, fmt.Sprintf("-test.timeout=%v", subTimeout))
768 out, err := testenv.Command(t, os.Args[0], args...).CombinedOutput()
770 t.Errorf("ran test with -check_notify_ctx_notification and it failed with %v.\nOutput:\n%s", err, out)
772 if want := []byte("received SIGINT\n"); !bytes.Contains(out, want) {
773 t.Errorf("got %q, wanted %q", out, want)
779 func TestNotifyContextStop(t *testing.T) {
780 Ignore(syscall.SIGHUP)
781 if !Ignored(syscall.SIGHUP) {
782 t.Errorf("expected SIGHUP to be ignored when explicitly ignoring it.")
785 parent, cancelParent := context.WithCancel(context.Background())
787 c, stop := NotifyContext(parent, syscall.SIGHUP)
790 // If we're being notified, then the signal should not be ignored.
791 if Ignored(syscall.SIGHUP) {
792 t.Errorf("expected SIGHUP to not be ignored.")
795 if want, got := "signal.NotifyContext(context.Background.WithCancel, [hangup])", fmt.Sprint(c); want != got {
796 t.Errorf("c.String() = %q, wanted %q", got, want)
802 if got := c.Err(); got != context.Canceled {
803 t.Errorf("c.Err() = %q, want %q", got, context.Canceled)
805 case <-time.After(time.Second):
806 t.Errorf("timed out waiting for context to be done after calling stop")
810 func TestNotifyContextCancelParent(t *testing.T) {
811 parent, cancelParent := context.WithCancel(context.Background())
813 c, stop := NotifyContext(parent, syscall.SIGINT)
816 if want, got := "signal.NotifyContext(context.Background.WithCancel, [interrupt])", fmt.Sprint(c); want != got {
817 t.Errorf("c.String() = %q, want %q", got, want)
823 if got := c.Err(); got != context.Canceled {
824 t.Errorf("c.Err() = %q, want %q", got, context.Canceled)
826 case <-time.After(time.Second):
827 t.Errorf("timed out waiting for parent context to be canceled")
831 func TestNotifyContextPrematureCancelParent(t *testing.T) {
832 parent, cancelParent := context.WithCancel(context.Background())
835 cancelParent() // Prematurely cancel context before calling NotifyContext.
836 c, stop := NotifyContext(parent, syscall.SIGINT)
839 if want, got := "signal.NotifyContext(context.Background.WithCancel, [interrupt])", fmt.Sprint(c); want != got {
840 t.Errorf("c.String() = %q, want %q", got, want)
845 if got := c.Err(); got != context.Canceled {
846 t.Errorf("c.Err() = %q, want %q", got, context.Canceled)
848 case <-time.After(time.Second):
849 t.Errorf("timed out waiting for parent context to be canceled")
853 func TestNotifyContextSimultaneousStop(t *testing.T) {
854 c, stop := NotifyContext(context.Background(), syscall.SIGINT)
857 if want, got := "signal.NotifyContext(context.Background, [interrupt])", fmt.Sprint(c); want != got {
858 t.Errorf("c.String() = %q, want %q", got, want)
861 var wg sync.WaitGroup
864 for i := 0; i < n; i++ {
873 if got := c.Err(); got != context.Canceled {
874 t.Errorf("c.Err() = %q, want %q", got, context.Canceled)
876 case <-time.After(time.Second):
877 t.Errorf("expected context to be canceled")
881 func TestNotifyContextStringer(t *testing.T) {
882 parent, cancelParent := context.WithCancel(context.Background())
884 c, stop := NotifyContext(parent, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM)
887 want := `signal.NotifyContext(context.Background.WithCancel, [hangup interrupt terminated])`
888 if got := fmt.Sprint(c); got != want {
889 t.Errorf("c.String() = %q, want %q", got, want)
893 // #44193 test signal handling while stopping and starting the world.
894 func TestSignalTrace(t *testing.T) {
895 done := make(chan struct{})
896 quit := make(chan struct{})
897 c := make(chan os.Signal, 1)
898 Notify(c, syscall.SIGHUP)
900 // Source and sink for signals busy loop unsynchronized with
901 // trace starts and stops. We are ultimately validating that
902 // signals and runtime.(stop|start)TheWorldGC are compatible.
906 pid := syscall.Getpid()
912 syscall.Kill(pid, syscall.SIGHUP)
914 waitSig(t, c, syscall.SIGHUP)
918 for i := 0; i < 100; i++ {
919 buf := new(bytes.Buffer)
920 if err := trace.Start(buf); err != nil {
921 t.Fatalf("[%d] failed to start tracing: %v", i, err)
923 time.After(1 * time.Microsecond)
927 t.Fatalf("[%d] trace is empty", i)