def test_exit_with_parent_process_died( language_server_process: IRobocorpLanguageServerClient, language_server_io, ws_root_path, initialization_options, ): """ :note: Only check with the language_server_io (because that's in another process). """ from robocorp_ls_core.subprocess_wrapper import subprocess from robocorp_ls_core.basic import is_process_alive from robocorp_ls_core.basic import kill_process_and_subprocesses from robocorp_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, initialization_options=initialization_options, ) 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 test_system_mutex_locked_on_subprocess(): import sys from robocorp_ls_core.subprocess_wrapper import subprocess from robocorp_ls_core.basic import kill_process_and_subprocesses from robocorp_ls_core.system_mutex import SystemMutex from robocorp_ls_core.basic import wait_for_condition code = ''' import sys import time print('initialized') from robocorp_ls_core.system_mutex import SystemMutex mutex = SystemMutex('test_system_mutex_locked_on_subprocess') assert mutex.get_mutex_aquired() print('acquired mutex') sys.stdout.flush() time.sleep(30) ''' p = subprocess.Popen([sys.executable, '-c', code], stdout=subprocess.PIPE, stdin=subprocess.PIPE) wait_for_condition(lambda: p.stdout.readline().strip() == b'acquired mutex') mutex = SystemMutex('test_system_mutex_locked_on_subprocess') assert not mutex.get_mutex_aquired() # i.e.: check that we can acquire the mutex if the related process dies. kill_process_and_subprocesses(p.pid) def acquire_mutex(): mutex = SystemMutex('test_system_mutex_locked_on_subprocess') return mutex.get_mutex_aquired() wait_for_condition(acquire_mutex, timeout=5)
def disconnect(self, disconnect_request): from robocorp_ls_core.basic import kill_process_and_subprocesses if self._popen is not None: if self._popen.returncode is None: kill_process_and_subprocesses(self._popen.pid) else: kill_process_and_subprocesses(self._track_process_pid)
def test_restart_when_api_dies(language_server_tcp, ws_root_path, data_regression): from robocorp_ls_core.basic import kill_process_and_subprocesses from robocorp_ls_core import basic from robotframework_ls.server_manager import _ServerApi import time # Check just with language_server_tcp as it's easier to kill the subprocess. server_apis = set() server_processes = set() def on_get_robotframework_api_client(server_api): if (server_api.robot_framework_language_server is language_server_tcp.language_server_instance): server_apis.add(server_api) server_processes.add(server_api._server_process.pid) with basic.after(_ServerApi, "get_robotframework_api_client", on_get_robotframework_api_client): language_server_tcp.initialize(ws_root_path, process_id=os.getpid()) import robot env = { "PYTHONPATH": os.path.dirname(os.path.dirname(os.path.abspath(robot.__file__))) } language_server_tcp.settings({ "settings": { "robot.python.env": env, "robot.lint.robocop.enabled": True } }) processes_per_api = 3 check_diagnostics(language_server_tcp, data_regression) assert len(server_apis) == processes_per_api assert len(server_processes) == processes_per_api check_diagnostics(language_server_tcp, data_regression) assert len(server_apis) == processes_per_api assert len(server_processes) == processes_per_api log.info("Killing server api process.") for pid in server_processes: kill_process_and_subprocesses(pid) # Just make sure the connection is properly dropped before re-requesting. time.sleep(0.2) check_diagnostics(language_server_tcp, data_regression) assert len(server_processes) == processes_per_api * 2 assert len(server_apis) == processes_per_api
def _dispose_server_process(self): self._check_in_main_thread() 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._robotframework_api_client = None self._used_environ = None self._used_python_executable = None
def _dispose_server_process(self): from robocorp_ls_core.basic import kill_process_and_subprocesses self._check_thread() 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._locators_api_client = None
def _dispose_server_process(self): from robocorp_ls_core.basic import kill_process_and_subprocesses with self._lock_api_client: 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._disposed = True self._server_process = None self._rf_interpreter_api_client = None
def server_process(tmpdir, on_timeout, remote_fs_observer): from robocorp_ls_core.basic import kill_process_and_subprocesses from robotframework_ls.server_api.server__main__ import start_server_process log_file = str(tmpdir.join("robotframework_api_tests.log")) import robot env = { "PYTHONPATH": os.path.dirname(os.path.dirname(os.path.abspath(robot.__file__))) } language_server_api_process = start_server_process( args=[ "-vv", "--log-file=%s" % log_file, f"--remote-fs-observer-port={remote_fs_observer.port}", ], env=env, ) returncode = language_server_api_process.poll() assert returncode is None def write_on_finish(): import sys dirname = os.path.dirname(log_file) for f in os.listdir(dirname): if f.startswith("robotframework_api_tests") and f.endswith(".log"): full = os.path.join(dirname, f) sys.stderr.write("\n--- %s contents:\n" % (full, )) with open(full, "r") as stream: sys.stderr.write(stream.read()) on_timeout.add(write_on_finish) yield language_server_api_process on_timeout.remove(write_on_finish) returncode = language_server_api_process.poll() if returncode is None: kill_process_and_subprocesses(language_server_api_process.pid) write_on_finish()
def dap_process(dap_log_file, dap_process_stderr_file): from robotframework_debug_adapter import __main__ from robocorp_ls_core.basic import kill_process_and_subprocesses env = os.environ.copy() env["ROBOTFRAMEWORK_DAP_LOG_LEVEL"] = "3" env["ROBOTFRAMEWORK_DAP_LOG_FILENAME"] = dap_log_file dap_process = subprocess.Popen( [sys.executable, "-u", __main__.__file__], stdout=subprocess.PIPE, stderr=dap_process_stderr_file, stdin=subprocess.PIPE, env=env, ) assert dap_process.returncode is None yield dap_process if dap_process.returncode is None: kill_process_and_subprocesses(dap_process.pid)
def create_language_server_process(log_file, __main__module): from robocorp_ls_core.basic import kill_process_and_subprocesses from robocorp_ls_core.subprocess_wrapper import subprocess language_server_process = subprocess.Popen( [ sys.executable, "-u", __main__module.__file__, "-vv", "--log-file=%s" % log_file, ], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, ) stderr = language_server_process.stderr buf = [] t = threading.Thread(target=_stderr_reader, args=(stderr, buf)) t.name = "Stderr reader" t.start() returncode = language_server_process.poll() assert returncode is None try: yield language_server_process finally: t.join(1) stderr_contents = b"".join(buf).decode("utf-8") if stderr_contents: sys.stderr.write( f"Found stderr contents: >>\n{stderr_contents}\n<<") returncode = language_server_process.poll() if returncode is None: kill_process_and_subprocesses(language_server_process.pid)
def main(): args = sys.argv[1:] # If -o is not passed, without logging to any file. All other arguments # are passed on to pytest. open_stream = _noop_ctx pytest_args = [] for arg in args: if arg.startswith("-o"): test_output_filename = arg[2:] open_stream = lambda: open(test_output_filename, "w") else: pytest_args.append(arg) with open_stream() as stream: def write(msg): for s in (sys.stderr, stream): if s is not None: s.write(msg) s.write("\n") s.flush() write("=== Initializing test run ===") retcode = 1 initial_time = time.time() try: args = [sys.executable, "-m", "pytest"] + pytest_args timeout = int(os.environ.get("RUN_TESTS_TIMEOUT", "100")) write("Calling:\n cwd:%s\n args: %s\n timeout: %s" % (os.path.abspath(os.getcwd()), args, timeout)) process = subprocess.Popen(args) pid = process.pid while (time.time() - initial_time) < timeout: time.sleep(1) process_retcode = process.poll() if process_retcode is not None: retcode = process_retcode process = None break else: write( "Running tests timed out (pid: %s, timeout: %s seconds)." % (pid, timeout)) try: import psutil except ImportError: pass else: pids = [] p = psutil.Process() for s in p.children(recursive=True): try: cmdline = s.cmdline() except Exception as e: cmdline = str(e) write("Subprocess leaked: %s (%s)\n" % (s, cmdline)) pids.append(s.pid) try: from robocorp_ls_core.basic import kill_process_and_subprocesses except: # Automatically add it to the path if not there. sys.path.append( os.path.join( os.path.dirname( os.path.dirname( os.path.abspath(__file__))), "src", )) from robocorp_ls_core.basic import kill_process_and_subprocesses kill_process_and_subprocesses(pid) sys.exit(1) sys.exit(retcode) finally: write("=== Finalizing test run. Total time: %.2fs ===" % (time.time() - initial_time))