If a subprocess gets killed by an OOM killer or whatever it should respawn and raise an InternalError

This commit is contained in:
Dave Halter
2018-01-02 00:56:22 +01:00
parent 7ff6871548
commit bcb3f02a01
2 changed files with 25 additions and 1 deletions

View File

@@ -10,6 +10,8 @@ goals:
import os import os
import sys import sys
import subprocess import subprocess
import socket
import errno
import weakref import weakref
import pickle import pickle
from functools import partial from functools import partial
@@ -192,7 +194,16 @@ class _CompiledSubprocess(object):
data = evaluator_id, function, args, kwargs data = evaluator_id, function, args, kwargs
pickle.dump(data, self._process.stdin, protocol=_PICKLE_PROTOCOL) pickle.dump(data, self._process.stdin, protocol=_PICKLE_PROTOCOL)
self._process.stdin.flush() try:
self._process.stdin.flush()
except socket.error as e:
# Once Python2 will be removed we can just use `BrokenPipeError`.
if e.errno != errno.EPIPE:
# Not a broken pipe
raise
self.kill()
raise InternalError("The subprocess was killed. Maybe out of memory?")
try: try:
is_exception, result = _pickle_load(self._process.stdout) is_exception, result = _pickle_load(self._process.stdout)
except EOFError: except EOFError:

View File

@@ -58,3 +58,16 @@ def test_error_in_environment(evaluator, Script):
# Jedi should still work. # Jedi should still work.
def_, = Script('str').goto_definitions() def_, = Script('str').goto_definitions()
assert def_.name == 'str' assert def_.name == 'str'
def test_killed_subprocess(evaluator, Script):
# Just kill the subprocess.
evaluator.compiled_subprocess._compiled_subprocess._process.kill()
# Since the process was terminated (and nobody knows about it) the first
# Jedi call fails.
with pytest.raises(jedi.InternalError):
Script('str').goto_definitions()
def_, = Script('str').goto_definitions()
# Jedi should now work again.
assert def_.name == 'str'