Skip to content

Commit b84bf19

Browse files
authored
fix: always use spawn for subprocess (#930)
1 parent 1eedf72 commit b84bf19

File tree

1 file changed

+15
-1
lines changed

1 file changed

+15
-1
lines changed

python/cocoindex/subprocess_exec.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from .user_app_loader import load_user_app
2323
from .runtime import execution_context
2424
import logging
25+
import multiprocessing as mp
2526

2627
WATCHDOG_INTERVAL_SECONDS = 10.0
2728

@@ -43,6 +44,7 @@ def _get_pool() -> ProcessPoolExecutor:
4344
max_workers=1,
4445
initializer=_subprocess_init,
4546
initargs=(_user_apps, os.getpid()),
47+
mp_context=mp.get_context("spawn"),
4648
)
4749
return _pool
4850

@@ -69,6 +71,7 @@ def _restart_pool(old_pool: ProcessPoolExecutor | None = None) -> None:
6971
max_workers=1,
7072
initializer=_subprocess_init,
7173
initargs=(_user_apps, os.getpid()),
74+
mp_context=mp.get_context("spawn"),
7275
)
7376
if prev_pool is not None:
7477
# Best-effort shutdown of previous pool; letting exceptions bubble up
@@ -124,8 +127,19 @@ def _watch() -> None:
124127

125128
def _subprocess_init(user_apps: list[str], parent_pid: int) -> None:
126129
_start_parent_watchdog(parent_pid)
130+
131+
# In case any user app is already in this subprocess, e.g. the subprocess is forked, we need to avoid loading it again.
132+
with _pool_lock:
133+
already_loaded_apps = set(_user_apps)
134+
135+
loaded_apps = []
127136
for app_target in user_apps:
128-
load_user_app(app_target)
137+
if app_target not in already_loaded_apps:
138+
load_user_app(app_target)
139+
loaded_apps.append(app_target)
140+
141+
with _pool_lock:
142+
_user_apps.extend(loaded_apps)
129143

130144

131145
class _OnceResult:

0 commit comments

Comments
 (0)