The macOS seatbelt profile grants (allow ipc-posix-sem), so POSIX
semaphores are clearly intended to work. But Python's
concurrent.futures.ProcessPoolExecutor (and multiprocessing generally)
crashes on startup under fence:
File ".../concurrent/futures/process.py", line 594, in _check_system_limits
nsems_max = os.sysconf("SC_SEM_NSEMS_MAX")
PermissionError: [Errno 1] Operation not permitted
sysconf(SC_SEM_NSEMS_MAX) performs a sysctl lookup that is not on the
profile's sysctl-read allowlist (which covers hw.* names and a few
others). Python checks this limit before creating any semaphore, so the
allowed ipc-posix-sem capability is unreachable in practice for the most
common Python parallelism API.
Reproduce
fence -- python3 -c "from concurrent.futures import ProcessPoolExecutor as P; P(2).__enter__()"
Real-world hit: marker-pdf (PDF OCR) uses a process pool for text
extraction and dies immediately under fence; the workaround is per-tool
(--disable_multiprocessing) and not always available.
Suggested fix
According to Claude:
Add the POSIX semaphore sysctls to the allowlist, e.g.:
(allow sysctl-read (sysctl-name-prefix "kern.posix.sem."))
(Or the specific name the lookup uses on current macOS — the denial is
visible via log stream --predicate 'sender == "Sandbox"' while running the
one-liner above.)
Unlike GPU access this has no security-posture trade-off worth debating:
it's a read-only limit query required to use a capability the profile
already grants.
Environment: macOS 24.6.0 (Apple Silicon), Python 3.14 (uv-managed), fence
sandbox-exec backend.
The macOS seatbelt profile grants
(allow ipc-posix-sem), so POSIXsemaphores are clearly intended to work. But Python's
concurrent.futures.ProcessPoolExecutor(andmultiprocessinggenerally)crashes on startup under fence:
sysconf(SC_SEM_NSEMS_MAX)performs a sysctl lookup that is not on theprofile's
sysctl-readallowlist (which covershw.*names and a fewothers). Python checks this limit before creating any semaphore, so the
allowed
ipc-posix-semcapability is unreachable in practice for the mostcommon Python parallelism API.
Reproduce
fence -- python3 -c "from concurrent.futures import ProcessPoolExecutor as P; P(2).__enter__()"Real-world hit:
marker-pdf(PDF OCR) uses a process pool for textextraction and dies immediately under fence; the workaround is per-tool
(
--disable_multiprocessing) and not always available.Suggested fix
According to Claude:
Environment: macOS 24.6.0 (Apple Silicon), Python 3.14 (uv-managed), fence
sandbox-execbackend.