From 0abd4b66a3073564c4e28c7fb7192d98918d9131 Mon Sep 17 00:00:00 2001 From: Paul De Geest Date: Sun, 22 Mar 2026 19:56:55 +0100 Subject: [PATCH] fix: propagate start() to backends in DistributedObjectStore DistributedObjectStore inherited the no-op base ObjectStore.start(), so IRODSObjectStore.start() was never called after fork. This meant the ConnectionPoolMonitorThread never started, causing stale iRODS connections to accumulate. When get_connection() found them, it called conn.disconnect() -> ssl.unwrap() on a dead socket, blocking for the full socket timeout before raising TimeoutError. Fixes #22219 --- lib/galaxy/objectstore/__init__.py | 4 ++++ test/unit/objectstore/test_objectstore.py | 14 +++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/galaxy/objectstore/__init__.py b/lib/galaxy/objectstore/__init__.py index d7b51f731a2..2148a6eeb9a 100644 --- a/lib/galaxy/objectstore/__init__.py +++ b/lib/galaxy/objectstore/__init__.py @@ -1482,6 +1482,10 @@ class DistributedObjectStore(NestedObjectStore): as_dict["backends"] = backends return as_dict + def start(self): + for backend in self.backends.values(): + backend.start() + def shutdown(self): """Shut down. Kill the free space monitor if there is one.""" super().shutdown() diff --git a/test/unit/objectstore/test_objectstore.py b/test/unit/objectstore/test_objectstore.py index 6fe31f79bb4..3704f967250 100644 --- a/test/unit/objectstore/test_objectstore.py +++ b/test/unit/objectstore/test_objectstore.py @@ -6,7 +6,10 @@ from tempfile import ( mkdtemp, mkstemp, ) -from unittest.mock import patch +from unittest.mock import ( + MagicMock, + patch, +) from uuid import uuid4 import pytest @@ -514,6 +517,15 @@ def test_distributed_store_with_cache_targets(): assert len(object_store.cache_targets()) == 2 +def test_distributed_store_start_propagates_to_backends(): + with TestConfig(DISTRIBUTED_TEST_CONFIG) as (_, object_store): + for backend in object_store.backends.values(): + backend.start = MagicMock() + object_store.start() + for backend in object_store.backends.values(): + backend.start.assert_called_once() + + HIERARCHICAL_MUST_HAVE_UNIFIED_QUOTA_SOURCE = """