diff options
author | Andrew G. Morgan <agm@google.com> | 2021-03-26 19:27:22 -0700 |
---|---|---|
committer | Michael Pratt <mpratt@google.com> | 2021-04-21 21:25:26 +0000 |
commit | 7e97e4e8ccdba9677f31ab9380802cd7613f62c5 (patch) | |
tree | 74a0797fa08596e554f1f5f6070fb95ea961aba3 /src/os | |
parent | 54af9fd9e69d5cc33b16b9a32d9f7dc71eef0d18 (diff) | |
download | go-7e97e4e8ccdba9677f31ab9380802cd7613f62c5.tar.gz go-7e97e4e8ccdba9677f31ab9380802cd7613f62c5.zip |
syscall: syscall.AllThreadsSyscall signal handling fixes
The runtime support for syscall.AllThreadsSyscall() functions had
some corner case deadlock issues when signal handling was in use.
This was observed in at least 3 build test failures on ppc64 and
amd64 architecture CGO_ENABLED=0 builds over the last few months.
The fixes involve more controlled handling of signals while the
AllThreads mechanism is being executed. Further details are
discussed in bug #44193.
The all-threads syscall support is new in go1.16, so earlier
releases are not affected by this bug.
Fixes #44193
Change-Id: I01ba8508a6e1bb2d872751f50da86dd07911a41d
Reviewed-on: https://go-review.googlesource.com/c/go/+/305149
Reviewed-by: Michael Pratt <mpratt@google.com>
Trust: Michael Pratt <mpratt@google.com>
Trust: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Michael Pratt <mpratt@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Diffstat (limited to 'src/os')
-rw-r--r-- | src/os/signal/signal_test.go | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/src/os/signal/signal_test.go b/src/os/signal/signal_test.go index 292d24c6f1..4c19281e91 100644 --- a/src/os/signal/signal_test.go +++ b/src/os/signal/signal_test.go @@ -16,6 +16,7 @@ import ( "os" "os/exec" "runtime" + "runtime/trace" "strconv" "sync" "syscall" @@ -854,3 +855,44 @@ func TestNotifyContextStringer(t *testing.T) { t.Errorf("c.String() = %q, want %q", got, want) } } + +// #44193 test signal handling while stopping and starting the world. +func TestSignalTrace(t *testing.T) { + done := make(chan struct{}) + quit := make(chan struct{}) + c := make(chan os.Signal, 1) + Notify(c, syscall.SIGHUP) + + // Source and sink for signals busy loop unsynchronized with + // trace starts and stops. We are ultimately validating that + // signals and runtime.(stop|start)TheWorldGC are compatible. + go func() { + defer close(done) + defer Stop(c) + pid := syscall.Getpid() + for { + select { + case <-quit: + return + default: + syscall.Kill(pid, syscall.SIGHUP) + } + waitSig(t, c, syscall.SIGHUP) + } + }() + + for i := 0; i < 100; i++ { + buf := new(bytes.Buffer) + if err := trace.Start(buf); err != nil { + t.Fatalf("[%d] failed to start tracing: %v", i, err) + } + time.After(1 * time.Microsecond) + trace.Stop() + size := buf.Len() + if size == 0 { + t.Fatalf("[%d] trace is empty", i) + } + } + close(quit) + <-done +} |