def test_exit_with_parent_process_died( language_server_process: IRobocodeLanguageServerClient, language_server_io, ws_root_path, ): """ :note: Only check with the language_server_io (because that's in another process). """ from robocode_ls_core.subprocess_wrapper import subprocess from robocode_ls_core.basic import is_process_alive from robocode_ls_core.basic import kill_process_and_subprocesses from robocode_ls_core.unittest_tools.fixtures import wait_for_test_condition language_server = language_server_io dummy_process = subprocess.Popen( [sys.executable, "-c", "import time;time.sleep(10000)"]) language_server.initialize(ws_root_path, process_id=dummy_process.pid) assert is_process_alive(dummy_process.pid) assert is_process_alive(language_server_process.pid) kill_process_and_subprocesses(dummy_process.pid) wait_for_test_condition(lambda: not is_process_alive(dummy_process.pid)) wait_for_test_condition( lambda: not is_process_alive(language_server_process.pid)) language_server_io.require_exit_messages = False
def _dispose_server_process(self): with self._server_lock: try: log.debug("Dispose server process.") if self._server_process is not None: if is_process_alive(self._server_process.pid): kill_process_and_subprocesses(self._server_process.pid) finally: self._server_process = None self._server_api = None self._used_environ = None self._used_python_executable = None
def _notify_on_exited_pid(on_exit, pid): try: from robocode_ls_core.basic import is_process_alive import time log.debug("Waiting for pid to exit (_notify_on_exited_pid).") while True: if not is_process_alive(pid): break time.sleep(0.5) log.debug("pid exited (_notify_on_exited_pid).") on_exit() except: log.exception("Error")
def _get_server_api(self): with self._server_lock: server_process = self._server_process if server_process is not None: # If someone killed it, dispose of internal references # and create a new process. if not is_process_alive(server_process.pid): server_process = None self._dispose_server_process() if server_process is None: try: from robotframework_ls.options import Setup from robotframework_ls.server_api.client import ( RobotFrameworkApiClient, ) from robotframework_ls.server_api.server__main__ import ( start_server_process, ) from robocode_ls_core.jsonrpc.streams import ( JsonRpcStreamWriter, JsonRpcStreamReader, ) args = [] if Setup.options.verbose: args.append("-" + "v" * int(Setup.options.verbose)) if Setup.options.log_file: log_id = _next_id() # i.e.: use a log id in case we create more than one in the # same session. if log_id == 0: args.append( "--log-file=" + Setup.options.log_file + self._log_extension ) else: args.append( "--log-file=" + Setup.options.log_file + (".%s" % (log_id,)) + self._log_extension ) python_exe = self._get_python_executable() environ = self._get_environ() self._used_python_executable = python_exe self._used_environ = environ server_process = start_server_process( args=args, python_exe=python_exe, env=environ ) self._server_process = server_process write_to = server_process.stdin read_from = server_process.stdout w = JsonRpcStreamWriter(write_to, sort_keys=True) r = JsonRpcStreamReader(read_from) api = self._server_api = RobotFrameworkApiClient( w, r, server_process ) api.initialize( process_id=os.getpid(), root_uri=self.workspace.root_uri, workspace_folders=list( {"uri": folder.uri, "name": folder.name} for folder in list(self.workspace.folders.values()) ), ) config = self._config if config is not None: api.forward( "workspace/didChangeConfiguration", {"settings": config.get_full_settings()}, ) # Open existing documents in the API. for document in self.workspace.iter_documents(): try: source = document.source except Exception: source = None api.forward( "textDocument/didOpen", { "textDocument": { "uri": document.uri, "version": document.version, "text": source, } }, ) except Exception as e: if server_process is None: log.exception( "Error starting robotframework server api (server_process=None)." ) else: exitcode = server_process.poll() if exitcode is not None: # Note: only read() if the process exited. log.exception( "Error starting robotframework server api. Exit code: %s Base exception: %s. Stderr: %s" % (exitcode, e, server_process.stderr.read()) ) else: log.exception( "Error (%s) starting robotframework server api (still running). Base exception: %s." % (exitcode, e) ) self._dispose_server_process() finally: if server_process is not None: log.debug( "Server api (%s) created pid: %s" % (self, server_process.pid) ) return self._server_api