_input: reject attempts to call Helper from a non-main thread
This causes two threads to use the reactor at the same time, with horrible results. The _rlcompleter code currently violates this requirement, causing occasional failures if the messages arrive in just the wrong way (refs #280).
This commit is contained in:
parent
dce01174eb
commit
3847339f43
|
@ -1,4 +1,8 @@
|
||||||
from __future__ import print_function, absolute_import, unicode_literals
|
from __future__ import print_function, absolute_import, unicode_literals
|
||||||
|
# We use 'threading' defensively here, to detect if we're being called from a
|
||||||
|
# non-main thread. _rlcompleter.py is the only internal Wormhole code that
|
||||||
|
# deliberately creates a new thread.
|
||||||
|
import threading
|
||||||
from zope.interface import implementer
|
from zope.interface import implementer
|
||||||
from attr import attrs, attrib
|
from attr import attrs, attrib
|
||||||
from attr.validators import provides
|
from attr.validators import provides
|
||||||
|
@ -240,19 +244,28 @@ class Input(object):
|
||||||
class Helper(object):
|
class Helper(object):
|
||||||
_input = attrib()
|
_input = attrib()
|
||||||
|
|
||||||
|
def __attrs_post_init__(self):
|
||||||
|
self._main_thread = threading.current_thread().ident
|
||||||
|
|
||||||
def refresh_nameplates(self):
|
def refresh_nameplates(self):
|
||||||
|
assert threading.current_thread().ident == self._main_thread
|
||||||
self._input.refresh_nameplates()
|
self._input.refresh_nameplates()
|
||||||
def get_nameplate_completions(self, prefix):
|
def get_nameplate_completions(self, prefix):
|
||||||
|
assert threading.current_thread().ident == self._main_thread
|
||||||
return self._input.get_nameplate_completions(prefix)
|
return self._input.get_nameplate_completions(prefix)
|
||||||
def choose_nameplate(self, nameplate):
|
def choose_nameplate(self, nameplate):
|
||||||
|
assert threading.current_thread().ident == self._main_thread
|
||||||
self._input._debug("I.choose_nameplate")
|
self._input._debug("I.choose_nameplate")
|
||||||
self._input.choose_nameplate(nameplate)
|
self._input.choose_nameplate(nameplate)
|
||||||
self._input._debug("I.choose_nameplate finished")
|
self._input._debug("I.choose_nameplate finished")
|
||||||
def when_wordlist_is_available(self):
|
def when_wordlist_is_available(self):
|
||||||
|
assert threading.current_thread().ident == self._main_thread
|
||||||
return self._input.when_wordlist_is_available()
|
return self._input.when_wordlist_is_available()
|
||||||
def get_word_completions(self, prefix):
|
def get_word_completions(self, prefix):
|
||||||
|
assert threading.current_thread().ident == self._main_thread
|
||||||
return self._input.get_word_completions(prefix)
|
return self._input.get_word_completions(prefix)
|
||||||
def choose_words(self, words):
|
def choose_words(self, words):
|
||||||
|
assert threading.current_thread().ident == self._main_thread
|
||||||
self._input._debug("I.choose_words")
|
self._input._debug("I.choose_words")
|
||||||
self._input.choose_words(words)
|
self._input.choose_words(words)
|
||||||
self._input._debug("I.choose_words finished")
|
self._input._debug("I.choose_words finished")
|
||||||
|
|
Loading…
Reference in New Issue
Block a user