|
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