On Python 3.14, a salt-master with presence_events: True crashes every MWorker at startup. Minions can't auth; no presence events fire.
Versions
Salt 3008.0rc3 · Python 3.14
Repro
- Master with presence_events: True.
- Start under Python 3.14 with any minion.
- Minion loops on AuthenticationError: Master did not return a session key for pillar request.
Scenario test: enable presence_events: True on the master fixture in tests/pytests/scenarios/reauth/ and assert a salt/presence/present event fires.
Root cause
salt/utils/channel.py:iter_transport_opts does copy.deepcopy(opts). opts["secrets"] is SMaster.secrets — multiprocessing.sharedctypes.SynchronizedString objects. Python 3.14's reduce calls assert_spawning(), which raises
outside a spawn context even when start method is fork:
File "salt/utils/channel.py", line 23, in iter_transport_opts
t_opts = copy.deepcopy(opts)
File ".../multiprocessing/sharedctypes.py", line 199, in reduce
assert_spawning(self)
RuntimeError: SynchronizedString objects should only be shared between processes through inheritance
Only presence_events: True reaches this path before workers are up — that's why earlier RCs didn't catch it.
On Python 3.14, a salt-master with presence_events: True crashes every MWorker at startup. Minions can't auth; no presence events fire.
Versions
Salt 3008.0rc3 · Python 3.14
Repro
Scenario test: enable presence_events: True on the master fixture in tests/pytests/scenarios/reauth/ and assert a salt/presence/present event fires.
Root cause
salt/utils/channel.py:iter_transport_opts does copy.deepcopy(opts). opts["secrets"] is SMaster.secrets — multiprocessing.sharedctypes.SynchronizedString objects. Python 3.14's reduce calls assert_spawning(), which raises
outside a spawn context even when start method is fork:
File "salt/utils/channel.py", line 23, in iter_transport_opts
t_opts = copy.deepcopy(opts)
File ".../multiprocessing/sharedctypes.py", line 199, in reduce
assert_spawning(self)
RuntimeError: SynchronizedString objects should only be shared between processes through inheritance
Only presence_events: True reaches this path before workers are up — that's why earlier RCs didn't catch it.