go dlv debug 进程
类似gdb LLDB
只有 Delve 是专门为 Go 语言设计开发的调试工具. 线上debug break断点.
- 定位到函数某行,还可以。一直输入goroutines 能能看到哪里hang住。
- 看哪些goroutine运行什么,bt也可以。
- 看汇编...
go install github.com/go-delve/delve/cmd/dlv@latest
提供个hang死code
package main
import (
"fmt"
"math/rand"
"strconv"
"sync"
"time"
)
type AllData struct {
data map[*Conn]*Conn
dLock sync.RWMutex
closeChan chan *Conn
}
type Conn struct {
Name string
Id int
tag bool
}
func main() {
allData := &AllData{
data: make(map[*Conn]*Conn, 10),
closeChan: make(chan *Conn, 5),
}
go allData.addTest()
go allData.waitfordie()
go func() {
interval := 100 * time.Millisecond
timer := time.NewTimer(interval)
for {
select {
case <-timer.C:
allData.rangeForTest()
timer.Reset(interval)
}
}
}()
go func() {
interval := 3 * time.Millisecond
timer := time.NewTimer(interval)
for {
select {
case <-timer.C:
allData.addTest()
timer.Reset(interval)
}
}
}()
for {
time.Sleep(10 * time.Second)
}
}
func (a *AllData) rangeForTest() {
a.dLock.RLock()
defer a.dLock.RUnlock()
for key := range a.data {
if key.Id%5 == 0 {
if key.tag {
fmt.Println("in again")
continue
} else {
key.tag = true
a.closeChan <- key // todo 这里阻塞
fmt.Println("rangeForTest in ", len(a.closeChan), time.Now())
}
}
}
fmt.Println("rangeForTest ", time.Now())
}
func (a *AllData) addTest() {
a.dLock.Lock()
intn := rand.Intn(1000)
//fmt.Println(">>>>>>>>>>>>>>>>>>", "addTest", intn)
c := &Conn{
Name: "this is test :" + strconv.Itoa(intn),
Id: intn,
tag: false,
}
a.data[c] = c
a.dLock.Unlock()
//fmt.Printf("allData len %d\n", len(a.data))
}
func (a *AllData) deleteConn(c *Conn) {
a.dLock.Lock()
defer a.dLock.Unlock()
delete(a.data, c)
fmt.Println("deleteConn", c.Id, time.Now())
}
func (a *AllData) waitfordie() {
for {
select {
case c := <-a.closeChan: // todo func deletechan can't get lock
fmt.Println("accept close info :", c.Id, ">>>>>>>>>>> len:", len(a.closeChan))
a.deleteConn(c) // 上边range 一边往里放, 拿着锁, 这里删不掉,满了。 又拿不到锁
}
}
}
- go build v2main.go
- pidof v2main 或者ps -ef| grep v2main
- dlv attach 8796
- goroutines 看到多少协程
- goroutine 【number】 切换到别的协程上
都是系统goroutine- bt 打印调用堆栈 stack
- disass 反编译查看汇编