diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2015-03-06 22:35:27 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2015-03-06 22:35:27 (GMT) |
commit | 4a7cc8847276df27c8f52987cda619ca279687c2 (patch) | |
tree | 9bc7cfee8bf0fc27dc7f14ba4853c935d9f21b4c /Python | |
parent | d81431f587e9eab67db683908548b0ad46847b38 (diff) | |
download | cpython-4a7cc8847276df27c8f52987cda619ca279687c2.zip cpython-4a7cc8847276df27c8f52987cda619ca279687c2.tar.gz cpython-4a7cc8847276df27c8f52987cda619ca279687c2.tar.bz2 |
Issue #23571: PyObject_Call(), PyCFunction_Call() and call_function() now
raise a SystemError if a function returns a result and raises an exception.
The SystemError is chained to the previous exception.
Refactor also PyObject_Call() and PyCFunction_Call() to make them more readable.
Remove some checks which became useless (duplicate checks).
Change reviewed by Serhiy Storchaka.
Diffstat (limited to 'Python')
-rw-r--r-- | Python/ceval.c | 30 |
1 files changed, 11 insertions, 19 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index 5cefdcf..1c6089d 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3192,8 +3192,7 @@ fast_block_end: if (why != WHY_RETURN) retval = NULL; - assert((retval != NULL && !PyErr_Occurred()) - || (retval == NULL && PyErr_Occurred())); + assert((retval != NULL) ^ (PyErr_Occurred() != NULL)); fast_yield: if (co->co_flags & CO_GENERATOR) { @@ -3254,7 +3253,7 @@ exit_eval_frame: f->f_executing = 0; tstate->frame = f->f_back; - return retval; + return _Py_CheckFunctionResult(retval, "PyEval_EvalFrameEx"); } static void @@ -4119,13 +4118,6 @@ PyEval_CallObjectWithKeywords(PyObject *func, PyObject *arg, PyObject *kw) { PyObject *result; -#ifdef Py_DEBUG - /* PyEval_CallObjectWithKeywords() must not be called with an exception - set, because it may clear it (directly or indirectly) - and so the caller looses its exception */ - assert(!PyErr_Occurred()); -#endif - if (arg == NULL) { arg = PyTuple_New(0); if (arg == NULL) @@ -4149,8 +4141,6 @@ PyEval_CallObjectWithKeywords(PyObject *func, PyObject *arg, PyObject *kw) result = PyObject_Call(func, arg, kw); Py_DECREF(arg); - assert((result != NULL && !PyErr_Occurred()) - || (result == NULL && PyErr_Occurred())); return result; } @@ -4253,11 +4243,15 @@ call_function(PyObject ***pp_stack, int oparg PyObject *self = PyCFunction_GET_SELF(func); if (flags & METH_NOARGS && na == 0) { C_TRACE(x, (*meth)(self,NULL)); + + x = _Py_CheckFunctionResult(x, "call_function"); } else if (flags & METH_O && na == 1) { PyObject *arg = EXT_POP(*pp_stack); C_TRACE(x, (*meth)(self,arg)); Py_DECREF(arg); + + x = _Py_CheckFunctionResult(x, "call_function"); } else { err_args(func, flags, na); @@ -4277,7 +4271,8 @@ call_function(PyObject ***pp_stack, int oparg x = NULL; } } - } else { + } + else { if (PyMethod_Check(func) && PyMethod_GET_SELF(func) != NULL) { /* optimize access to bound methods */ PyObject *self = PyMethod_GET_SELF(func); @@ -4299,9 +4294,9 @@ call_function(PyObject ***pp_stack, int oparg x = do_call(func, pp_stack, na, nk); READ_TIMESTAMP(*pintr1); Py_DECREF(func); + + assert((x != NULL) ^ (PyErr_Occurred() != NULL)); } - assert((x != NULL && !PyErr_Occurred()) - || (x == NULL && PyErr_Occurred())); /* Clear the stack of the function object. Also removes the arguments in case they weren't consumed already @@ -4313,8 +4308,7 @@ call_function(PyObject ***pp_stack, int oparg PCALL(PCALL_POP); } - assert((x != NULL && !PyErr_Occurred()) - || (x == NULL && PyErr_Occurred())); + assert((x != NULL) ^ (PyErr_Occurred() != NULL)); return x; } @@ -4601,8 +4595,6 @@ ext_call_fail: Py_XDECREF(callargs); Py_XDECREF(kwdict); Py_XDECREF(stararg); - assert((result != NULL && !PyErr_Occurred()) - || (result == NULL && PyErr_Occurred())); return result; } |