From 25c0ce791cc1ac10170e6242c3076ee84b42dedb Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Mon, 27 Apr 2020 00:16:15 +0200 Subject: Fix the memoryview error exit case (don't need the GIL for it) and add assertions that success and error exit paths end up with the same GIL state. --- Cython/Compiler/Nodes.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index bef5db2e8..f7020ab51 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -2029,7 +2029,6 @@ class FuncDefNode(StatNode, BlockNode): if return_type.is_memoryviewslice: from . import MemoryView - assure_gil('error') MemoryView.put_init_entry(Naming.retval_cname, code) err_val = Naming.retval_cname else: @@ -2066,7 +2065,8 @@ class FuncDefNode(StatNode, BlockNode): # jump past it if we have an error. The if-test below determine # whether this section is used. if buffers_present or is_getbuffer_slot or return_type.is_memoryviewslice: - # In all three cases, we already called assure_gil('error') and own the GIL. + # In the buffer cases, we already called assure_gil('error') and own the GIL. + assert gil_owned['error'] or return_type.is_memoryviewslice code.put_goto(code.return_from_error_cleanup_label) else: # align error and success GIL state @@ -2078,6 +2078,8 @@ class FuncDefNode(StatNode, BlockNode): # ----- Non-error return cleanup code.put_label(code.return_label) + assert gil_owned['error'] == gil_owned['success'], "%s != %s" % (gil_owned['error'], gil_owned['success']) + for entry in used_buffer_entries: assure_gil('success') Buffer.put_release_buffer_code(code, entry) @@ -2102,11 +2104,12 @@ class FuncDefNode(StatNode, BlockNode): '}') # ----- Return cleanup for both error and no-error return - code.put_label(code.return_from_error_cleanup_label) - # If we jumped here from the error path, then we own the GIL. - # If we came through the success path, we took the same decisions as for jumping. - # If we came through the error path and did not jump, we aligned both paths above. - # In the end, all three paths are aligned from this point on. + if code.label_used(code.return_from_error_cleanup_label): + # If we came through the success path, then we took the same GIL decisions as for jumping here. + # If we came through the error path and did not jump, then we aligned both paths above. + # In the end, all paths are aligned from this point on. + assert gil_owned['error'] == gil_owned['success'], "%s != %s" % (gil_owned['error'], gil_owned['success']) + code.put_label(code.return_from_error_cleanup_label) for entry in lenv.var_entries: if not entry.used or entry.in_closure: -- cgit v1.2.1