From 97c68f56bf68e34059c8c9d51ba7367c17620bc6 Mon Sep 17 00:00:00 2001 From: grossmj Date: Sat, 6 Oct 2018 21:30:39 +0800 Subject: [PATCH] Notify users if x11vnc process has crashed. Fix #1401. --- gns3server/compute/docker/docker_vm.py | 40 ++++++++++++++++---------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/gns3server/compute/docker/docker_vm.py b/gns3server/compute/docker/docker_vm.py index 9dc696a8..f6ffc16a 100644 --- a/gns3server/compute/docker/docker_vm.py +++ b/gns3server/compute/docker/docker_vm.py @@ -82,12 +82,14 @@ class DockerVM(BaseNode): self._ethernet_adapters = [] self._temporary_directory = None self._telnet_servers = [] + self._xvfb_process = None self._x11vnc_process = None self._console_resolution = console_resolution self._console_http_path = console_http_path self._console_http_port = console_http_port self._console_websocket = None self._extra_hosts = extra_hosts + self._closing = False self._volumes = [] # Keep a list of created bridge @@ -425,6 +427,11 @@ class DockerVM(BaseNode): elif state == "running": return else: + + if self._console_type == "vnc" and not self._x11vnc_process: + # start the x11vnc process in case it had previously crashed + self._x11vnc_process = yield from asyncio.create_subprocess_exec("x11vnc", "-forever", "-nopw", "-shared", "-geometry", self._console_resolution, "-display", "WAIT:{}".format(self._display), "-rfbport", str(self.console), "-rfbportv6", str(self.console), "-noncache", "-listen", self._manager.port_manager.console_host) + yield from self._clean_servers() yield from self.manager.query("POST", "containers/{}/start".format(self._cid)) @@ -532,22 +539,11 @@ class DockerVM(BaseNode): self._xvfb_process = yield from asyncio.create_subprocess_exec("Xvfb", "-nolisten", "tcp", ":{}".format(self._display), "-screen", "0", self._console_resolution + "x16") # We pass a port for TCPV6 due to a crash in X11VNC if not here: https://github.com/GNS3/gns3-server/issues/569 self._x11vnc_process = yield from asyncio.create_subprocess_exec("x11vnc", "-forever", "-nopw", "-shared", "-geometry", self._console_resolution, "-display", "WAIT:{}".format(self._display), "-rfbport", str(self.console), "-rfbportv6", str(self.console), "-noncache", "-listen", self._manager.port_manager.console_host) - x11_socket = os.path.join("/tmp/.X11-unix/", "X{}".format(self._display)) yield from wait_for_file_creation(x11_socket) - #monitor_process(self._xvfb_process, self._xvfb_callback) - #monitor_process(self._x11vnc_process, self._x11vnc_callback) - - def _xvfb_callback(self, returncode): - """ - Called when the process has stopped. - - :param returncode: Process returncode - """ - - if returncode != 0: - self.project.emit("log.error", {"message": "The Xvfb process has stopped, return code: {}.".format(returncode)}) + # sometimes the x11vnc process can crash + monitor_process(self._x11vnc_process, self._x11vnc_callback) def _x11vnc_callback(self, returncode): """ @@ -556,8 +552,9 @@ class DockerVM(BaseNode): :param returncode: Process returncode """ - if returncode != 0: - self.project.emit("log.error", {"message": "The x11vnc process has stopped, return code: {}.".format(returncode)}) + if returncode != 0 and self._closing is False: + self.project.emit("log.error", {"message": "The x11vnc process has stopped with return code {} for node '{}'. Please restart this node.".format(returncode, self.name)}) + self._x11vnc_process = None @asyncio.coroutine def _start_http(self): @@ -740,6 +737,7 @@ class DockerVM(BaseNode): Closes this Docker container. """ + self._closing = True if not (yield from super().close()): return False yield from self.reset() @@ -751,6 +749,7 @@ class DockerVM(BaseNode): state = yield from self._get_container_state() if state == "paused" or state == "running": yield from self.stop() + if self.console_type == "vnc": if self._x11vnc_process: try: @@ -758,11 +757,22 @@ class DockerVM(BaseNode): yield from self._x11vnc_process.wait() except ProcessLookupError: pass + self._x11vnc_process = None + if self._xvfb_process: try: self._xvfb_process.terminate() yield from self._xvfb_process.wait() except ProcessLookupError: pass + self._xvfb_process = None + + display = "/tmp/.X11-unix/X{}".format(self._display) + try: + if os.path.exists(display): + os.remove(display) + except OSError as e: + log.warning("Could not remove display {}: {}".format(display, e)) + # v – 1/True/true or 0/False/false, Remove the volumes associated to the container. Default false. # force - 1/True/true or 0/False/false, Kill then remove the container. Default false. try: