diff options
author | Stefan Behnel <stefan_ml@behnel.de> | 2018-09-19 22:31:19 +0200 |
---|---|---|
committer | Stefan Behnel <stefan_ml@behnel.de> | 2018-09-19 22:31:19 +0200 |
commit | 7b4079c50d88f5ce1cf3cc55a6f46cd6e35cbda4 (patch) | |
tree | 342f4335ea8ba71cfa358778ca14a63d552fa4b3 /Cython/Compiler/ParseTreeTransforms.py | |
parent | 04114b9b927c22b7cf0510f7b1587b691acb14bc (diff) | |
download | cython-7b4079c50d88f5ce1cf3cc55a6f46cd6e35cbda4.tar.gz |
Check some child nodes against the correct nogil context when they are actually being evaluated in the outer scope (e.g default arguments or annotations of a nogil function).
Diffstat (limited to 'Cython/Compiler/ParseTreeTransforms.py')
-rw-r--r-- | Cython/Compiler/ParseTreeTransforms.py | 36 |
1 files changed, 24 insertions, 12 deletions
diff --git a/Cython/Compiler/ParseTreeTransforms.py b/Cython/Compiler/ParseTreeTransforms.py index 6d56e5aac..154f341ae 100644 --- a/Cython/Compiler/ParseTreeTransforms.py +++ b/Cython/Compiler/ParseTreeTransforms.py @@ -2861,24 +2861,33 @@ class GilCheck(VisitorTransform): self.nogil_declarator_only = False return super(GilCheck, self).__call__(root) + def _visit_scoped_children(self, node, gil_state): + was_nogil = self.nogil + outer_attrs = node.outer_attrs + if outer_attrs and len(self.env_stack) > 1: + self.nogil = self.env_stack[-2].nogil + self.visitchildren(node, outer_attrs) + + self.nogil = gil_state + self.visitchildren(node, exclude=outer_attrs) + self.nogil = was_nogil + def visit_FuncDefNode(self, node): self.env_stack.append(node.local_scope) - was_nogil = self.nogil - self.nogil = node.local_scope.nogil + inner_nogil = node.local_scope.nogil - if self.nogil: + if inner_nogil: self.nogil_declarator_only = True - if self.nogil and node.nogil_check: + if inner_nogil and node.nogil_check: node.nogil_check(node.local_scope) - self.visitchildren(node) + self._visit_scoped_children(node, inner_nogil) # This cannot be nested, so it doesn't need backup/restore self.nogil_declarator_only = False self.env_stack.pop() - self.nogil = was_nogil return node def visit_GILStatNode(self, node): @@ -2886,9 +2895,9 @@ class GilCheck(VisitorTransform): node.nogil_check() was_nogil = self.nogil - self.nogil = (node.state == 'nogil') + is_nogil = (node.state == 'nogil') - if was_nogil == self.nogil and not self.nogil_declarator_only: + if was_nogil == is_nogil and not self.nogil_declarator_only: if not was_nogil: error(node.pos, "Trying to acquire the GIL while it is " "already held.") @@ -2901,8 +2910,7 @@ class GilCheck(VisitorTransform): # which is wrapped in a StatListNode. Just unpack that. node.finally_clause, = node.finally_clause.stats - self.visitchildren(node) - self.nogil = was_nogil + self._visit_scoped_children(node, is_nogil) return node def visit_ParallelRangeNode(self, node): @@ -2949,8 +2957,12 @@ class GilCheck(VisitorTransform): def visit_Node(self, node): if self.env_stack and self.nogil and node.nogil_check: node.nogil_check(self.env_stack[-1]) - self.visitchildren(node) - node.in_nogil_context = self.nogil + if node.outer_attrs: + self._visit_scoped_children(node, self.nogil) + else: + self.visitchildren(node) + if self.nogil: + node.in_nogil_context = True return node |