Skip to content

bug(mcp-server): race condition in _init() allows multiple threads to initialize model and client simultaneously #169

@zong0728

Description

@zong0728

Bug Description

_init() in kagent-feast-mcp/mcp-server/server.py performs unsynchronised
lazy initialisation. Under concurrent tool calls, multiple threads can observe
model is None simultaneously and each create a separate SentenceTransformer
instance, wasting memory and causing non-deterministic behaviour.

Root Cause

The check-then-act sequence has no lock, making it a classic TOCTOU race:

def _init():
    global model, client
    if model is None:          # thread A and B both see None here
        model = SentenceTransformer(EMBEDDING_MODEL)   # both initialise
    if client is None:
        client = MilvusClient(...)                     # both initialise

Impact

Redundant model loads under burst traffic increase memory pressure
Non-deterministic which instance ends up in the global, making behaviour hard to reason about in production

Proposed Fix

Apply the double-checked locking pattern with a module-level threading.Lock(): a fast unsynchronised check on the hot path, with a safe re-check under the lock to guarantee single initialisation.

I will submit a PR with this fix.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions