Skip to content

Potential Concurrency Issue with s.clients Access in Server #2

@beka-birhanu

Description

@beka-birhanu

Description

The s.clients map in the Server structure appears to be accessed concurrently without proper synchronization, which may lead to race conditions.

  1. Example 1: Access in findClientBySessionID

    // returns the Client by the Session ID
    func (s *Server) findClientBySessionID(sessionID []byte) (*Client, bool) {
        for _, client := range s.clients {
            if bytes.Equal(client.sessionID, sessionID) {
                return client, true
            }
        }
        return nil, false
    }

    In this method, s.clients is iterated over, potentially while other parts of the code modify it.

  2. Example 2: Modification in Garbage Collection

    case <-s.garbageCollectionTicker.C:
        for _, c := range s.clients {
            if c.lastHeartbeat != nil && time.Now().After(c.lastHeartbeat.Add(s.heartbeatExpiration)) {
                delete(s.clients, c.ID)
                delete(s.sessions, fmt.Sprintf("%s_%d", c.addr.IP.String(), c.addr.Port))
            }
        }
    }

    The garbage collection routine iterates over and modifies s.clients concurrently, potentially leading to a panic due to a concurrent map read and write.

Problem

The s.clients map is not thread-safe. While one goroutine (e.g., the garbage collector) might be deleting clients, another goroutine (e.g., findClientBySessionID) could be iterating or reading from it, leading to undefined behavior or a runtime panic.

Suggestions

  1. Use sync.Map
    Replace s.clients with a sync.Map under a type wrapper. This will ensure thread-safe operations for both reading and writing.

  2. Introduce a Mutex
    Use a sync.Mutex or sync.RWMutex to explicitly lock the s.clients map during reads and writes. This approach ensures safety and maintains the existing map structure but could introduce performance overhead depending on the frequency of access.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions