From 7b2b56ab8fcd72f4217fa28be4da4c139813a06a Mon Sep 17 00:00:00 2001 From: Chris Burr Date: Mon, 30 Nov 2020 14:21:06 +0100 Subject: [PATCH 1/2] Implement Py_Exit --HG-- branch : implement-pyexit --- pypy/module/cpyext/pythonrun.py | 7 +++++++ pypy/module/cpyext/stubs.py | 6 ------ pypy/module/cpyext/test/test_cpyext.py | 4 ++++ 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/pypy/module/cpyext/pythonrun.py b/pypy/module/cpyext/pythonrun.py index 19fe20af86..605eb8ed41 100644 --- a/pypy/module/cpyext/pythonrun.py +++ b/pypy/module/cpyext/pythonrun.py @@ -1,4 +1,5 @@ from rpython.rtyper.lltypesystem import rffi, lltype +from pypy.interpreter.error import OperationError from pypy.module.cpyext.api import cpython_api, CANNOT_FAIL from pypy.module.cpyext.state import State @@ -46,3 +47,9 @@ def Py_AtExit(space, func_ptr): except ValueError: return -1 return 0 + +@cpython_api([rffi.INT_real], lltype.Void) +def Py_Exit(space, status): + """Exit the current process. This calls Py_Finalize() and then calls the + standard C library function exit(status).""" + raise OperationError(space.w_SystemExit, space.newint(status)) diff --git a/pypy/module/cpyext/stubs.py b/pypy/module/cpyext/stubs.py index 3dba4ffa8a..431350c78e 100644 --- a/pypy/module/cpyext/stubs.py +++ b/pypy/module/cpyext/stubs.py @@ -1344,12 +1344,6 @@ def PySys_SetPath(space, path): (: on Unix, ; on Windows).""" raise NotImplementedError -@cpython_api([rffi.INT_real], lltype.Void) -def Py_Exit(space, status): - """Exit the current process. This calls Py_Finalize() and then calls the - standard C library function exit(status).""" - raise NotImplementedError - @cpython_api([], rffi.INT_real, error=CANNOT_FAIL) def PyTuple_ClearFreeList(space): """Clear the free list. Return the total number of freed items. diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py index 997357716a..a25eaa5937 100644 --- a/pypy/module/cpyext/test/test_cpyext.py +++ b/pypy/module/cpyext/test/test_cpyext.py @@ -937,3 +937,7 @@ class AppTestCpythonExtension(AppTestCpythonExtensionBase): ''' ), ]) + + def test_call_py_exit(self): + exc = raises(SystemExit, self.import_module, name="foo", init="Py_Exit(42);") + assert exc.value.code == 42 -- GitLab From 4e098914fe19f1e48fdeb278ba16afa36a074836 Mon Sep 17 00:00:00 2001 From: Matti Picus Date: Tue, 8 Dec 2020 08:38:36 +0200 Subject: [PATCH 2/2] fix test, allow exception to percolate out --HG-- branch : implement-pyexit --- pypy/module/cpyext/api.py | 6 ++++++ pypy/module/cpyext/pythonrun.py | 2 +- pypy/module/cpyext/test/test_cpyext.py | 19 +++++++++++++++++-- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py index 84ec9ed150..9c8f82fa08 100644 --- a/pypy/module/cpyext/api.py +++ b/pypy/module/cpyext/api.py @@ -1028,6 +1028,8 @@ def make_wrapper_second_level(space, argtypesw, restype, except OperationError as e: failed = True state.set_exception(e) + if e.match(space, space.w_SystemExit): + raise e except BaseException as e: failed = True if not we_are_translated(): @@ -1068,6 +1070,10 @@ def make_wrapper_second_level(space, argtypesw, restype, elif restype is not lltype.Void: retval = rffi.cast(restype, result) + except OperationError as e: + _restore_gil_state(pygilstate_release, gilstate, gil_release, _gil_auto) + raise e + return fatal_value except Exception as e: unexpected_exception(pname, e, tb) _restore_gil_state(pygilstate_release, gilstate, gil_release, _gil_auto) diff --git a/pypy/module/cpyext/pythonrun.py b/pypy/module/cpyext/pythonrun.py index 605eb8ed41..317e6cf496 100644 --- a/pypy/module/cpyext/pythonrun.py +++ b/pypy/module/cpyext/pythonrun.py @@ -48,7 +48,7 @@ def Py_AtExit(space, func_ptr): return -1 return 0 -@cpython_api([rffi.INT_real], lltype.Void) +@cpython_api([rffi.INT_real], lltype.Void, error=-1) def Py_Exit(space, status): """Exit the current process. This calls Py_Finalize() and then calls the standard C library function exit(status).""" diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py index a25eaa5937..317d3ba5e7 100644 --- a/pypy/module/cpyext/test/test_cpyext.py +++ b/pypy/module/cpyext/test/test_cpyext.py @@ -939,5 +939,20 @@ class AppTestCpythonExtension(AppTestCpythonExtensionBase): ]) def test_call_py_exit(self): - exc = raises(SystemExit, self.import_module, name="foo", init="Py_Exit(42);") - assert exc.value.code == 42 + try: + import posix + except ImportError: + skip("requires posix.fork() to test") + mod = self.import_extension('foo', [ + ('exit', 'METH_NOARGS', + ''' + Py_Exit(42); + ''')]) + # run the function in a thread + pid = posix.fork() + if pid == 0: + mod.exit() + pid, status = posix.waitpid(pid, 0) + print pid, status + assert posix.WIFEXITED(status) + assert posix.WEXITSTATUS(status) == 42 -- GitLab