File tree Expand file tree Collapse file tree 1 file changed +15
-5
lines changed
Expand file tree Collapse file tree 1 file changed +15
-5
lines changed Original file line number Diff line number Diff line change 1313_L = threading .local ()
1414
1515_mainthread_stack = []
16+ _mainthread_lock = threading .RLock ()
1617def _getstack ():
1718 if threading .current_thread () is threading .main_thread ():
1819 return _mainthread_stack
@@ -22,7 +23,8 @@ def _getstack():
2223 #
2324 # TODO: preferable to use the parent thread's current stack, but difficult to get.
2425 # Could monkey-patch threading.Thread.__init__ to record this information in self...
25- _L ._stack = _mainthread_stack .copy ()
26+ with _mainthread_lock :
27+ _L ._stack = _mainthread_stack .copy ()
2628 return _L ._stack
2729
2830def _getobservers ():
@@ -168,10 +170,18 @@ def update(self, **bindings):
168170 caution applies. Use carefully, if at all.
169171 """
170172 # validate, and resolve scopes (let AttributeError propagate)
171- scopes = {k : self ._resolve (k ) for k in bindings }
172- for k , v in bindings .items ():
173- scope = scopes [k ]
174- scope [k ] = v
173+ def doit ():
174+ scopes = {k : self ._resolve (k ) for k in bindings }
175+ for k , v in bindings .items ():
176+ scope = scopes [k ]
177+ scope [k ] = v
178+ # If we're the main thread, any new threads spawned will copy our scope stack
179+ # in whatever state it happens to be in. Make the update atomic.
180+ if threading .current_thread () is threading .main_thread ():
181+ with _mainthread_lock :
182+ doit ()
183+ else :
184+ doit ()
175185
176186 # membership test (in, not in)
177187 def __contains__ (self , name ):
You can’t perform that action at this time.
0 commit comments