zinx
zinx copied to clipboard
ConnManager ClearConn方法死锁问题
代码分支: master
ClearConn方法会对connMgr 加锁,然后会循环调用conn.Stop()
在conn.Stop()
中会调用c.TCPServer.GetConnMgr().Remove(c)来移除连接
此时调用了connMgr.Remove()
方法,在这个方法中,会对connMgr再次加锁,最终导致死锁
下面的实例会触发死锁,无法正常关闭,zinx_v2.0, v1.0.0等分支均存在此bug
func main() {
s := znet.NewServer()
s.Start()
time.Sleep(time.Second * 1)
go func() {
_, _ = net.Dial("tcp", "127.0.0.1:8999")
}()
time.Sleep(time.Second * 1)
s.Stop()
}
这个问题还是挺严重的,希望能尽快修复吧 我暂时将ClearConn进行了如下改造,暂时避免了这个问题,但没有思考过是否存在并发风险,大家可以考虑下是不是有更好的办法
func (connMgr *ConnManager) ClearConn() {
connections := make([]iface.IConnection, 0, connMgr.Len())
//保护共享资源Map 加写锁
connMgr.connLock.Lock()
//停止并删除全部的连接信息
for connID, conn := range connMgr.connections {
connections = append(connections, conn)
//删除
delete(connMgr.connections, connID)
}
connMgr.connLock.Unlock()
//停止
for _, conn := range connections {
conn.Stop()
}
}
@graydovee PR已验证,非常棒,也十分感谢提交PR,已经Merge
感觉是不是直接把ClearConn()里边加的写锁去掉就行了 因为ClearConn()方法是服务器调用关闭只有一次不存在并发问题,并且删除map中的每一个connection也就是实际调用Remove()的时候,Remove内部会加写锁避免了链接并发问题。