Skip to content
This repository was archived by the owner on Jul 21, 2026. It is now read-only.

dinit: supervise real Kandelo service processes - #51

Open
brandonpayton wants to merge 3 commits into
mainfrom
migrate/dinit-service-manager
Open

dinit: supervise real Kandelo service processes#51
brandonpayton wants to merge 3 commits into
mainfrom
migrate/dinit-service-manager

Conversation

@brandonpayton

@brandonpayton brandonpayton commented Jul 11, 2026

Copy link
Copy Markdown
Member

Why

Kandelo images need a service supervisor that can start, monitor, control, and
stop real processes. The existing Dinit entry belongs to the older package
registry, so Homebrew-based images cannot yet depend on it as a normal package.
Migrating Dinit 0.19.4 matters because its complete lifecycle exercises
Kandelo's standard C++ library, signals, process creation, execution, and wait
behavior instead of a service-specific substitute.

This PR contains Formula source only. It does not publish a bottle, which is
Homebrew's prebuilt package archive, or change Kandelo's runtime or Application
Binary Interface (ABI).

What changed

  • build the exact upstream v0.19.4 release and declare the tap's full-name libcxx target dependency
  • run native mconfig-gen through the declared host C++ helper while target objects use Kandelo's wasm32 SDK and the installed libcxx keg
  • carry a scoped Dasynq Wasm SjLj patch that removes only the two noexcept event-loop boundaries which would terminate before the generated setjmp dispatcher receives longjmp
  • fork-instrument and require complete continuation exports on dinit and dinit-monitor
  • require dinitctl and dinitcheck to remain fork-free
  • reject retired Asyncify, undeclared imports, and host/build paths
  • test a real Dinit -> monitor -> fork/exec/wait -> dinitcheck service lifecycle

No registry build script, syscall workaround, or package-specific runtime behavior is used.

Exact source

  • reviewed PR head: fb6b3da7fb1d948c750867cdee054fd980e13a7d
  • tree: db7c3a4f8bb5de36c71c713efbce21263b2bb670
  • Formula blob: 5ac08c51ab1ed31acc5a508dc8b2af9756b53a74
  • Formula SHA-256: 49bca24889dc8f204e9f2ceeaed543e4a4ea173fd5b6c257d7b2567813aa9835
  • embedded patch SHA-256: 0e452b82854072df24dd02fa971b28b72387e52b5ee18dc3ba8b476506f1f888
  • Kandelo main used for the current review: 9a7a679195ead9bbdef119830437d5a758566607 (ABI 39)

The final branch must be restacked onto the then-current tap main before merge. Formula and patch bytes remain identical to the previously reviewed source.

Current platform gates

Do not merge this PR yet. The Formula is correct, but two open Kandelo fixes gate an honest ABI 39 lifecycle:

  1. sdk: preserve static linker argument order kandelo#913: preserve static linker input order. Dinit correctly invokes wasm32posix-c++ with objects before -lc++ -lc++abi. Current SDK argument reconstruction moves those objects after the libraries. The ABI-bearing channel_syscall.c is present; the Formula did not omit it. #913 fixes the SDK defect.
  2. homebrew: publish and verify installable Kandelo bottles kandelo#936: read ABI exports through linker thunks. Current main reports ABI 0 after fork instrumentation because the ABI function is exported through a linker-generated constructor command thunk. #936 follows the thunk's final callee and reports ABI 39 on the same bytes, both before and after instrumentation.

After #913 and #936 land, this PR needs a fresh source install plus brew test on current tap main. That lifecycle will determine whether #842's larger default main-thread stack is also required. #842 is not yet claimed as a Dinit gate.

Current validation

  • Ruby syntax and git diff --check: passed
  • exact source fetch and checksum: passed
  • fresh musl, kernel, and fork-tool builds: passed
  • source-built libcxx: passed
  • Dinit compile, link, and fork instrumentation: passed
  • hardened #936 ABI extraction on the exact instrumented Dinit bytes: ABI 39
  • current-main validator negative control on those same bytes: ABI 0

Installation correctly stops at the current validator mismatch, so no ABI 39 Formula lifecycle claim is made yet.

Historical runtime evidence

The byte-identical Formula previously completed two ABI 18 source builds. Node and Chromium ran the CLI probes and the full Dinit service lifecycle; dinit and dinit-monitor were fork-complete, while dinitctl and dinitcheck remained fork-free. That evidence supports the recipe design but is not a current-ABI, bottle, provenance, or pour claim.

Bottle publication remains separate and requires the merged publisher plus stock Homebrew Node and Chromium pours. This PR contains no bottle do block, archive, sidecar, receipt, or provenance metadata.

@brandonpayton
brandonpayton force-pushed the migrate/dinit-service-manager branch 2 times, most recently from b596452 to 815ad25 Compare July 12, 2026 10:35
@brandonpayton

Copy link
Copy Markdown
Member Author

Exact-head refresh pushed at 815ad25efe5096a03f85c385552ccf0023074239.

  • restacked the original Dinit source change and embedded patch on current tap main
  • switched to installed-tap Formula support
  • replaced duplicate ABI/fork checks with the shared validator while preserving the strict Dinit env import allowlist
  • added Binaryen as the validator's declared build tool
  • passed Ruby syntax, Homebrew style, shared support (30/221), and diff checks
  • independent devil review accepted the refresh

