diff --git a/src/backend/base/langflow/main.py b/src/backend/base/langflow/main.py index e80e558922..c24c8de959 100644 --- a/src/backend/base/langflow/main.py +++ b/src/backend/base/langflow/main.py @@ -53,8 +53,6 @@ from langflow.services.utils import initialize_services, initialize_settings_ser from langflow.utils.mcp_cleanup import cleanup_mcp_sessions if TYPE_CHECKING: - from tempfile import TemporaryDirectory - from lfx.services.mcp_composer.service import MCPComposerService # Ignore Pydantic deprecation warnings from Langchain @@ -153,10 +151,9 @@ def get_lifespan(*, fix_migration=False, version=None): async def lifespan(_app: FastAPI): from lfx.interface.components import get_and_cache_all_types_dict - from langflow.preload import _STATE, get_preloaded_temp_dirs, is_master, is_preloaded + from langflow.preload import _STATE, get_owned_temp_dirs, is_preloaded preloaded = is_preloaded() - running_in_master = is_master() configure() @@ -166,7 +163,6 @@ def get_lifespan(*, fix_migration=False, version=None): else: await logger.adebug("Starting Langflow...") - temp_dirs: list[TemporaryDirectory] = [] sync_flows_from_fs_task = None mcp_init_task = None @@ -255,11 +251,10 @@ def get_lifespan(*, fix_migration=False, version=None): if preloaded and _STATE.starter_projects_created: # Inherit bundle paths and types dict from master via COW. - # Only the master owns the bundle temp dirs; workers must NOT - # add them to their own cleanup list, or shutdown would delete - # files that other workers (and the master) still expect. - if running_in_master: - temp_dirs = get_preloaded_temp_dirs() + # get_owned_temp_dirs() returns the preloaded dirs if this is + # the master, or an empty list if this is a worker (workers + # must NOT clean up the master's temp_dirs). + temp_dirs = get_owned_temp_dirs() await logger.adebug("Skipping bundle load, types cache and starter projects: inherited from master") else: current_time = asyncio.get_event_loop().time() diff --git a/src/backend/base/langflow/preload.py b/src/backend/base/langflow/preload.py index ff9400b7d5..29a5696015 100644 --- a/src/backend/base/langflow/preload.py +++ b/src/backend/base/langflow/preload.py @@ -81,6 +81,23 @@ def get_preloaded_temp_dirs() -> list[TemporaryDirectory]: return _STATE.temp_dirs +def get_owned_temp_dirs() -> list[TemporaryDirectory]: + """Return temp_dirs that the current process owns and should clean up. + + When preloaded: + - Master returns the preloaded temp_dirs (it owns them) + - Workers return an empty list (they must NOT clean up master's temp_dirs) + When not preloaded: + - Returns an empty list (will be populated by load_bundles later) + + This encodes the master-only ownership rule so callers don't need + to check is_master() themselves. + """ + if _STATE.preloaded and is_master(): + return _STATE.temp_dirs + return [] + + async def _run_master_preload() -> None: """Run fork-safe one-time initialization inside an asyncio event loop.