-
Notifications
You must be signed in to change notification settings - Fork 38
Description
Hello :)
Thank you for maintaining this library!
Starting from version "3.2.0", the special "code" attribute of the SystemExit exception is not preserved after unpickling.
Raised from a sub-process, this can lead to a wrong exit code of a whole program.
Example (Ubuntu24.04, Python 3.12):
cat test_exit_code_multiprocessing.py
from concurrent.futures import ProcessPoolExecutor
import tblib.pickling_support
def _function_raising_exit(_x: int) -> None:
raise SystemExit(42)
def test_exit_code():
tblib.pickling_support.install()
with ProcessPoolExecutor() as pool:
return list(pool.map(_function_raising_exit, [1]))
if __name__ == "__main__":
test_exit_code()
python test_exit_code_multiprocessing.py
echo $? --> is 0 instead of 42
For completeness, here is also a test which checks this behavior (similar to test_oserror from the repo):
def test_systemexit_error(clear_dispatch_table):
try:
raise SystemExit(42)
except SystemExit as e:
exc = e
tblib.pickling_support.install(exc)
exc = pickle.loads(pickle.dumps(exc))
assert isinstance(exc, SystemExit)
assert exc.code == 42
assert exc.__traceback__ is not None
Note: There are also further builtin exceptions with special attributes which are also not preserved after unpickling.
I created here a draft PR with a few test cases and a proposal on how to fix it:
#86
Not sure if I overlooked some corner cases, but I hope it helps to find the best solution on how to fix it =)