This is source-contract evidence only. #867 is resolved; the remaining platform/publisher gates and fresh bottle-backed Node/Chromium proof still apply.

@brandonpayton

Copy link
Copy Markdown
Member Author

Independent devil review at exact refreshed head 815ad25efe5096a03f85c385552ccf0023074239: APPROVE the source contract after #882; retain the documented platform/publication gates.

The upstream source/hash/license and libcxx dependency are explicit. The embedded two-line Dasynq change is byte-identical to the previously proven patch and is scoped to the LLVM Wasm SjLj/noexcept compiler boundary; it does not hide a Kandelo POSIX failure. The exact final dinit and dinit-monitor bytes are instrumented and validated fork: :required; dinitctl/dinitcheck remain import-authoritative under fork: :auto; the Dinit-specific unresolved env allowlist is preserved. Binaryen/WABT and the native mconfig generator path are declared, stable guest prefixes replace build paths, and the test exercises the real nested service-manager -> monitor -> fork/exec/wait checker lifecycle.

Fresh exact-head checks: Ruby syntax passed, Homebrew style inspected 1 file with no offenses, git diff --check passed, and the worktree is clean. Shared support blobs are the same 30-run / 221-assertion version already executed in this review batch. No new source build, bottle, or pour is claimed; #882 plus exact merged-head dependency/bottle provenance remain binding.

@brandonpayton

Copy link
Copy Markdown
Member Author

APPROVE for source/formula readiness at exact head 05f9eb5f032f9443dba903f91147bd27142691a3. Leave unmerged pending the hosted artifact gates below.

Devil review evidence:

  • Upstream v0.19.4 re-download hashes to 3c0f624eb958f8e884631be4ef687da1e475ebaa6241e7ee330b864e6cd9e30b; upstream LICENSE is Apache-2.0. The embedded patch changes only the two Dasynq noexcept event-loop boundaries required by Wasm SjLj exception transport.
  • Binaryen, WABT, and native m4 are build-only. The sole target dependency is the merged automattic/kandelo-homebrew/libcxx formula. The Dinit receipt records it as a direct runtime dependency. A stale pre-libcxx: keep static runtime archives relocatable #48 local libc++abi archive was correctly rejected for path leakage; rebuilding the current formula produced path-clean archives and the leaf then built. The local source receipt is evidence, not bottle provenance.
  • Exact installed imports match policy: dinit and dinit-monitor import kernel_fork and have all five continuation exports; dinitctl and dinitcheck have no fork import or instrumentation and are now guarded with fork: :forbidden. No legacy Asyncify was found.
  • Two clean builds were byte-identical. Exact hashes are recorded in the PR body. I reran brew test --verbose against the current installed bytes: all four CLI probes and the dinit -> monitor -> fork/exec/wait -> dinitcheck lifecycle passed under Node.
  • All four Wasm programs and all three linked libcxx archives were rescanned for /private/tmp, /Users, and /nix/store; none remain. The installed formula differs from this exact head only in the temporary local support-loader line used during the source build.
  • Exact Ruby syntax, Homebrew style, Formula support (30/221), and diff checks pass. The source formula has no bottle block or generated publication metadata.

This approval does not cover a bottle, receipt/provenance sidecar, stock-guest pour, or a fresh Chromium run. Keep #51 gated on the applicable platform/publisher stack, including #842, #873, exact #882 (ad671bb48f18af2a2174898a4c63c5df5d6e7a2f, full CI still running), #885, #888/#890, and exact merged-head Node/Chromium bottle pours.

Dinitctl and dinitcheck do not import fork and are not instrumented. Make that negative boundary explicit so a future dependency or link change cannot silently turn either control-plane tool into a fork-capable artifact.
@brandonpayton
brandonpayton force-pushed the migrate/dinit-service-manager branch from 05f9eb5 to fb6b3da Compare July 13, 2026 01:25
@brandonpayton

Copy link
Copy Markdown
Member Author

Independent exact-head review completed for fb6b3da7fb1d948c750867cdee054fd980e13a7d: ACCEPT for force-push/source review; not merge/publish ready.

  • Formula and Dasynq patch bytes are identical to the accepted series; the only range-diff change is README aggregation context.
  • Installed-tap loading, Binaryen/WABT validation, exact libcxx keg resolution, fork-required/forbidden policies, and strict env-import boundaries meet current contracts.
  • Historical evidence covers two reproducible ABI 18 builds and real Node/Chromium dinit -> monitor -> fork/exec/wait -> checker lifecycles; it is not final bottle evidence.
  • Platform gates are #842/#873/#882, deterministic #888-on-#889, #905 service-process parentage, #906 timer behavior, and the consolidated ABI.
  • Publication requires #887/#890/#885, #895/#900, a prior exact libcxx bottle, provenance, and stock Node/Chromium pours.

No Formula blocker was found. Fresh final-ABI source and bottle validation remains required.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant