diff --git a/tractor/ipc/_mp_bs.py b/tractor/ipc/_mp_bs.py index 33a64a32..462291c6 100644 --- a/tractor/ipc/_mp_bs.py +++ b/tractor/ipc/_mp_bs.py @@ -17,36 +17,59 @@ Utils to tame mp non-SC madeness ''' +import platform + -# !TODO! in 3.13 this can be disabled (the-same/similarly) using -# a flag, -# - [ ] soo if it works like this, drop this module entirely for -# 3.13+ B) -# |_https://docs.python.org/3/library/multiprocessing.shared_memory.html -# def disable_mantracker(): ''' Disable all `multiprocessing` "resource tracking" machinery since it's an absolute multi-threaded mess of non-SC madness. ''' - from multiprocessing import resource_tracker as mantracker + from multiprocessing.shared_memory import SharedMemory - # Tell the "resource tracker" thing to fuck off. - class ManTracker(mantracker.ResourceTracker): - def register(self, name, rtype): - pass - def unregister(self, name, rtype): - pass + # 3.13+ only.. can pass `track=False` to disable + # all the resource tracker bs. + # https://docs.python.org/3/library/multiprocessing.shared_memory.html + if (_py_313 := ( + platform.python_version_tuple()[:-1] + >= + ('3', '13') + ) + ): + from functools import partial + return partial( + SharedMemory, + track=False, + ) - def ensure_running(self): - pass + # !TODO, once we drop 3.12- we can obvi remove all this! + else: + from multiprocessing import ( + resource_tracker as mantracker, + ) - # "know your land and know your prey" - # https://www.dailymotion.com/video/x6ozzco - mantracker._resource_tracker = ManTracker() - mantracker.register = mantracker._resource_tracker.register - mantracker.ensure_running = mantracker._resource_tracker.ensure_running - mantracker.unregister = mantracker._resource_tracker.unregister - mantracker.getfd = mantracker._resource_tracker.getfd + # Tell the "resource tracker" thing to fuck off. + class ManTracker(mantracker.ResourceTracker): + def register(self, name, rtype): + pass + + def unregister(self, name, rtype): + pass + + def ensure_running(self): + pass + + # "know your land and know your prey" + # https://www.dailymotion.com/video/x6ozzco + mantracker._resource_tracker = ManTracker() + mantracker.register = mantracker._resource_tracker.register + mantracker.ensure_running = mantracker._resource_tracker.ensure_running + mantracker.unregister = mantracker._resource_tracker.unregister + mantracker.getfd = mantracker._resource_tracker.getfd + + # use std type verbatim + shmT = SharedMemory + + return shmT diff --git a/tractor/ipc/_shm.py b/tractor/ipc/_shm.py index ed17a2b7..2360f893 100644 --- a/tractor/ipc/_shm.py +++ b/tractor/ipc/_shm.py @@ -23,14 +23,15 @@ considered optional within the context of this runtime-library. """ from __future__ import annotations +from multiprocessing import shared_memory as shm +from multiprocessing.shared_memory import ( + # SharedMemory, + ShareableList, +) +import platform from sys import byteorder import time from typing import Optional -from multiprocessing import shared_memory as shm -from multiprocessing.shared_memory import ( - SharedMemory, - ShareableList, -) from msgspec import ( Struct, @@ -61,7 +62,7 @@ except ImportError: log = get_logger(__name__) -disable_mantracker() +SharedMemory = disable_mantracker() class SharedInt: @@ -797,8 +798,15 @@ def open_shm_list( # "close" attached shm on actor teardown try: actor = tractor.current_actor() + actor.lifetime_stack.callback(shml.shm.close) - actor.lifetime_stack.callback(shml.shm.unlink) + + # XXX on 3.13+ we don't need to call this? + # -> bc we pass `track=False` for `SharedMemeory` orr? + if ( + platform.python_version_tuple()[:-1] < ('3', '13') + ): + actor.lifetime_stack.callback(shml.shm.unlink) except RuntimeError: log.warning('tractor runtime not active, skipping teardown steps')