Skip to content

Instantly share code, notes, and snippets.

@maxfischer2781
Created November 27, 2018 16:59
Show Gist options
  • Save maxfischer2781/bb47e00f5d11453fd7249846184fb29b to your computer and use it in GitHub Desktop.
Save maxfischer2781/bb47e00f5d11453fd7249846184fb29b to your computer and use it in GitHub Desktop.
MVCE for early finalisation using Python multiprocessing and spawn/fork method
import os
import sys
import time
import multiprocessing
def print_pid(*args, **kwargs):
print('[%s]' % os.getpid(), *args, **kwargs)
class Finalisable:
def __init__(self, name):
self.name = name
def __repr__(self):
return '<Finalisable object %s at 0x%x>' % (getattr(self, 'name', 'unknown'), id(self))
def __del__(self):
print_pid('finalising', self)
def drop_late():
payload = Finalisable('late')
child = multiprocessing.Process(target=print_pid, args=(payload,))
child.start()
child.join()
del payload
def drop_early():
payload = Finalisable('early')
child = multiprocessing.Process(target=print_pid, args=('child sees', payload,))
print('drop')
del payload
print('start')
child.start()
child.join()
def drop_early_shared():
payload = Finalisable(multiprocessing.Value('i', 65))
child = multiprocessing.Process(target=print_pid, args=('child sees', payload,))
print('drop')
del payload
print('start')
child.start()
child.join()
if __name__ == '__main__':
method = sys.argv[1] if len(sys.argv) > 1 else None
multiprocessing.set_start_method(method)
for test in (drop_late, drop_early, drop_early_shared):
print('### test', test.__name__, 'in', os.getpid(), 'method:', method)
test()
print('### done', '\n'*2)
@maxfischer2781
Copy link
Author

Using either fork, forkserver or spawn shows the payload passed as args to Process is finalised too early (CPython 3.7.0, MacOS). In the case of spawn, a multiprocessing.Value will incorrectly drop its resources as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment