(shutdownOptions: { exitCode?: number; cause?: unknown } = {})
| 239 | |
| 240 | let shuttingDown = false; |
| 241 | const shutdown = async (shutdownOptions: { exitCode?: number; cause?: unknown } = {}) => { |
| 242 | if (shuttingDown) return; |
| 243 | shuttingDown = true; |
| 244 | if (shutdownOptions.cause) { |
| 245 | await emitFatalDiagnostic(shutdownOptions.cause); |
| 246 | } |
| 247 | await closeDaemonServers(servers); |
| 248 | // Hand healthy simulator runners off to the next daemon before session |
| 249 | // teardown gets a chance to kill them; everything left after this |
| 250 | // (real devices, unhealthy runners) goes through the normal stop path. |
| 251 | const { detachIosSimulatorRunnerSessionsForShutdown, stopAllIosRunnerSessions } = |
| 252 | await import('../../platforms/apple/core/runner/runner-client.ts'); |
| 253 | try { |
| 254 | await detachIosSimulatorRunnerSessionsForShutdown(); |
| 255 | } catch {} |
| 256 | await teardownDaemonSessions(); |
| 257 | await Promise.allSettled( |
| 258 | providerDeviceRuntimes.map(async (runtime) => await runtime.shutdown()), |
| 259 | ); |
| 260 | await stopAllIosRunnerSessions(); |
| 261 | // Best effort: stop the PNG worker so an in-flight job cannot delay exit. |
| 262 | await Promise.race([ |
| 263 | terminatePngWorker().catch(() => {}), |
| 264 | sleep(DAEMON_PNG_WORKER_TERMINATE_TIMEOUT_MS), |
| 265 | ]); |
| 266 | removeInfo(infoPath); |
| 267 | releaseDaemonLock(lockPath); |
| 268 | setRunnerLeaseOwnerStateDir(undefined); |
| 269 | exit(shutdownOptions.exitCode ?? 0); |
| 270 | }; |
| 271 | |
| 272 | if (options.registerProcessHandlers !== false) { |
| 273 | process.on('SIGINT', () => { |
no test coverage detected
searching dependent graphs…