ReviewOS

craft-native/craft

Cancel owned Android emulator sessions through complete process cleanup

#434
Open chris opened this 12 hours ago ·
12 hours ago

Related parent: S3-012 native Vulkan qualification. The new Android native qualification runner needs to interrupt an owned emulator without touching other devices or deleting files still used by SDK processes.

createAndroidEmulator currently has no public cancellation contract. An initial signal implementation also exposed two independently reproduced failures: abort after returning a session only sends SIGTERM, leaving a TERM-ignoring guest alive; failed process-group disposal removes the private registry even while its guest remains alive. Exceptions raised while signaling from abort/timer callbacks can escape the awaited error path.

Reproduction uses the public helper with isolated shell SDK fixtures and owned-PID-filtered syscall fault injection. Before the correction, the new post-return and failed-disposal regression cases both failed (0 passed, 2 failed). Separate unchanged-original-API regressions for pre-cancelled requests, provisioning cancellation and boot cancellation also failed before the initial signal support. All test guests are explicitly rescued and reaped by the fixture teardown; no foreign Android device or registry is modified.

Acceptance:

  • Pre-cancelled requests start no commands or registry.
  • Provisioning and boot cancellation terminate and reap every owned process group within bounded budgets.
  • Cancellation after successful session creation performs full bounded disposal, including TERM-ignoring guests.
  • The public session exposes an awaitable cleanup result; signaling and cleanup errors reject awaited promises instead of escaping async callbacks.
  • Private registry/log files remain available if a group cannot be reaped or command pipes never reach EOF.
  • No shared ADB server, foreign device, user registry or unrelated process is stopped or removed.
  • Public helper regressions cover the successful and failed paths, including OS signaling denial and an escaped child holding command pipes open.
  • Owning lint, SDK/mobile helper tests, types, package exports, formatting and release checks pass before source delivery. Package publication and downstream adoption require separate verified evidence.

This issue qualifies emulator ownership and cancellation. It does not establish native Vulkan pixels, native game presentation, or device performance. Those remain with #393 and downstream game acceptance.

12 hours ago

Implemented and pushed on main as Chris, without coauthors, in 31d88913.

The public helper now accepts cancellation before provisioning, during SDK work, while booting, between readiness probes, and after returning a session. It owns command and guest process groups through bounded termination and reap acknowledgement. A missing acknowledgement or pipe EOF retains the private registry. Abort and timer callbacks report errors through awaited promises instead of throwing outside the helper.

session.closed records the first disposal outcome. Concurrent and successful dispose() calls share one promise; after a genuine failed disposal, a caller can restore OS access and retry dispose() without losing the original closed failure. Cancellation preserves the exact caller-supplied abort reason when cleanup succeeds. A transient timed-out readiness probe remains a failed probe that can retry inside the original boot deadline.

Retained public regressions use isolated SDK fixtures, real owned processes and narrowly filtered syscall fault injection. They cover pre-abort, provisioning and boot abort, between-probe reason identity, post-return TERM resistance, signaling failure, retry after denied signaling, escaped pipe ownership, and readiness timeout retry. The reproduced ownership failures were red before correction; retry and abort-identity cases also failed before their corresponding corrections. Fixture teardown rescues only its known owned processes.

Local verification on the integrated source:

  • Frozen installation passed.
  • Full SDK: 836 passed, 10 explicit existing skips, 0 failed, 2,374 assertions across 57 files, including all 36 Android emulator helper cases.
  • Android package: 203 passed, 0 failed, 2,130 assertions across 18 files, including executed JVM fixtures.
  • Full type checks passed.
  • Release regression suite: 416 passed, 0 failed, 4,595 assertions.
  • Normal package builds, 8 npm archives / 16 installed runtime and type entry points, and 43 publish-surface checks passed.
  • Zig formatting passed with the exact Pantry pin 0.18.0-dev.146+35accc0. The unpinned global compiler was initially rejected and was not bypassed.
  • Full Pickier lint passed with 0 errors and 26 existing warnings; the changed files and whitespace checks are clean.

Remote checks are queued at recording time: exact-source CI, Mobile E2E.

The issue remains open pending the relevant publication and downstream adoption evidence. No package release was cut, no published package adoption is claimed, and this helper correction does not qualify native Vulkan pixels, native gameplay, or physical device performance. Those acceptance results remain separate under parent #393.

12 hours ago

The independently cut v0.0.421 candidate at 806d3d52 includes this fix. Its ordinary Releaser is waiting for the required exact-source CI and Mobile E2E gates. No duplicate version bump was performed. The candidate's existing release/source attribution was preserved; the fix remains authored and committed as Chris chris@stacksjs.com without coauthors.

The original private staged npm artifact 13118038680 was independently downloaded and verified against GitHub SHA-256 e29224b6d921a826532d93bc7886c595e666aacbfdc6e788f72ec9d1955c663e (2,988,823 bytes), including every ZIP CRC and the canonical eight-package archive manifest. The staged Android tarball has SHA-256 282482f380744350530196574f2777a7f416a23668445043ad106f838da604e1.

A separate normal and frozen consumer installation of those unchanged archives passed all 36 emulator helper cases and 214 assertions through the installed @craft-native/android public export. Only the test imports changed from source-relative imports to the package export; assertions and limits stayed unchanged. All 432 installed payload files from the eight Craft packages matched the original staged tarballs byte for byte. Consumer lock SHA-256: c3ef8c166b0ea9d65c20dddaf54ae640f41a5f8701abdab09f1e501a8abfb5db.

This is staged-artifact evidence, not a shipped-release claim. Public native archives and npm publication are still gated, and Stacks/game adoption has not begun. The issue stays open until the remaining publication/adoption evidence is verified.

12 hours ago

Release verification update: the independently cut v0.0.421 candidate at 806d3d52ec876dccc441bee70b2d922ebbf1a072 includes the #434 source fix 31d88913aed18f5eb1bdc707f43cea6c35a48050. Exact source CI succeeded, but canonical Releaser 41393706745 failed its native acceptance gate. Publication was correctly skipped; the candidate is not verified published and has not been adopted downstream.

The exact candidate Android job records a JavaScriptSandbox service disconnect during isolate evaluation after 73 instrumentation cases had passed, followed by cascading dead-engine navigation failures. This does not establish the upstream provider service-loss cause or implicate the emulator cancellation change. Independent API34/API35 native navigation jobs passed the same source.

Follow-up #438, attached to the Gold native foundations epic, repairs the concrete missing-diagnostics boundary before further diagnosis. The original artifact 13120804415 was retained unchanged with SHA256 3e711f10fe31b7d4c8c06117d1156ec1fbdb4425a2dfe5e1a5c1409008848ccd and all ZIP CRCs checked. Its full-logcat artifact was captured after emulator teardown and contains only - waiting for device -; the native runner filtered provider/system logs and deleted instrumentation reports. The new source work preserves these before teardown. It does not cure sandbox service loss or bypass any native/release gate.

#434 stays open for verified publication/adoption. No duplicate bump, blind release retry, or downstream install has been performed.

Sign in to comment on this issue.