From 1b42ab251efb30066024330563ba9c61a1ff4f1d Mon Sep 17 00:00:00 2001 From: Ryan Malloy Date: Fri, 30 Jan 2026 19:25:25 -0700 Subject: [PATCH] fix: Deadlock in instances_use when port not yet registered MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit instances_use held _instances_lock while calling register_instance, which also acquires the same lock — non-reentrant Lock = hang forever. - Release lock before calling register_instance (avoids blocking other threads during the HTTP health check too) - Upgrade Lock → RLock as safety net for any other reentrant paths --- src/ghydramcp/mixins/base.py | 4 ++-- src/ghydramcp/mixins/instances.py | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/ghydramcp/mixins/base.py b/src/ghydramcp/mixins/base.py index e849510..6bbf048 100644 --- a/src/ghydramcp/mixins/base.py +++ b/src/ghydramcp/mixins/base.py @@ -4,7 +4,7 @@ Provides shared state and utilities for all domain mixins. """ import time -from threading import Lock +from threading import RLock from typing import Any, Dict, Optional from fastmcp import Context @@ -25,7 +25,7 @@ class GhydraMixinBase(MCPMixin): # Shared state across all mixins _instances: Dict[int, Dict[str, Any]] = {} - _instances_lock = Lock() + _instances_lock = RLock() _current_port: Optional[int] = None def __init__(self): diff --git a/src/ghydramcp/mixins/instances.py b/src/ghydramcp/mixins/instances.py index 20573c8..e92f4d4 100644 --- a/src/ghydramcp/mixins/instances.py +++ b/src/ghydramcp/mixins/instances.py @@ -168,11 +168,12 @@ class InstancesMixin(GhydraMixinBase): Confirmation message with instance details """ with self._instances_lock: - if port not in self._instances: - # Try to register it first - result = self.register_instance(port) - if "Failed" in result or "Error" in result: - return result + needs_register = port not in self._instances + + if needs_register: + result = self.register_instance(port) + if "Failed" in result or "Error" in result: + return result self.set_current_port(port)