Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions loky/backend/synchronize.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@
from multiprocessing import process, util
from multiprocessing.context import assert_spawning

# Import Python's stdlib resource_tracker to unregister semaphores from it
# This prevents "leaked semaphore" warnings on Python 3.13+ when loky manages cleanup
try:
from multiprocessing import resource_tracker as stdlib_resource_tracker
except ImportError:
stdlib_resource_tracker = None

from . import resource_tracker

__all__ = [
Expand Down Expand Up @@ -72,6 +79,14 @@ def __init__(self, kind, value, maxvalue, name=None):
self._semlock = _SemLock(
kind, value, maxvalue, SemLock._make_name(), unlink_now
)
# FIX: Unregister from stdlib resource_tracker immediately after creation
# to prevent "leaked semaphore" warnings on Python 3.13+
if stdlib_resource_tracker is not None:
try:
stdlib_resource_tracker.unregister(self._semlock.name, "semlock")
except (KeyError, ValueError):
# Semaphore wasn't registered in stdlib tracker, that's fine
pass
except FileExistsError: # pragma: no cover
pass
else:
Expand All @@ -80,6 +95,14 @@ def __init__(self, kind, value, maxvalue, name=None):
raise FileExistsError("cannot find name for semaphore")
else:
self._semlock = _SemLock(kind, value, maxvalue, name, unlink_now)
# FIX: Unregister from stdlib resource_tracker immediately after creation
# to prevent "leaked semaphore" warnings on Python 3.13+
if stdlib_resource_tracker is not None:
try:
stdlib_resource_tracker.unregister(self._semlock.name, "semlock")
except (KeyError, ValueError):
# Semaphore wasn't registered in stdlib tracker, that's fine
pass
self.name = name
util.debug(
f"created semlock with handle {self._semlock.handle} and name "
Expand All @@ -96,6 +119,7 @@ def _after_fork(obj):
# When the object is garbage collected or the
# process shuts down we unlink the semaphore name
resource_tracker.register(self._semlock.name, "semlock")

util.Finalize(
self, SemLock._cleanup, (self._semlock.name,), exitpriority=0
)
Expand Down