Repository: servo/servo
File: tests/wpt/tests/tools/wptrunner/wptrunner/browsers/servodriver.py (Python)

Code before:

    def stop(self, force=False):
        retry_cnt = 0
        while self.is_alive():
            self.logger.info("Trying to shut down gracefully by extension command")
            try:
                requests.delete(
                    f"http://{self.host}:{self.port}/session/dummy-session-id/servo/shutdown",
                    timeout=5
                )
            except requests.exceptions.ConnectionError:
                self.logger.debug("Browser already shut down (connection refused)")
                break
            except requests.exceptions.RequestException as e:
                self.logger.debug(f"Request exception: {e}")
                break
            except requests.exceptions.Timeout:
                self.logger.debug("Request timed out")
                break
                
            retry_cnt += 1
            if retry_cnt >= self.shutdown_retry:
                self.logger.debug("Max retry exceeded.")
                break
            time.sleep(1)
        super().stop(force=force)

    def find_wpt_prefs(self, logger):
        default_path = os.path.join("resources", "wpt-prefs.json")
        # The cwd is the servo repo for `./mach test-wpt`, but on WPT runners
        # it is the WPT repo. The nightly tar is extracted inside the Python
        # virtual environment within the repo. This means that on WPT runners,
        # the cwd has the `_venv3/servo` directory inside which we find the
        # binary and the 'resources' directory.
        for dir in [".", "./_venv3/servo"]:
            candidate = os.path.abspath(os.path.join(dir, default_path))
            if os.path.isfile(candidate):
                return candidate
        logger.error("Unable to find wpt-prefs.json")
        return default_path


Review comment (suggestion):
Maybe we should add a wait here for `super.is_alive()`, so we know when the process really exited? Currently the binary could be still shutting down, and the process force-killed during the normal shutdown.

Code after:
            return True
        except Exception as exception:
            self.logger.debug(f"Servo has shut down normally. {exception}")
            return False

        return True

    def stop(self, force=False):
        retry_cnt = 0
        while self.is_alive():
            self.logger.info("Trying to shut down gracefully by extension command")
            try:
                requests.delete(
                    f"http://{self.host}:{self.port}/session/dummy-session-id/servo/shutdown",
                    timeout=3
                )
            except requests.exceptions.ConnectionError:
                self.logger.debug("Browser already shut down (connection refused)")
                break
            except requests.exceptions.RequestException as exeception:
                self.logger.debug(f"Request exception: {exeception}")
                break
            except requests.exceptions.Timeout:
                self.logger.debug("Request timed out")
                break
                
            retry_cnt += 1
            if retry_cnt >= self.shutdown_retry_attempts:
                self.logger.warn("Max retry exceeded to normally shut down. Killing instead.")
                break
            time.sleep(1)
        super().stop(force)

    def find_wpt_prefs(self, logger):
        default_path = os.path.join("resources", "wpt-prefs.json")
        # The cwd is the servo repo for `./mach test-wpt`, but on WPT runners
        # it is the WPT repo. The nightly tar is extracted inside the Python
        # virtual environment within the repo. This means that on WPT runners,
        # the cwd has the `_venv3/servo` directory inside which we find the
        # binary and the 'resources' directory.
        for dir in [".", "./_venv3/servo"]:
            candidate = os.path.abspath(os.path.join(dir, default_path))
            if os.path.isfile(candidate):
                return candidate
        logger.error("Unable to find wpt-prefs.json")
        return default_path