Process leak in nested context managers and exception handling
I tried to run pychroot 0.10.4 inside a context manager that mounts and umounts a filesystem using subprocess.run, and the result is odd: the unmount call fails because the filesystem is busy, and the context ending method is called multiple times. The same thing happens when calling pychroot inside an equivalent try/finally block.
My initial attempt was on a filesystem containing a valid OS tree, but this simpler example illustrates what's happening:
print("mount")
subprocess.run(["/bin/mount", "-ttmpfs", "none", "/mnt"])
try:
with contextlib.suppress(SystemExit), pychroot.Chroot("/mnt"):
pass
finally:
print("finally umount")
subprocess.run(["/bin/umount", "/mnt"])
The snippet above returns:
mount
finally umount
umount: /mnt: target is busy.
finally umount
Traceback (most recent call last):
File "./w2.py", line 16, in <module>
subprocess.run(["/bin/umount", "/mnt"])
File "/usr/lib/python3.8/subprocess.py", line 489, in run
with Popen(*popenargs, **kwargs) as process:
File "/usr/lib/python3.8/subprocess.py", line 854, in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
File "/usr/lib/python3.8/subprocess.py", line 1637, in _execute_child
self.pid = _posixsubprocess.fork_exec(
OSError: [Errno 12] Cannot allocate memory
finally umount
Note that the finally block runs three times and actually works in the third attempt, but the result is very ugly. Is that a known problem or expected behavior when using pychroot? Any advice on how to handle this situation?
The reason for the multiple finally handlers is that they're running in different processes, so exiting those that are not the one we were previously running seems to solve this issue. Thanks @cjp256 for investigating this!
Well, ideally this process leak should be handled internally by pychroot so I'll keep this open.