[cherry-pick][cr148] OS simulator wipe and boot reliability cherry picks landed

Chromium changes:
https://chromium.googlesource.com/chromium/src/+/39a1c1938c9f9c3bcf36f015172600018169b6db
https://chromium.googlesource.com/chromium/src/+/b4a2fed9285188d8a5957d87f72db7162ff90026

commit 39a1c1938c9f9c3bcf36f015172600018169b6db
Author: Yue She <yueshe@google.com>
Date:   Wed Mar 18 11:57:28 2026 -0700

    Improve iOS simulator wipe and boot reliability in test runners

    - Reorders simulator teardown steps: `kill_simulators` is now invoked
    after wiping/erasing data instead of before. This ensures that any stray processes or simulators left in a bad state from the wipe/erase
    procedures are properly cleaned up.
    - Adds a retry mechanism for simulator pre-booting.

    Bug: 441038354
    Change-Id: I8f94649d195a3804d9392dafdcde6dbd2c88ec88
    Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7676077
    Reviewed-by: Will Yeager <wyeager@google.com>
    Commit-Queue: Yue She <yueshe@google.com>
    Cr-Commit-Position: refs/heads/main@{#1601444}

commit b4a2fed9285188d8a5957d87f72db7162ff90026
Author: Yue She <yueshe@google.com>
Date:   Mon Mar 23 10:21:18 2026 -0700

    [iOS] Cache dyld before pre-booting simulators

    This seems to help with simulator booting failures. The workaround is also suggested in https://developer.apple.com/documentation/xcode-release-notes/xcode-26_1-release-notes

    Bug: 441038354
    Change-Id: I5bc754bddbd98a580ed16b1245cf43a267807908
    Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7691682
    Commit-Queue: Yue She <yueshe@google.com>
    Reviewed-by: Will Yeager <wyeager@google.com>
    Cr-Commit-Position: refs/heads/main@{#1603573}
This commit is contained in:
Claudio DeSouza
2026-04-27 12:00:56 +01:00
parent a07ff0019d
commit 71a73115fb
3 changed files with 1 additions and 137 deletions
@@ -1,69 +0,0 @@
diff --git a/ios/build/bots/scripts/iossim_util.py b/ios/build/bots/scripts/iossim_util.py
index d1253bb5e285087154f6586074eba069a2ebe8c3..e2d064221e1b7171c8cf7fea9b752aab8b9c46a1 100644
--- a/ios/build/bots/scripts/iossim_util.py
+++ b/ios/build/bots/scripts/iossim_util.py
@@ -333,7 +333,10 @@ def boot_simulator_if_not_booted(sim_udid, path=SIMULATOR_DEFAULT_PATH):
(sim_udid, simulator_list['devices']))
-def ensure_simulator_fully_booted(sim_udid: str, path=SIMULATOR_DEFAULT_PATH):
+def ensure_simulator_fully_booted(sim_udid: str,
+ path=SIMULATOR_DEFAULT_PATH,
+ num_attempts=1):
+ return False
"""Ensures simulator of given udid is fully booted.
`xcrun simctl boot` launches only background processes and does not ensure the
@@ -351,29 +354,36 @@ def ensure_simulator_fully_booted(sim_udid: str, path=SIMULATOR_DEFAULT_PATH):
Returns:
True if the simulator was successfully booted, false otherwise.
"""
- if is_device_with_udid_simulator(sim_udid):
+ if not is_device_with_udid_simulator(sim_udid):
+ raise test_runner.SimulatorNotFoundError(
+ f"Not found simulator with UDID: {sim_udid}")
- # Ensure data migrations are run
- cmd = [
- 'xcrun',
- 'simctl',
- '--set',
- path,
- 'bootstatus',
- sim_udid,
- '-bd',
- ]
+ # Ensure data migrations are run
+ cmd = [
+ 'xcrun',
+ 'simctl',
+ '--set',
+ path,
+ 'bootstatus',
+ sim_udid,
+ '-bd',
+ ]
+
+ for boot_attempt in range(num_attempts):
try:
subprocess.check_call(cmd, timeout=120)
+ return True
except subprocess.TimeoutExpired as e:
msg = f"Manually booting simulator timed out after 120 seconds."
LOGGER.info(msg)
- return False
- return True
+ msg_again = " again" if boot_attempt > 0 else ""
+ msg_action = "continuing" if boot_attempt == num_attempts - 1 else "retrying"
+ LOGGER.info(f"Failed to manually boot simulator{msg_again}. "
+ f"Wiping simulator and {msg_action}.")
+ wipe_simulator_by_udid(sim_udid)
+ test_runner.SimulatorTestRunner.kill_simulators()
- else:
- raise test_runner.SimulatorNotFoundError(
- f"Not found simulator with UDID: {sim_udid}")
+ return False
@@ -1,5 +1,5 @@
diff --git a/ios/build/bots/scripts/test_runner.py b/ios/build/bots/scripts/test_runner.py
index ce272919c24e5603347929097efbdf15c24f140d..eff230cf2155d6e97527cd53f6cf981555431ae8 100644
index ec3d4b370663ee996c0169f2bf545c5c6de0360b..eff230cf2155d6e97527cd53f6cf981555431ae8 100644
--- a/ios/build/bots/scripts/test_runner.py
+++ b/ios/build/bots/scripts/test_runner.py
@@ -404,6 +404,7 @@ class TestRunner(object):
@@ -10,27 +10,3 @@ index ce272919c24e5603347929097efbdf15c24f140d..eff230cf2155d6e97527cd53f6cf9815
LOGGER.info('Removing any proxy settings.')
network_services = subprocess.check_output(
['networksetup',
@@ -636,10 +637,7 @@ class TestRunner(object):
if iossim_util.is_device_with_udid_simulator(self.udid):
with measures.time_consumption('Simulator full boot', 'TestRunner',
'Pre launch for testing'):
- if not iossim_util.ensure_simulator_fully_booted(self.udid):
- LOGGER.info("Failed to manually boot simulator. "
- "Wiping simulator and continuing.")
- iossim_util.wipe_simulator_by_udid(self.udid)
+ iossim_util.ensure_simulator_fully_booted(self.udid)
try:
result = self._run(cmd=cmd, clones=self.clones or 1)
@@ -830,10 +828,10 @@ class SimulatorTestRunner(TestRunner):
def set_up(self):
"""Performs setup actions which must occur prior to every test launch."""
self.remove_proxy_settings()
- self.kill_simulators()
self.wipe_simulator()
self.wipe_derived_data()
self.disable_hw_keyboard()
+ self.kill_simulators()
self.homedir = self.get_home_directory()
# Crash reports have a timestamp in their file name, formatted as
# YYYY-MM-DD-HHMMSS. Save the current time in the same format so
@@ -1,43 +0,0 @@
diff --git a/ios/build/bots/scripts/xcodebuild_runner.py b/ios/build/bots/scripts/xcodebuild_runner.py
index e114ee2fd9e394332b80ce159ace3b25a3b6151a..6f3a9c66595913b347de7175f7ed5e41c4c02842 100644
--- a/ios/build/bots/scripts/xcodebuild_runner.py
+++ b/ios/build/bots/scripts/xcodebuild_runner.py
@@ -201,12 +201,12 @@ class LaunchCommand(object):
# Erase all simulators per each attempt
if iossim_util.is_device_with_udid_simulator(self.udid):
if self.erase_simulators:
- # kill all running simulators to prevent possible memory leaks
- test_runner.SimulatorTestRunner.kill_simulators()
shutdown_all_simulators()
shutdown_all_simulators(XTDEVICE_FOLDER)
erase_all_simulators()
erase_all_simulators(XTDEVICE_FOLDER)
+ # kill all running simulators to prevent possible memory leaks
+ test_runner.SimulatorTestRunner.kill_simulators()
if self.cert_path:
iossim_util.copy_trusted_certificate(self.cert_path, self.udid)
@@ -214,10 +214,7 @@ class LaunchCommand(object):
'XcodeBuildRunner',
'Pre launch For testing',
f'Test attempt {attempt}'):
- if not iossim_util.ensure_simulator_fully_booted(self.udid):
- LOGGER.info("Failed to manually boot simulator. "
- "Wiping simulator and continuing.")
- iossim_util.wipe_simulator_by_udid(self.udid)
+ iossim_util.ensure_simulator_fully_booted(self.udid, num_attempts=2)
# ideally this should be the last step before running tests, because
@@ -384,10 +381,7 @@ class SimulatorParallelTestRunner(test_runner.SimulatorTestRunner):
if iossim_util.is_device_with_udid_simulator(self.udid):
with measures.time_consumption('Simulator full boot', 'XcodeBuildRunner',
'Pre launch for enumerate test cases'):
- if not iossim_util.ensure_simulator_fully_booted(self.udid):
- LOGGER.info("Failed to manually boot simulator. "
- "Wiping simulator and continuing.")
- iossim_util.wipe_simulator_by_udid(self.udid)
+ iossim_util.ensure_simulator_fully_booted(self.udid, num_attempts=2)
for attempt in range(num_attempts):
# reset error_message with each attempt