simple.protocolExchanger的PushProtocols方法逻辑问题
发现问题:
309~315行这段代码逻辑存在问题,在当前Push执行未结束时,后续对PushProtocols的调用都会启动一个go routine来延迟调用PushProtocols,而若当前执行仍然未结束,那么就会不停的启动go routine来延迟调用PushProtocols,这有些类似死循环的极端场景。
建议方案: 去掉go routine,直接延迟后递归调用,让后续的PushProtocols调用阻塞等待当前Push执行结束,修改后代码类似如下:
// PushProtocols will send protocols supported by us to the other.
// This method will be invoked when new protocol registering.
func (p *protocolExchanger) PushProtocols(pid peer.ID) error {
// create a signal chan, for listening PUSH_OK back.
signalC := make(chan struct{}, 1)
_, loaded := p.pushSignalMap.LoadOrStore(pid, &signalC)
if loaded {
time.Sleep(time.Second)
err := p.PushProtocols(pid)
if err != nil {
p.logger.Warnf("[ProtocolExchanger][PushProtocols] push failed, (remote pid: %s)", pid)
}
return nil
}
defer p.pushSignalMap.Delete(pid)
// send PUSH , waiting for PUSH_OK back or timeout
timer := time.NewTimer(exchangeTimeout)
err := p.sendSelfProtocols(pid, pb.ProtocolExchangerMsg_PUSH)
if err != nil {
return err
}
select {
case <-signalC:
p.logger.Infof("[ProtocolExchanger][PushProtocols] push success, (remote pid: %s)", pid)
case <-timer.C:
return ErrPushProtocolTimeout
}
return nil
}