aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/trace.go
diff options
context:
space:
mode:
authorMichael Anthony Knyszek <mknyszek@google.com>2020-05-19 16:33:17 +0000
committerMichael Knyszek <mknyszek@google.com>2020-05-21 14:48:50 +0000
commitc847589ad06a1acfcceaac7b230c0d5a826caab8 (patch)
treefac92e13da0a4e8cff561c73010c34a7fb2e9a93 /src/runtime/trace.go
parent39ea0ea05dcfa281dc5977410b60458f2d2adb99 (diff)
downloadgo-c847589ad06a1acfcceaac7b230c0d5a826caab8.tar.gz
go-c847589ad06a1acfcceaac7b230c0d5a826caab8.zip
runtime: synchronize StartTrace and StopTrace with sysmon
Currently sysmon is not stopped when the world is stopped, which is in general a difficult thing to do. The result of this is that when tracing starts and the value of trace.enabled changes, it's possible for sysmon to fail to emit an event when it really should. This leads to traces which the execution trace parser deems inconsistent. Fix this by putting all of sysmon's work behind a new lock sysmonlock. StartTrace and StopTrace both acquire this lock after stopping the world but before performing any work in order to ensure sysmon sees the required state change in tracing. This change is expected to slow down StartTrace and StopTrace, but will help ensure consistent traces are generated. Updates #29707. Fixes #38794. Change-Id: I64c58e7c3fd173cd5281ffc208d6db24ff6c0284 Reviewed-on: https://go-review.googlesource.com/c/go/+/234617 Run-TryBot: Michael Knyszek <mknyszek@google.com> Run-TryBot: Ian Lance Taylor <iant@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org> Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com> Reviewed-by: Michael Pratt <mpratt@google.com>
Diffstat (limited to 'src/runtime/trace.go')
-rw-r--r--src/runtime/trace.go12
1 files changed, 12 insertions, 0 deletions
diff --git a/src/runtime/trace.go b/src/runtime/trace.go
index 33062daa46..169b650eb4 100644
--- a/src/runtime/trace.go
+++ b/src/runtime/trace.go
@@ -187,6 +187,9 @@ func StartTrace() error {
// paired with an end).
stopTheWorldGC("start tracing")
+ // Prevent sysmon from running any code that could generate events.
+ lock(&sched.sysmonlock)
+
// We are in stop-the-world, but syscalls can finish and write to trace concurrently.
// Exitsyscall could check trace.enabled long before and then suddenly wake up
// and decide to write to trace at a random point in time.
@@ -196,6 +199,7 @@ func StartTrace() error {
if trace.enabled || trace.shutdown {
unlock(&trace.bufLock)
+ unlock(&sched.sysmonlock)
startTheWorldGC()
return errorString("tracing is already enabled")
}
@@ -267,6 +271,8 @@ func StartTrace() error {
unlock(&trace.bufLock)
+ unlock(&sched.sysmonlock)
+
startTheWorldGC()
return nil
}
@@ -279,10 +285,14 @@ func StopTrace() {
stopTheWorldGC("stop tracing")
// See the comment in StartTrace.
+ lock(&sched.sysmonlock)
+
+ // See the comment in StartTrace.
lock(&trace.bufLock)
if !trace.enabled {
unlock(&trace.bufLock)
+ unlock(&sched.sysmonlock)
startTheWorldGC()
return
}
@@ -320,6 +330,8 @@ func StopTrace() {
trace.shutdown = true
unlock(&trace.bufLock)
+ unlock(&sched.sysmonlock)
+
startTheWorldGC()
// The world is started but we've set trace.shutdown, so new tracing can't start.