terminal,service: print WaitReason, WaitSince for goroutines (#2270)

Fixes #637
This commit is contained in:
Alessandro Arzilli 2021-01-05 19:59:17 +01:00 committed by GitHub
parent 433eafb280
commit 6d1c00e56d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 59 additions and 6 deletions

@ -322,9 +322,7 @@ func TestRedirect(t *testing.T) {
// and detach from and kill the headless instance
client := rpc2.NewClient(listenAddr)
if err := client.Detach(true); err != nil {
t.Fatalf("error detaching from headless instance: %v", err)
}
_ = client.Detach(true)
cmd.Wait()
}

@ -20,6 +20,7 @@ import (
"strconv"
"strings"
"text/tabwriter"
"time"
"github.com/cosiner/argv"
"github.com/go-delve/delve/pkg/locspec"
@ -922,11 +923,58 @@ func (t *Term) formatGoroutine(g *api.Goroutine, fgl formatGoroutineLoc) string
locname = "Start"
loc = g.StartLoc
}
thread := ""
buf := new(strings.Builder)
fmt.Fprintf(buf, "%d - %s: %s", g.ID, locname, t.formatLocation(loc))
if g.ThreadID != 0 {
thread = fmt.Sprintf(" (thread %d)", g.ThreadID)
fmt.Fprintf(buf, " (thread %d)", g.ThreadID)
}
return fmt.Sprintf("%d - %s: %s%s", g.ID, locname, t.formatLocation(loc), thread)
if (g.Status == api.GoroutineWaiting || g.Status == api.GoroutineSyscall) && g.WaitReason != 0 {
var wr string
if g.WaitReason > 0 && g.WaitReason < int64(len(waitReasonStrings)) {
wr = waitReasonStrings[g.WaitReason]
} else {
wr = fmt.Sprintf("unknown wait reason %d", g.WaitReason)
}
fmt.Fprintf(buf, " [%s", wr)
if g.WaitSince > 0 {
fmt.Fprintf(buf, " %s", time.Since(time.Unix(0, g.WaitSince)).String())
}
fmt.Fprintf(buf, "]")
}
return buf.String()
}
var waitReasonStrings = [...]string{
"",
"GC assist marking",
"IO wait",
"chan receive (nil chan)",
"chan send (nil chan)",
"dumping heap",
"garbage collection",
"garbage collection scan",
"panicwait",
"select",
"select (no cases)",
"GC assist wait",
"GC sweep wait",
"GC scavenge wait",
"chan receive",
"chan send",
"finalizer wait",
"force gc (idle)",
"semacquire",
"sleep",
"sync.Cond.Wait",
"timer goroutine (idle)",
"trace reader (blocked)",
"wait for GC cycle",
"GC worker (idle)",
"preempted",
"debug call",
}
func writeGoroutineLong(t *Term, w io.Writer, g *api.Goroutine, prefix string) {

@ -298,6 +298,7 @@ func ConvertGoroutine(g *proc.G) *Goroutine {
WaitSince: g.WaitSince,
WaitReason: g.WaitReason,
Labels: g.Labels(),
Status: g.Status,
}
}

@ -314,6 +314,7 @@ type Goroutine struct {
StartLoc Location `json:"startLoc"`
// ID of the associated thread for running goroutines
ThreadID int `json:"threadID"`
Status uint64 `json:"status"`
WaitSince int64 `json:"waitSince"`
WaitReason int64 `json:"waitReason"`
Unreadable string `json:"unreadable"`
@ -321,6 +322,11 @@ type Goroutine struct {
Labels map[string]string `json:"labels,omitempty"`
}
const (
GoroutineWaiting = proc.Gwaiting
GoroutineSyscall = proc.Gsyscall
)
// DebuggerCommand is a command which changes the debugger's execution state.
type DebuggerCommand struct {
// Name is the command to run.