From c24cc40075d77b96bbf1f217dcdcff651229e89b Mon Sep 17 00:00:00 2001 From: "Hyang-Ah (Hana) Kim" Date: Mon, 8 Aug 2016 17:24:07 -0400 Subject: cmd/trace: fix a runnable goroutine count bug When starting tracing, EvGoCreate events are added for existing goroutines that may have been blocking in syscall. EvGoCreate increments the runnable goroutine count. This change makes the following EvGoInSyscall event decrement the runnable goroutine count because we now know that goroutine is in syscall, and not runnable. Made generateTrace return an error, at any given time, the number of runnable/running/insyscall goroutines becomes non-negative. Added a basic test that checks the number of runnable/running goroutines don't include the goroutines in syscall - the test failed before this change. Change-Id: Ib732c382e7bd17158a437576f9d589ab89097ce6 Reviewed-on: https://go-review.googlesource.com/25552 Run-TryBot: Hyang-Ah Hana Kim TryBot-Result: Gobot Gobot Reviewed-by: Dmitry Vyukov --- src/internal/trace/parser_test.go | 47 ++++----------------------------------- src/internal/trace/writer.go | 45 +++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 43 deletions(-) create mode 100644 src/internal/trace/writer.go (limited to 'src/internal') diff --git a/src/internal/trace/parser_test.go b/src/internal/trace/parser_test.go index daad3e3ad7..d6f580aed5 100644 --- a/src/internal/trace/parser_test.go +++ b/src/internal/trace/parser_test.go @@ -90,52 +90,13 @@ func TestParseVersion(t *testing.T) { func TestTimestampOverflow(t *testing.T) { // Test that parser correctly handles large timestamps (long tracing). - w := newWriter() - w.emit(EvBatch, 0, 0) - w.emit(EvFrequency, 1e9) + w := NewWriter() + w.Emit(EvBatch, 0, 0) + w.Emit(EvFrequency, 1e9) for ts := uint64(1); ts < 1e16; ts *= 2 { - w.emit(EvGoCreate, ts, ts, 0, 0) + w.Emit(EvGoCreate, ts, ts, 0, 0) } if _, err := Parse(w, ""); err != nil { t.Fatalf("failed to parse: %v", err) } } - -type writer struct { - bytes.Buffer -} - -func newWriter() *writer { - w := new(writer) - w.Write([]byte("go 1.7 trace\x00\x00\x00\x00")) - return w -} - -func (w *writer) emit(typ byte, args ...uint64) { - nargs := byte(len(args)) - 1 - if nargs > 3 { - nargs = 3 - } - buf := []byte{typ | nargs<<6} - if nargs == 3 { - buf = append(buf, 0) - } - for _, a := range args { - buf = appendVarint(buf, a) - } - if nargs == 3 { - buf[1] = byte(len(buf) - 2) - } - n, err := w.Write(buf) - if n != len(buf) || err != nil { - panic("failed to write") - } -} - -func appendVarint(buf []byte, v uint64) []byte { - for ; v >= 0x80; v >>= 7 { - buf = append(buf, 0x80|byte(v)) - } - buf = append(buf, byte(v)) - return buf -} diff --git a/src/internal/trace/writer.go b/src/internal/trace/writer.go new file mode 100644 index 0000000000..a481f50a7e --- /dev/null +++ b/src/internal/trace/writer.go @@ -0,0 +1,45 @@ +package trace + +import "bytes" + +// Writer is a test trace writer. +type Writer struct { + bytes.Buffer +} + +func NewWriter() *Writer { + w := new(Writer) + w.Write([]byte("go 1.7 trace\x00\x00\x00\x00")) + return w +} + +// Emit writes an event record to the trace. +// See Event types for valid types and required arguments. +func (w *Writer) Emit(typ byte, args ...uint64) { + nargs := byte(len(args)) - 1 + if nargs > 3 { + nargs = 3 + } + buf := []byte{typ | nargs<<6} + if nargs == 3 { + buf = append(buf, 0) + } + for _, a := range args { + buf = appendVarint(buf, a) + } + if nargs == 3 { + buf[1] = byte(len(buf) - 2) + } + n, err := w.Write(buf) + if n != len(buf) || err != nil { + panic("failed to write") + } +} + +func appendVarint(buf []byte, v uint64) []byte { + for ; v >= 0x80; v >>= 7 { + buf = append(buf, 0x80|byte(v)) + } + buf = append(buf, byte(v)) + return buf +} -- cgit v1.3-5-g9baa