|
1 | 1 | """Main Nvim interface."""
|
2 | 2 | import os
|
3 | 3 | import sys
|
| 4 | +import threading |
4 | 5 | from functools import partial
|
5 | 6 | from traceback import format_stack
|
6 | 7 |
|
@@ -165,6 +166,15 @@ def request(self, name, *args, **kwargs):
|
165 | 166 | present and True, a asynchronous notification is sent instead. This
|
166 | 167 | will never block, and the return value or error is ignored.
|
167 | 168 | """
|
| 169 | + if (self._session._loop_thread is not None and |
| 170 | + threading.current_thread() != self._session._loop_thread): |
| 171 | + |
| 172 | + msg = ("request from non-main thread:\n{}\n" |
| 173 | + .format('\n'.join(format_stack(None, 5)[:-1]))) |
| 174 | + |
| 175 | + self.async_call(self._err_cb, msg) |
| 176 | + raise NvimError("request from non-main thread") |
| 177 | + |
168 | 178 | decode = kwargs.pop('decode', self._decode)
|
169 | 179 | args = walk(self._to_nvim, args)
|
170 | 180 | res = self._session.request(name, *args, **kwargs)
|
@@ -382,8 +392,18 @@ def out_write(self, msg, **kwargs):
|
382 | 392 |
|
383 | 393 | def err_write(self, msg, **kwargs):
|
384 | 394 | """Print `msg` as an error message."""
|
| 395 | + if self._thread_invalid(): |
| 396 | + # special case: if a non-main thread writes to stderr |
| 397 | + # i.e. due to an uncaught exception, pass it through |
| 398 | + # without raising an additional exception. |
| 399 | + self.async_call(self.err_write, msg, **kwargs) |
| 400 | + return |
385 | 401 | return self.request('nvim_err_write', msg, **kwargs)
|
386 | 402 |
|
| 403 | + def _thread_invalid(self): |
| 404 | + return (self._session._loop_thread is not None and |
| 405 | + threading.current_thread() != self._session._loop_thread) |
| 406 | + |
387 | 407 | def quit(self, quit_command='qa!'):
|
388 | 408 | """Send a quit command to Nvim.
|
389 | 409 |
|
|
0 commit comments