swarm/pss: fix data race on topicHandlerCaps map (#18523)
This commit is contained in:
		
				
					committed by
					
						
						Anton Evangelatov
					
				
			
			
				
	
			
			
			
						parent
						
							17723a5294
						
					
				
				
					commit
					2209fede4e
				
			@@ -141,7 +141,8 @@ type Pss struct {
 | 
				
			|||||||
	handlers           map[Topic]map[*handler]bool // topic and version based pss payload handlers. See pss.Handle()
 | 
						handlers           map[Topic]map[*handler]bool // topic and version based pss payload handlers. See pss.Handle()
 | 
				
			||||||
	handlersMu         sync.RWMutex
 | 
						handlersMu         sync.RWMutex
 | 
				
			||||||
	hashPool           sync.Pool
 | 
						hashPool           sync.Pool
 | 
				
			||||||
	topicHandlerCaps map[Topic]*handlerCaps // caches capabilities of each topic's handlers (see handlerCap* consts in types.go)
 | 
						topicHandlerCaps   map[Topic]*handlerCaps // caches capabilities of each topic's handlers
 | 
				
			||||||
 | 
						topicHandlerCapsMu sync.RWMutex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// process
 | 
						// process
 | 
				
			||||||
	quitC chan struct{}
 | 
						quitC chan struct{}
 | 
				
			||||||
@@ -307,6 +308,19 @@ func (p *Pss) PublicKey() *ecdsa.PublicKey {
 | 
				
			|||||||
// SECTION: Message handling
 | 
					// SECTION: Message handling
 | 
				
			||||||
/////////////////////////////////////////////////////////////////////
 | 
					/////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *Pss) getTopicHandlerCaps(topic Topic) (hc *handlerCaps, found bool) {
 | 
				
			||||||
 | 
						p.topicHandlerCapsMu.RLock()
 | 
				
			||||||
 | 
						defer p.topicHandlerCapsMu.RUnlock()
 | 
				
			||||||
 | 
						hc, found = p.topicHandlerCaps[topic]
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *Pss) setTopicHandlerCaps(topic Topic, hc *handlerCaps) {
 | 
				
			||||||
 | 
						p.topicHandlerCapsMu.Lock()
 | 
				
			||||||
 | 
						defer p.topicHandlerCapsMu.Unlock()
 | 
				
			||||||
 | 
						p.topicHandlerCaps[topic] = hc
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Links a handler function to a Topic
 | 
					// Links a handler function to a Topic
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// All incoming messages with an envelope Topic matching the
 | 
					// All incoming messages with an envelope Topic matching the
 | 
				
			||||||
@@ -323,20 +337,24 @@ func (p *Pss) Register(topic *Topic, hndlr *handler) func() {
 | 
				
			|||||||
	if handlers == nil {
 | 
						if handlers == nil {
 | 
				
			||||||
		handlers = make(map[*handler]bool)
 | 
							handlers = make(map[*handler]bool)
 | 
				
			||||||
		p.handlers[*topic] = handlers
 | 
							p.handlers[*topic] = handlers
 | 
				
			||||||
		log.Debug("registered handler", "caps", hndlr.caps)
 | 
							log.Debug("registered handler", "capabilities", hndlr.caps)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if hndlr.caps == nil {
 | 
						if hndlr.caps == nil {
 | 
				
			||||||
		hndlr.caps = &handlerCaps{}
 | 
							hndlr.caps = &handlerCaps{}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	handlers[hndlr] = true
 | 
						handlers[hndlr] = true
 | 
				
			||||||
	if _, ok := p.topicHandlerCaps[*topic]; !ok {
 | 
					
 | 
				
			||||||
		p.topicHandlerCaps[*topic] = &handlerCaps{}
 | 
						capabilities, ok := p.getTopicHandlerCaps(*topic)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							capabilities = &handlerCaps{}
 | 
				
			||||||
 | 
							p.setTopicHandlerCaps(*topic, capabilities)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if hndlr.caps.raw {
 | 
						if hndlr.caps.raw {
 | 
				
			||||||
		p.topicHandlerCaps[*topic].raw = true
 | 
							capabilities.raw = true
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if hndlr.caps.prox {
 | 
						if hndlr.caps.prox {
 | 
				
			||||||
		p.topicHandlerCaps[*topic].prox = true
 | 
							capabilities.prox = true
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return func() { p.deregister(topic, hndlr) }
 | 
						return func() { p.deregister(topic, hndlr) }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -357,7 +375,7 @@ func (p *Pss) deregister(topic *Topic, hndlr *handler) {
 | 
				
			|||||||
				caps.prox = true
 | 
									caps.prox = true
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		p.topicHandlerCaps[*topic] = caps
 | 
							p.setTopicHandlerCaps(*topic, caps)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	delete(handlers, hndlr)
 | 
						delete(handlers, hndlr)
 | 
				
			||||||
@@ -390,8 +408,8 @@ func (p *Pss) handlePssMsg(ctx context.Context, msg interface{}) error {
 | 
				
			|||||||
	// raw is simplest handler contingency to check, so check that first
 | 
						// raw is simplest handler contingency to check, so check that first
 | 
				
			||||||
	var isRaw bool
 | 
						var isRaw bool
 | 
				
			||||||
	if pssmsg.isRaw() {
 | 
						if pssmsg.isRaw() {
 | 
				
			||||||
		if _, ok := p.topicHandlerCaps[psstopic]; ok {
 | 
							if capabilities, ok := p.getTopicHandlerCaps(psstopic); ok {
 | 
				
			||||||
			if !p.topicHandlerCaps[psstopic].raw {
 | 
								if !capabilities.raw {
 | 
				
			||||||
				log.Debug("No handler for raw message", "topic", psstopic)
 | 
									log.Debug("No handler for raw message", "topic", psstopic)
 | 
				
			||||||
				return nil
 | 
									return nil
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -404,8 +422,8 @@ func (p *Pss) handlePssMsg(ctx context.Context, msg interface{}) error {
 | 
				
			|||||||
	// - prox handler on message and we are in prox regardless of partial address match
 | 
						// - prox handler on message and we are in prox regardless of partial address match
 | 
				
			||||||
	// store this result so we don't calculate again on every handler
 | 
						// store this result so we don't calculate again on every handler
 | 
				
			||||||
	var isProx bool
 | 
						var isProx bool
 | 
				
			||||||
	if _, ok := p.topicHandlerCaps[psstopic]; ok {
 | 
						if capabilities, ok := p.getTopicHandlerCaps(psstopic); ok {
 | 
				
			||||||
		isProx = p.topicHandlerCaps[psstopic].prox
 | 
							isProx = capabilities.prox
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	isRecipient := p.isSelfPossibleRecipient(pssmsg, isProx)
 | 
						isRecipient := p.isSelfPossibleRecipient(pssmsg, isProx)
 | 
				
			||||||
	if !isRecipient {
 | 
						if !isRecipient {
 | 
				
			||||||
@@ -783,8 +801,8 @@ func (p *Pss) SendRaw(address PssAddress, topic Topic, msg []byte) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// if we have a proxhandler on this topic
 | 
						// if we have a proxhandler on this topic
 | 
				
			||||||
	// also deliver message to ourselves
 | 
						// also deliver message to ourselves
 | 
				
			||||||
	if _, ok := p.topicHandlerCaps[topic]; ok {
 | 
						if capabilities, ok := p.getTopicHandlerCaps(topic); ok {
 | 
				
			||||||
		if p.isSelfPossibleRecipient(pssMsg, true) && p.topicHandlerCaps[topic].prox {
 | 
							if p.isSelfPossibleRecipient(pssMsg, true) && capabilities.prox {
 | 
				
			||||||
			return p.process(pssMsg, true, true)
 | 
								return p.process(pssMsg, true, true)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -885,8 +903,8 @@ func (p *Pss) send(to []byte, topic Topic, msg []byte, asymmetric bool, key []by
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if _, ok := p.topicHandlerCaps[topic]; ok {
 | 
						if capabilities, ok := p.getTopicHandlerCaps(topic); ok {
 | 
				
			||||||
		if p.isSelfPossibleRecipient(pssMsg, true) && p.topicHandlerCaps[topic].prox {
 | 
							if p.isSelfPossibleRecipient(pssMsg, true) && capabilities.prox {
 | 
				
			||||||
			return p.process(pssMsg, true, true)
 | 
								return p.process(pssMsg, true, true)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user