terminal,service: print WaitReason, WaitSince for goroutines (#2270)
Fixes #637
This commit is contained in:
parent
433eafb280
commit
6d1c00e56d
@ -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.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user