zinx icon indicating copy to clipboard operation
zinx copied to clipboard

ConnManager ClearConn方法死锁问题

Open graydovee opened this issue 3 years ago • 2 comments

代码分支: 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 avatar Jan 08 '22 12:01 graydovee

@graydovee PR已验证,非常棒,也十分感谢提交PR,已经Merge

aceld avatar Jan 11 '22 03:01 aceld

感觉是不是直接把ClearConn()里边加的写锁去掉就行了 因为ClearConn()方法是服务器调用关闭只有一次不存在并发问题,并且删除map中的每一个connection也就是实际调用Remove()的时候,Remove内部会加写锁避免了链接并发问题。

weilanhanf avatar Mar 20 '22 10:03 weilanhanf