Configurable boot deadlines for full iOS simulators and Android emulators
I maintainer di solito rispondono entro 1 giorno
@V3RON ci sta già lavorando.
Dal 5/11/2026.
Valutazione
Questa issue non è ancora stata valutata.
Descrizione
Part of #1311.
Scope
An operator sets how long a full iOS simulator boot (ios.full.bootTimeoutMs) and an Android emulator boot (android.bootTimeoutMs) may take. Both default to 300 s, up from today's fixed 120 s (iOS, F1) and 180 s (Android, F8). The whole feature in one PR: two config keys, the two drivers, the daemon wiring, config.get, the docs.
In short
A full iOS boot now waits ios.full.bootTimeoutMs (300 000 ms unless set, counted from the end of simctl boot) and an Android boot waits android.bootTimeoutMs (300 000 ms unless set, counted from the emulator's spawn) before giving up. A slim iOS boot keeps ios.slim.bootTimeoutMs. The timeout's message stays Timed out waiting for device to boot: <device id> (F13).
flowchart LR
A[config.json] --> B[loadConfig]
B --> C[discoverDrivers]
C --> D[iOS driver]
C --> E[Android driver]
D --> F["full boot, recovery boot, seed boot: ios.full.bootTimeoutMs (changed)"]
D --> G[slim boot: ios.slim.bootTimeoutMs]
E --> H["every emulator boot: android.bootTimeoutMs (changed)"]
E --> I[emulator exit wait at shutdown and delete: 180 s fixed]
| Config | Today | After |
|---|---|---|
| nothing set | iOS full 120 s, Android 180 s | 300 s each |
ios.full.bootTimeoutMs: 400000 |
warned Unknown config key: "ios.full.bootTimeoutMs", ignored (F19) |
full iOS boots wait 400 s |
android.bootTimeoutMs: 600000 |
warned Unknown config key: "android.bootTimeoutMs", ignored (F19) |
Android boots wait 600 s; exit waits stay 180 s |
either key 0, -1 or "300000" |
warned, ignored | daemon refuses to start; message names the key, as ios.slim.bootTimeoutMs does (F5) |
If this goes wrong, a user sees one kind of boot (a seed, a recovery, an Android copy) still fail at the old deadline.
Technical spec
Facts
Commit 85944c1f6.
| # | Fact | Source |
|---|---|---|
| F1 | The iOS full boot deadline is the constant BOOTSTATUS_TIMEOUT_MS = 120_000 |
src/drivers/ios/index.ts:91 |
| F2 | A new iOS seed boots with that constant | src/drivers/ios/index.ts:1033 |
| F3 | planSlimBoot gives the constant to a recovery boot, a boot without slim options, a non-slim mode and a runtime below iOS 18.5; only a slim prepare on 18.5+ gets slim.bootTimeoutMs |
src/drivers/ios/index.ts:2561-2586 |
| F4 | #bootAndWait runs simctl boot (30 s), then counts one deadline over bootstatus -b and the listapps polls; expiry shuts the device down and throws BootTimeoutError |
src/drivers/ios/index.ts:1188-1210 |
| F5 | ios.slim.bootTimeoutMs defaults to 600_000 and is validated positiveNumber; bad values are refused naming the key |
src/core/config.ts:1005-1010, src/core/config.ts:1170-1175, src/core/config.test.ts:1187-1190 |
| F6 | config.get's output is configSchema, which declares ios.slim.bootTimeoutMs and android.emulator; an undeclared field is stripped |
src/contract/operations.ts:692-697, src/contract/schemas.ts:1096-1112 |
| F7 | The daemon passes config.ios.slim and config.android.emulator to discoverDrivers; AndroidDriver.create gets no readinessTimeoutMs |
src/daemon/main.ts:482-484, src/daemon/main.ts:1517-1530 |
| F8 | Android's boot deadline is DEFAULT_READINESS_TIMEOUT_MS = 180_000, overridable by the readinessTimeoutMs create option and handed to the emulator part |
src/drivers/android/index.ts:91, src/drivers/android/index.ts:128, src/drivers/android/index.ts:332 |
| F9 | waitForReadiness throws BootTimeoutError once readinessTimeoutMs has passed since its startedAt: the spawn for start (every boot), the call itself for a second makeReady of a booting device |
src/drivers/android/emulator.ts:197-205, src/drivers/android/emulator.ts:305, src/drivers/android/index.ts:591 |
| F10 | The same readinessTimeoutMs bounds the wait for an emulator to exit before a delete (waitForEmulatorsToExit) and before SIGKILL at shutdown |
src/drivers/android/emulator.ts:166, src/drivers/android/emulator.ts:351 |
| F11 | An Android seed make boots cold twice through emulator.start |
src/drivers/android/seeds.ts:588, src/drivers/android/seeds.ts:624 |
| F12 | A making seed row this process is making is removed by the sweep once older than SEED_MAKE_CEILING_MS = 900_000 |
src/drivers/android/seeds.ts:40, src/drivers/android/seeds.ts:165-171 |
| F13 | BootTimeoutError's message is Timed out waiting for device to boot: <deviceId> |
src/core/driver.ts:653 |
| F14 | iOS joins concurrent makes of one seed kind, so its 300 s stale-making sweep never runs during a make |
src/drivers/ios/index.ts:966-971, src/drivers/ios/index.ts:996-1002 |
| F15 | Existing tests pin the 120 s seed and full boot timeouts and model a deadline test on a fake clock | src/drivers/ios/index.test.ts:874, src/drivers/ios/index.test.ts:1698, src/drivers/ios/index.test.ts:3063-3102 |
| F16 | Android tests pass readinessTimeoutMs: 0 to make the exit wait instant before a destroy |
src/drivers/android/index-lifecycle.test.ts:685 |
| F17 | discoverDrivers is exported and tested with scripted runners |
src/daemon/main.ts:1372, src/daemon/main.test.ts:2247-2274 |
| F18 | simlock config set validates through loadConfig and prints Updated <key> in <path>; takes effect on daemon restart. |
src/cli/commands/config.ts:49-70 |
| F19 | An unknown config key is warned Unknown config key: "<path>" and ignored |
src/core/config.ts:1065, src/core/config.test.ts:1173-1183 |
| F20 | The website pages that describe boot deadlines (doc lines, no code): the configuration reference row, the slim note and boot-failed row in capacity, the 180 s line in requirements |
website/src/content/docs/docs/reference/configuration.mdx:197, website/src/content/docs/docs/worker/capacity.mdx:126, website/src/content/docs/docs/worker/capacity.mdx:220, website/src/content/docs/docs/introduction/requirements.mdx:58 |
| F21 | The module manuals list both deadlines as having no key | src/drivers/ios/AGENTS.md:111, src/drivers/android/AGENTS.md:120 |
| F22 | A seed make's steps besides its two boots are bounded at 60 s (shell sync), 60 s (reboot -p), 60 s (power-off wait), 60 s (snapshot save), 5 s (snapshot list), 5 s (emu kill) and the 180 s exit wait: 430 s; avdmanager create has no limit |
src/drivers/android/seeds.ts:39, src/drivers/android/seeds.ts:588-594, src/drivers/android/seeds.ts:637, src/drivers/android/seeds.ts:657-668, src/drivers/android/emulator.ts:344, src/drivers/android/emulator.ts:351 |
Modules touched
Searches: BOOTSTATUS_TIMEOUT_MS (5 hits, one file), readinessTimeoutMs (src, non-test: android/index.ts, emulator.ts, testing.ts), bootTimeoutMs (src, non-test: core/config.ts, contract/schemas.ts, drivers/ios/index.ts, daemon/main.ts), SEED_MAKE_CEILING_MS (one file).
src/core/config.ts: type, defaults, validators forios.full.bootTimeoutMsandandroid.bootTimeoutMs.src/contract/schemas.ts:configSchemagains both.src/daemon/main.ts: passes both to the drivers.src/drivers/ios/index.ts: the full deadline comes from the option.src/drivers/android/index.ts,emulator.ts,seeds.ts: the boot deadline comes from the option; the exit waits keep 180 s; the seed make ceiling covers two boots.- Docs: F20 pages, F21 manuals.
flowchart LR
config["core/config.ts (changed)"] --> main["daemon/main.ts (changed)"]
main --> ios["drivers/ios/index.ts (changed)"]
main --> android["drivers/android (changed)"]
schemas["contract/schemas.ts (changed)"] --> dispatcher[daemon/dispatcher.ts config.get]
Contract and event changes
configSchema (config.get's output, F6) gains ios.full: { bootTimeoutMs: number } and android.bootTimeoutMs: number. This PR bumps the protocol by one. No event changes. Bounds come from loadConfig: a positive number, else the daemon refuses to start naming the key (F5).
Other code on the same state
Searches: the two deadlines' uses (F1-F4, F8-F11), the stale-making sweeps (STALE_MAKING_MS, SEED_MAKE_CEILING_MS), boot estimates (COLD_BOOT_ESTIMATE_MS, SEED_MAKE_ESTIMATE_MS), the gateway's leaseRequestTimeoutMs.
- iOS stale
makingsweep (F14): never runs during a make of its kind, so a longer seed boot cannot be swept. No change. - Android seed sweep (F12): a make takes two boots plus steps bounded at up to 430 s in all (F22); at the 300 s default that is about 1030 s, past today's 900 s, so a running make would be removed. The ceiling becomes the larger of 900 s and twice
android.bootTimeoutMsplus 600 s (1200 s at the default).avdmanager createhas no limit of its own, as today. - Boot estimates and Doctor's stall threshold read the estimate, not the deadline: unchanged.
- Gateway
leaseRequestTimeoutMs(5 min): a cold lease that makes a seed can now take up to two deadlines. Slim already can (600 s). No change.
Failure modes
| Call | Outcome | What happens | Limit, counted from |
|---|---|---|---|
iOS bootstatus -b + listapps |
ok | device ready | ios.full.bootTimeoutMs, from the end of simctl boot |
iOS bootstatus -b + listapps |
no answer in time | best-effort shutdown, BootTimeoutError (F4) |
same |
| Android readiness poll | ok | device ready | android.bootTimeoutMs, from the spawn (a second makeReady: from that call) |
| Android readiness poll | no answer in time | SIGKILL, BootTimeoutError (F9) |
same |
| Android emulator exit at shutdown or delete | never exits | SIGKILL / refuse delete, as today | 180 s, from the kill request |
A restart in the middle writes nothing new: the deadline is read at start. Two boots at once each count their own deadline.
Rules in play
- ADR 0002 §8: "a
--fulldevice, a runtime below the floor, or a recovery boot keeps the normal deadline": the normal deadline becomesios.full.bootTimeoutMs. - ADR 0060 §5: "
ios.slim.bootTimeoutMskeeps its meaning ... and its default": unchanged. - Contract rule: "Every change to a contract shape bumps it by one in the same PR": bumped.
- Documentation rule 9: the public config surface changes, so the F20 pages change in this PR.
Tests
Seams: IosSimctlDriver in src/drivers/ios/index.test.ts (model: the slim deadline test, F15), AndroidDriver in src/drivers/android/index-lifecycle.test.ts, loadConfig in src/core/config.test.ts, Dispatcher in src/daemon/dispatcher.test.ts, discoverDrivers in src/daemon/main.test.ts. The tests pinning 120 s (F15) move to 300 s. The Android tests that pass readinessTimeoutMs: 0 to make the exit wait instant (F16; index-lifecycle.test.ts:712, :739, :771) advance the fake clock past 180 s instead; Tests line 4 extends the one at 712. About 21 test files build a full config by hand and gain the two new fields.
- An operator's full iOS boot waits
ios.full.bootTimeoutMs, then fails withBootTimeoutError: prepare full; prepare slim on an iOS 18.4 runtime; recover full; recover slim; prepare slim on iOS 18.5 keepsios.slim.bootTimeoutMs; key unset (300 s) and set (400 s). - A provision that makes a new iOS seed boots the seed within
ios.full.bootTimeoutMs: key unset (300 s); key set (400 s). - An Android boot waits
android.bootTimeoutMs, then fails withBootTimeoutError: prepare from the snapshot; recover; a seed's two cold boots; a second makeReady while the device still boots; key unset (300 s) and set (600 s). - An Android shutdown or delete waits 180 s for the emulator to exit, whatever
android.bootTimeoutMsis: key 600 s, emulator never exits. - An Android seed still being made is kept by a source listing while its two boots may still run:
android.bootTimeoutMs600 s, listing 1000 s into the make: kept; listing past the larger of 900 s and twiceandroid.bootTimeoutMsplus 600 s: removed. - An operator's config sets the two keys, or leaves them out: both unset (300000 each); both set;
0,-1,"300000"each refused naming the key. - An admin reads the config and sees both keys: defaults; set values.
- A worker starts its drivers with the two keys from its config: iOS key set; Android key set.
Done when
pnpm test:changedpasses, and holds the eight Tests lines above.- The configuration reference has a row for each key with its default (300000, 5 min); capacity's slim note, its
boot-failedrow and the requirements 180 s line point to the right key. - The iOS and Android manuals' timer tables name both keys.
Out of scope
- Admission under memory pressure (#1246).
- The boot estimates, the BootTimeoutError text, the 30 s per-
simctlcall, the slim readback, Android's snapshot save and power-off waits.
Depends on
Written by an agent.
- Lingua principale
- TypeScript
- Stelle
- 535
- Fork
- 21
- Merge medio
- 9h 10m
- PR unite (30g)
- 454
Preparare l'ambiente
Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di callstackincubator/simlock
-
os:windows request:new
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
callstackincubator/simlock#1071 ·
I maintainer di solito rispondono entro 1 giorno
-
A learned kind keeps one ready copy while its copies are leasedForse già presa @V3RON l’ha presa oggi. Apertatask:blocked
Difficoltà 4/5 3-5 giorni Idoneità per principianti 20/100
callstackincubator/simlock#1381 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
feature:planned
Difficoltà 4/5 3-5 giorni Idoneità per principianti 35/100
callstackincubator/simlock#1374 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
request:new
Difficoltà 3/5 1-2 giorni Idoneità per principianti 55/100
callstackincubator/simlock#1372 ·
I maintainer di solito rispondono entro 1 giorno
-
bug:new
Difficoltà 4/5 1-2 giorni Idoneità per principianti 55/100
callstackincubator/simlock#1371 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di callstackincubator/simlock
Issue simili
-
JSDelivr CDN is brokenAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
-
🐛 bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
LibreChat-AI/LibreChat#17875 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 85/100
I maintainer di solito rispondono entro 1 giorno
-
category:helper tech-debt
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
LanternOps/breeze#11285 ·
I maintainer di solito rispondono entro 1 giorno
-
area: core area: docs good first issue help wanted lane: free-agent priority: P3 roadmap size: XS type: task
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 86/100
arminazimi/seaworthy#701 ·
I maintainer di solito rispondono entro 1 giorno