RussellLuo / timingwheel

Golang implementation of Hierarchical Timing Wheels.
MIT License
657 stars 123 forks source link

添加定时器异常 #18

Open lonerwolf opened 4 years ago

lonerwolf commented 4 years ago

panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x20 pc=0x9cecc5] goroutine 35650 [running]: github.com/lonerwolf/danyun-service/server.(ClientSession).GetMessage.func2() /home/lonerwolf/danyun-service/server/client_session.go:71 +0x45 created by github.com/RussellLuo/timingwheel.(TimingWheel).addOrRun /home/lonerwolf/go/pkg/mod/github.com/!russell!luo/timingwheel@v0.0.0-20191022104228-f534fd34a762/timingwheel.go:117 +0x60

源代码 session.HeartTimeoutTimer.Stop() session.HeartTimeoutTimer = session.timingWheel.AfterFunc(time.Second*300, func() { log.Debugf("CloseSession by HeartTimeoutTimer RemoteAddr:%s sessionID:%d", session.conn.RemoteAddr().String(), session.SessionID) session.Close() }) AfterFunc 出错,这是为啥

RussellLuo commented 4 years ago

@lonerwolf 你好,方便贴一下可以复现问题的最小完整代码,以及完整的报错信息吗?另外代码的运行环境是怎样的?

lonerwolf commented 4 years ago

@lonerwolf 你好,方便贴一下可以复现问题的最小完整代码,以及完整的报错信息吗?另外代码的运行环境是怎样的?

情况是这样的,就是一个TCP服务器,开启定时器,多少时间没有收到心跳就关闭连接,收到就停止定时器,再开启新的定时器。现在是开起了32个协程处理TCP连接,也就是32个协程管理了1W多个TCP会话。在接受这里处理定时器的关闭和开启。然后就上面异常,出现概率很小。GO 13.4 13.5都出现。13.4的时候出现我以为是其他问题,因为确实存在其他问题。现在上生产出现了,生产环境是13.5。暂时没有最小代码,现在我把生产环境上的全部用GO原生TIMER替换了

lonerwolf commented 4 years ago

出错在session.timingWheel.AfterFunc(time.Second*300, func() {} 进去的addOrRun

RussellLuo commented 4 years ago

从你给的报错信息来看,出现 panic 的 goroutine 是由 addOrRun 创建的,但是 "invalid memory address or nil pointer dereference" 这个 error 发生在 goroutine 内部的这一行:

github.com/lonerwolf/danyun-service/server.(*ClientSession).GetMessage.func2() /home/lonerwolf/danyun-service/server/client_session.go:71 +0x45

初步怀疑是传入的处理函数 f 内部的 session.conn 或者 session.SessionID 存在问题?

lonerwolf commented 4 years ago

从你给的报错信息来看,出现 panic 的 goroutine 是由 addOrRun 创建的,但是 "invalid memory address or nil pointer dereference" 这个 error 发生在 goroutine 内部的这一行:

github.com/lonerwolf/danyun-service/server.(*ClientSession).GetMessage.func2() /home/lonerwolf/danyun-service/server/client_session.go:71 +0x45

初步怀疑是传入的处理函数 f 内部的 session.conn 或者 session.SessionID 存在问题?

提示错误的不在执行函数里面,在addOrRun t为空

RussellLuo commented 4 years ago

@lonerwolf 据我所知,Go 的调用栈信息是由近及远的(即越往下离错误越远),参考示例 https://play.golang.org/p/SulKU12FkgF