// GoSysExit has to happen when we have a P, but before GoStart.
// So we emit it here.
if gp.syscallsp != 0 && gp.sysblocktraced {
- traceGoSysExit(gp.sysexitseq, gp.sysexitticks)
+ // Since gp.sysblocktraced is true, we must emit an event.
+ // There is a race between the code that initializes sysexitseq
+ // and sysexitticks (in exitsyscall, which runs without a P,
+ // and therefore is not stopped with the rest of the world)
+ // and the code that initializes a new trace.
+ // The recorded sysexitseq and sysexitticks must therefore
+ // be treated as "best effort". If they are valid for this trace,
+ // then great, use them for greater accuracy.
+ // But if they're not valid for this trace, assume that the
+ // trace was started after the actual syscall exit (but before
+ // we actually managed to start the goroutine, aka right now),
+ // and assign a fresh time stamp to keep the log consistent.
+ seq, ts := gp.sysexitseq, gp.sysexitticks
+ if seq == 0 || int64(seq)-int64(trace.seqStart) < 0 {
+ seq, ts = tracestamp()
+ }
+ traceGoSysExit(seq, ts)
}
traceGoStart()
}