fix: Eliminate blocking HTTP call from instances_use
instances_use previously called register_instance which made a blocking safe_get (30s timeout) to validate the connection. If the Ghidra server was slow or unresponsive, this could hang the MCP tool call indefinitely from the client's perspective. Now instances_use creates a lazy stub entry and sets the port immediately — pure in-memory, no network I/O. The first actual tool call validates the connection naturally. Also fix background discovery thread using request_timeout (30s) instead of discovery_timeout (0.5s) per port — worst case went from 300s to 5s per scan cycle.
This commit is contained in:
parent
c93abaf86c
commit
458d4fb35b
@ -166,13 +166,20 @@ class InstancesMixin(GhydraMixinBase):
|
||||
Returns:
|
||||
Confirmation message with instance details
|
||||
"""
|
||||
# Register lazily without blocking HTTP calls.
|
||||
# If the instance is unknown, create a stub entry — the first
|
||||
# actual tool call (functions_list, etc.) will validate the
|
||||
# connection and fail fast with a clear error if unreachable.
|
||||
with self._instances_lock:
|
||||
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
|
||||
if port not in self._instances:
|
||||
config = get_config()
|
||||
self._instances[port] = {
|
||||
"url": f"http://{config.ghidra_host}:{port}",
|
||||
"project": "",
|
||||
"file": "",
|
||||
"registered_at": time.time(),
|
||||
"lazy": True,
|
||||
}
|
||||
|
||||
self.set_current_port(port)
|
||||
|
||||
|
||||
@ -105,10 +105,14 @@ def create_server(
|
||||
def _periodic_discovery(interval: int = 30):
|
||||
"""Background thread for periodic instance discovery.
|
||||
|
||||
Uses a short timeout per port so a full scan completes quickly
|
||||
even when most ports are unreachable.
|
||||
|
||||
Args:
|
||||
interval: Seconds between discovery attempts
|
||||
"""
|
||||
from .core.http_client import safe_get
|
||||
import requests as _requests
|
||||
|
||||
from .mixins.base import GhydraMixinBase
|
||||
|
||||
config = get_config()
|
||||
@ -116,15 +120,22 @@ def _periodic_discovery(interval: int = 30):
|
||||
while True:
|
||||
time.sleep(interval)
|
||||
try:
|
||||
# Quick scan of common ports
|
||||
# Quick scan — use discovery_timeout (0.5s), NOT request_timeout (30s)
|
||||
for port in config.quick_discovery_range:
|
||||
try:
|
||||
response = safe_get(port, "")
|
||||
url = f"http://{config.ghidra_host}:{port}/"
|
||||
resp = _requests.get(
|
||||
url,
|
||||
timeout=config.discovery_timeout,
|
||||
headers={"Accept": "application/json"},
|
||||
)
|
||||
if resp.ok:
|
||||
response = resp.json()
|
||||
if response.get("success", False):
|
||||
with GhydraMixinBase._instances_lock:
|
||||
if port not in GhydraMixinBase._instances:
|
||||
GhydraMixinBase._instances[port] = {
|
||||
"url": f"http://{config.ghidra_host}:{port}",
|
||||
"url": url.rstrip("/"),
|
||||
"project": response.get("project", ""),
|
||||
"file": response.get("file", ""),
|
||||
"discovered_at": time.time(),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user