Repository navigation
Started multiprocessing.Process instances are unserialisable #91090
Description
Activity
The Python program:
import multiprocessing import time class Application: def __init__(self): self._event = multiprocessing.Event() self._processes = [ multiprocessing.Process(target=self._worker) for _ in range(multiprocessing.cpu_count())] def _worker(self): while not self._event.is_set(): print(multiprocessing.current_process().name) time.sleep(1) def start(self): for process in self._processes: print('starting') process.start() def stop(self): self._event.set() for process in self._processes: process.join() if __name__ == '__main__': application = Application() application.start() time.sleep(3) application.stop()Its output:
starting starting Traceback (most recent call last): File "/Users/maggyero/Desktop/application.py", line 31, in <module> application.start() File "/Users/maggyero/Desktop/application.py", line 21, in start process.start() File "/usr/local/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/multiprocessing/process.py", line 121, in start self._popen = self._Popen(self) File "/usr/local/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/multiprocessing/context.py", line 224, in _Popen return _default_context.get_context().Process._Popen(process_obj) File "/usr/local/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/multiprocessing/context.py", line 284, in _Popen return Popen(process_obj) File "/usr/local/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/multiprocessing/popen_spawn_posix.py", line 32, in __init__ super().__init__(process_obj) File "/usr/local/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/multiprocessing/popen_fork.py", line 19, in __init__ self._launch(process_obj) File "/usr/local/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/multiprocessing/popen_spawn_posix.py", line 47, in _launch reduction.dump(process_obj, fp) File "/usr/local/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/multiprocessing/reduction.py", line 60, in dump ForkingPickler(file, protocol).dump(obj) TypeError: cannot pickle 'weakref' object Traceback (most recent call last): File "<string>", line 1, in <module> File "/usr/local/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/multiprocessing/spawn.py", line 116, in spawn_main exitcode = _main(fd, parent_sentinel) File "/usr/local/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/multiprocessing/spawn.py", line 126, in _main self = reduction.pickle.load(from_parent) File "/usr/local/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/multiprocessing/synchronize.py", line 110, in __setstate__ self._semlock = _multiprocessing.SemLock._rebuild(*state) FileNotFoundError: [Errno 2] No such file or directoryIn the function
Application.__init__, each callmultiprocessing.Process(target=self._worker)initializes amultiprocessing.Processinstance with the instance methodself._workeras itstargetargument.self._workeris bound toselfwhich has the instance attributeself._processes.In the function
Application.start, each callprocess.start()serialises thetargetargument and thereforeself._processes.self._processesis a list ofmultiprocessing.Processinstances, initially not started yet. The first callprocess.start()starts the firstmultiprocessing.Processinstance in that list without issue, but the second callprocess.start()fails.So a started
multiprocessing.Processinstance cannot be serialised.The root of the problem is that the
startmethod of amultiprocessing.Processinstance sets its_popeninstance attribute to amultiprocessing.popen_*.Popeninstance. The initialization of that instance performs these two steps (among others):-
For a
multiprocessing.popen_spawn_posix.Popeninstance, amultiprocessing.popen_spawn_win32.Popeninstance, or amultiprocessing.popen_forkserver.Popeninstance but not amultiprocessing.popen_fork.Popeninstance (i.e. for the start method'spawn'or the start method'forkserver'but not the start method'fork'), it serialises themultiprocessing.Processinstance for writing it to the end of the pipe used by the parent process to communicate with the child process so that the child process can execute therunmethod of themultiprocessing.Processinstance. -
It sets its
finalizerinstance attribute to amultiprocessing.util.Finalizeinstance which itself sets its_weakrefinstance attribute to aweakref.refinstance for closing at interpreter exit the ends of the pipes used by the parent process to communicate with the child process. In other words, it makes themultiprocessing.Processinstance hold a weak reference.
Thus if a
multiprocessing.Processinstance holds a reference to a startedmultiprocessing.Processinstance then it holds a weak reference (point 2), so starting it will fail since it will serialise (point 1) the weak reference and weak references are not serialisable:import multiprocessing if __name__ == '__main__': multiprocessing.set_start_method('spawn') # or 'forkserver' but not 'fork' process_a = multiprocessing.Process() process_b = multiprocessing.Process() process_b.foo = process_a process_a.start() # creates process_a._popen.finalizer._weakref process_b.start() # TypeError: cannot pickle 'weakref' objectA minimal Python program showing the serialisation issue:
import pickle import weakref pickle.dumps(weakref.ref(int)) # TypeError: cannot pickle 'weakref' objectReacted by Sergey Belov and Steven Bennett-
- added3.11only security fixesonly security fixesstdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-featureA feature request or enhancementA feature request or enhancement
on Mar 5, 2022 - changed the title
[-]A started multiprocessing.Process instance cannot be serialised[/-][+]Started multiprocessing.Process instances are unserialisable[/+]on Mar 5, 2022 - changed the title
[-]A started multiprocessing.Process instance cannot be serialised[/-][+]Started multiprocessing.Process instances are unserialisable[/+]on Mar 5, 2022 Up-voting this issue
Reacted by Sergey Belov, ussserrr and Adrien BourdeauxDo this bug have a workaround?
- added a commit that references this issue
on Feb 8, 2025
Metadata
Metadata
Assignees
Labels
Projects
- StatusShow more project fieldsNo status
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields: