[pypy-commit] pypy default: Issue #1194
arigo
noreply at buildbot.pypy.org
Mon May 4 13:16:17 CEST 2015
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r77036:0ab71c680c9f
Date: 2015-05-04 13:16 +0200
http://bitbucket.org/pypy/pypy/changeset/0ab71c680c9f/
Log: Issue #1194
Not fully tested: if a ctypes callback raises SystemExit, call the C
function exit() immediately. I have no clue why, but some people
depend on that.
diff --git a/lib_pypy/_ctypes/function.py b/lib_pypy/_ctypes/function.py
--- a/lib_pypy/_ctypes/function.py
+++ b/lib_pypy/_ctypes/function.py
@@ -308,6 +308,8 @@
res = self.callable(*newargs)
except:
exc_info = sys.exc_info()
+ if issubclass(exc_info[0], SystemExit):
+ exc_info = handle_system_exit(exc_info)
traceback.print_tb(exc_info[2], file=sys.stderr)
print >>sys.stderr, "%s: %s" % (exc_info[0].__name__, exc_info[1])
return 0
@@ -715,3 +717,26 @@
make_fastpath_subclass.memo[CFuncPtr] = CFuncPtrFast
return CFuncPtrFast
make_fastpath_subclass.memo = {}
+
+
+def handle_system_exit(exc_info):
+ # issue #1194: if we get SystemExit here, then exit the interpreter.
+ # Highly obscure imho but some people seem to depend on it.
+ try:
+ if sys.flags.inspect:
+ return exc_info # Don't exit if -i flag was given.
+
+ code = exc_info[1].code
+ if isinstance(code, int):
+ exitcode = code
+ else:
+ f = getattr(sys, 'stderr', None)
+ if f is None:
+ f = sys.__stderr__
+ print >> f, code
+ exitcode = 1
+
+ _rawffi.exit(exitcode)
+
+ except:
+ return sys.exc_info()
diff --git a/pypy/module/_rawffi/__init__.py b/pypy/module/_rawffi/__init__.py
--- a/pypy/module/_rawffi/__init__.py
+++ b/pypy/module/_rawffi/__init__.py
@@ -29,6 +29,7 @@
'get_last_error' : 'interp_rawffi.get_last_error',
'set_last_error' : 'interp_rawffi.set_last_error',
'SegfaultException' : 'space.new_exception_class("_rawffi.SegfaultException")',
+ 'exit' : 'interp_exit.exit',
}
appleveldefs = {
diff --git a/pypy/module/_rawffi/interp_exit.py b/pypy/module/_rawffi/interp_exit.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_rawffi/interp_exit.py
@@ -0,0 +1,9 @@
+from pypy.interpreter.gateway import unwrap_spec
+from rpython.rtyper.lltypesystem import lltype, rffi
+
+
+ll_exit = rffi.llexternal('exit', [rffi.INT], lltype.Void, _nowrapper=True)
+
+ at unwrap_spec(status="c_int")
+def exit(space, status):
+ ll_exit(rffi.cast(rffi.INT, status))
diff --git a/pypy/module/_rawffi/test/test_exit.py b/pypy/module/_rawffi/test/test_exit.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_rawffi/test/test_exit.py
@@ -0,0 +1,15 @@
+
+class AppTestFfi:
+ spaceconfig = dict(usemodules=['_rawffi', 'posix'])
+
+ def test_exit(self):
+ import posix, _rawffi
+ if not hasattr(posix, 'fork'):
+ skip("requires fork() to test")
+ #
+ pid = posix.fork()
+ if pid == 0:
+ _rawffi.exit(5) # in the child
+ pid, status = posix.waitpid(pid, 0)
+ assert posix.WIFEXITED(status)
+ assert posix.WEXITSTATUS(status) == 5
More information about the pypy-commit
mailing list