Skip to content

Instantly share code, notes, and snippets.

@maxfischer2781
Created November 27, 2018 16:59
Show Gist options
  • Select an option

  • Save maxfischer2781/bb47e00f5d11453fd7249846184fb29b to your computer and use it in GitHub Desktop.

Select an option

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
Copy Markdown
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