Skip to content

guest: let nvx-ingress start spawn its announcer itself (SL6.13c) - #1494

Merged
Pedro Henrique Penna (ppenna) merged 2 commits into
feature/nvx-refactorfrom
agents/slim-sl6-13c-ingress-announcer
Nov 11, 2026
Merged

Pedro Henrique Penna (ppenna) merged 2 commits into
feature/nvx-refactorfrom
agents/slim-sl6-13c-ingress-announcer

Conversation

@ppenna

@ppenna Pedro Henrique Penna (ppenna) commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

Part of #1120 (SL6.13c, "nvx-ingress start spawns its announcer itself"). Parent #1087, umbrella #1076.

What and why

nvx-ingress start was the last user in nvx of guest::ingress::Announcer, the library spawner of a clone's announcer, which depends on guest::spawn and guest::process, the process modules that later PRs delete. The program now starts its announcer itself, and the spawner goes:

  • start creates the announcer's IPv4 UDP socket and binds it with the existing shared bind_privileged search, to the highest free privileged source port from 1023 down to 512 (bind_announcer_socket). No copy of the search is added.
  • It spawns /sbin/nvx-ingress inherit GATEWAY_IPV4 with std::process::Command (launch): argv[0] is nvx-ingress, the socket is its standard input, and it keeps the caller's standard output and error. A pre_exec hook of the private OS layer, sys::configure_announcer in guest/sys/spawn.rs, calls setsid and the existing reset_signals. The child gets a session of its own without a controlling terminal, every signal's default disposition, and no blocked signal, as Announcer::start gave it through guest::spawn.
  • start returns once the program runs, which the standard library learns from its close-on-exec report, and exits with 0. It exits with 1 when the program does not start. It waits for no scan or announcement, and leaves the announcer to init or to the nearest subreaper, as before.
  • Before it spawns, launch restores SIGCHLD's default disposition with the existing sys::reset_child_signal. The standard library's spawn collects the status of a child that does not run the program, and panics (wait() should either return Ok or panic) when the kernel has collected it already. The kernel collects every child's status while SIGCHLD is ignored, a disposition that exec keeps. Announcer::start ignored a failure of that collection and still failed with status 1. The code review of this branch found this; the new test an_announcer_does_not_start_without_its_program_when_its_caller_ignores_sigchld fails without the reset and passes with it.
  • Announcer, PROGRAM and StartError are deleted with their tests. guest::ingress, whose only public item is now its main, which SL1.5 hid, becomes #[doc(hidden)]. nvx-rs/public-api/linux.txt drops their 17 lines and marks the module hidden. The nvx-ingress row of the README's guest-binary table and the rustdoc of guest, guest::ingress and sys::UdpSocket describe the new launch.

BOOT_CONTRACT_VERSION and CONTROL_CONTRACT_REVISION don't change, and nothing new on feature/nvx-refactor uses Announcer, PROGRAM or StartError.

Deviations from the issue

  • The runtime adapter changes. The adapter's guest worker started a clone's announcer with Announcer::start and classified StartError, so deleting them forces this change. SL5.2 (nvx-rs slimming 4.1.2: the test adapter is gone #1119) deletes the adapter later. The first commit gives the worker its own launcher, Announcement, with the launch that Announcer::start gave it, built on the public nvx::guest::spawn::Command and nvx::guest::process::Child:

    • it binds its socket to a privileged source port, from 1023 down to 512;
    • it runs /sbin/nvx-ingress inherit GATEWAY_IPV4 in a session of its own, with every signal reset, and waits until the program runs;
    • it stops and collects the announcer when the worker tears its root down or drops it.

    AnnounceFailure becomes public and carries an io::Error, and the guest-session fake now fails with it. Both still end the clone with ACTIVATION_NETWORK. The adapter is test code under tests/, so it adds no counted file.

  • init.rs changes. nvx-init's restored announcer took its path from PROGRAM, a use that guest: retain restored ingress as an init helper #1439 added. It now names c"/sbin/nvx-ingress" itself, and nvx-init still owns its announcer. This one line makes guest/init.rs the fourth counted file.

  • The start-failure message loses its launch stage. The standard library reports only the errno of a failed exec. So nvx-ingress: /sbin/nvx-ingress did not start: the exec launch stage failed: ... becomes nvx-ingress: /sbin/nvx-ingress did not start: No such file or directory (os error 2). A failed fork, which StartError::Spawn reported as ... cannot be started: ..., now reads ... did not start: ... too. The exit status stays 1.

History: the first implementation

Enrique Saurez (@esaurez)'s first implementation is esaurez/slim-4.2.1-sl6.13c-20261108 (fb5b5693, checkpoint on #1120): one commit on the SL7.3 branch. This PR carries it as two commits with Enrique Saurez (@esaurez) as their author, rebased onto feature/nvx-refactor. The runtime adapter's launcher comes first, so that each commit builds. The second commit changes the program. Its main changes to the first implementation are these:

  • start's launch is factored into bind_announcer_socket and launch(program, …), so that its tests run a script in place of /sbin/nvx-ingress. Those tests live in guest::ingress::tests, beside their subject, instead of guest::sys::spawn::tests.
  • It adds the init.rs edit that guest: retain restored ingress as an init helper #1439's use of PROGRAM needs.
  • It adds the SIGCHLD reset and its test.

The case matrix

SL5.1a's case matrix, doc/acceptance-case-matrix.md, gives each test of the runtime adapter a fate. The first commit adds a row for the three tests that it adds to the adapter's worker::tests: they retire with the adapter, and the row points to the tests of nvx-ingress start's own launch, nvx-rs/src/guest/ingress/tests.rs. The summary's count of the adapter's other tests becomes 169, 160 of them retired. The matrix names none of the announcer tests that this PR retires or moves, and each_class_of_failure_ends_the_clone_with_its_own_status keeps its name and its row.

Not in this PR

As the issue says: waiting for the announcer's first scan or announcement, retries beyond the existing descending search, changes to inherit, the announcements, gateway parsing or test mode, a general guest process wrapper or a private copy of the port search, and any change to nvx-init's ownership of its own announcer.

Size

Measured against feature/nvx-refactor 3c3dfce1: 52 core lines (estimate 80, stop 160) in 4 counted files (estimate 3):

File Core lines
guest/ingress/mod.rs 40
guest/sys/spawn.rs 10
guest/sys/mod.rs 1
guest/init.rs 1

These don't count:

  • guest/mod.rs, which only hides ingress, and guest/sys/socket.rs, whose only changes are to docs;
  • the deleted guest/ingress/announcer.rs;
  • tests, docs, the case matrix and the public-API snapshot;
  • the runtime adapter, which is test code under tests/.

Tests of the area

  • guest::ingress::tests, in nvx-rs/src/guest/ingress/tests.rs:
    • kept: decimal_files_hold_one_plain_number;
    • added: an_announcer_runs_its_program_with_its_socket_in_a_session_of_its_own, an_announcer_starts_with_every_signal_s_default_disposition_and_none_blocked and an_announcer_does_not_start_without_its_program_when_its_caller_ignores_sigchld;
    • moved and rewritten: an_announcer_whose_program_does_not_run_does_not_start, from guest::ingress::announcer::tests.
  • guest::ingress::announcer::tests retire with Announcer: an_announcer_runs_its_program_with_its_socket_until_it_is_stopped, an_announcer_that_ends_polls_readable_and_keeps_its_status, a_dropped_announcer_ends and start_errors_name_their_cause. Their cases that still apply move, as "Changes to existing tests" below says.
  • The other 37 tests of guest::ingress are kept unchanged: address (3), collect (10), diag (2), encode (3), sender (7), table (11) and test_mode (1).
  • guest_tools:
    • kept unchanged: ingress_test_mode_prints_the_conformance_vector_from_prebuilt_binaries, ingress_test_mode_preserves_udp_settling_between_snapshots, ingress_rejects_bad_invocations_and_test_snapshots and ingress_inherits_only_an_ipv4_datagram_socket_bound_to_a_privileged_source_port;
    • rewritten: ingress_start_fails_when_the_announcer_does_not_start.
  • guest::init::tests::restore is kept unchanged. Its tests still replace the restored announcer's program through tests::restore::announcer_program.
  • Runtime adapter:
    • worker::tests adds announcer_launch_keeps_the_socket_and_monitors_its_owned_child, announcer_drop_stops_and_reaps_the_child_that_it_owns and announcer_failed_exec_reports_the_cause_and_leaves_no_child, and keeps its PID 1 tests;
    • worker::activation::tests::each_class_of_failure_ends_the_clone_with_its_own_status and the guest_session fake's apply are rewritten;
    • every other test is kept.

Validation

feature/nvx-refactor has no scripts/local_gates.py, so the checks below ran from this branch's own action definitions (check-nvx-rs), with the pinned toolchain (1.95.0; MSRV 1.89). They ran on tree 9c014588, the previous head 2928e3c2 on 7bc238eb, unless a check names another. The Linux hosts held that tree as this branch's patch applied to the base, which git write-tree confirmed.

This head, 797e0ac0, is that branch rebased onto 3c3dfce1 (#1490, #1495 and #1488) without conflicts. git range-diff shows only one content change: the case matrix's new row and count, which are docs. CI validates the rebased code. On this head, these pass: a check of every pointer of the case matrix (every nvx-rs/…::test, scenario, Python test class and path that it names exists), and of its rows against the adapter's sources (169 tests, each named once; counts 169, 0, 9 and 160), together with check_markdown_links.py, check_test_layout.py and check_test_changes.py. At 3c3dfce1, the same check finds the adapter's 166 tests listed; at this head before the new row, it finds the three new tests without a row.

Windows (local):

Check Result
cargo fmt --all --check, for nvx-rs and the runtime adapter Passed
Clippy with -D warnings: the Lint step's five runs and -p nvx --lib --no-default-features Passed
The runtime adapter's protocol-only and host-only Clippy runs Passed
check_test_layout.py, public_api.py (both snapshots) and check_test_changes.py Passed

Linux, on nvx-kvm-test (linux-kvm, virtual machine, Azure Linux 3, kernel 6.6):

Check Result
cargo fmt --all --check Passed
Clippy with -D warnings: the Lint step's five runs, -p nvx --lib --no-default-features, and the musl guest run of check-guest-binaries Passed
cargo doc --all-features with -D warnings Passed
MSRV: cargo +1.89 check --all-targets --all-features Passed
macOS: cargo check --all-targets --all-features --target aarch64-apple-darwin Passed
public_api.py and check_test_layout.py Passed
guest::ingress unit tests, GNU --all-features and musl --features guest 42 passed on each
guest_tools ingress cases, GNU and musl 5 passed on each
nvx-init's guest::init::tests::restore, musl 6 passed, 1 ignored
Runtime adapter, guest-only (musl): Clippy, build and tests Passed; 150 tests passed
Runtime adapter, host-only and protocol-only Clippy Passed
Whole musl guest suite of check-guest-binaries Failed: pre-existing, below

Every failure is pre-existing on that host. The whole musl guest suite fails the same 26 tests, by name, that it failed on that host's Linux 6.6 at the earlier base 8b775211, and at this branch's earlier head on it. They are in guest::entry, guest::exec, guest::init::tests::exec and guest::managed_agent::dispatch, and none of them checks the announcer or nvx-init's restore. The new SIGCHLD test fails without the reset, with the standard library's panic, and passes with it, on the GNU and musl targets.

MicroVMs, on nvx-mshv-test (linux-mshv, virtual machine). OpenVMM, the kernel and the Alpine initramfs were built from this change on 3340bbd7 (tree b8214e28). The later base 7bc238eb adds only host sandbox code, which neither the guest nor these scenarios run. python3 scripts/nvx.py test-microvm --backend mshv --scenario untiered-network-policy --scenario private-network-ingress passed both scenarios:

  • untiered-network-policy (13.5 s): the restores whose policies publish the guest's listeners, host loopback and private-network ingress, report announcer=running, which the guest's restore repair started with nvx-ingress start. The host reaches the guest's server through the port that each publishes (NVX-UNTIERED-NETWORK-INBOUND 2 and 1). The deny-all and DNS-egress restores report announcer=none.
  • private-network-ingress (30.3 s).

Before this rebase, the previous head (a2b1ba84, on 8b775211) also passed these:

  • On nvx-mshv-test, with an initramfs built from it: untiered-network-policy, private-network-ingress, host-loopback-policy, platform-network-policy and network-snapshot, and the runtime adapter's vm_clone scenario of the clones of every network policy, one_template_serves_the_clones_of_every_network_policy_at_its_guest_s_address.
  • On nvx-kvm-test: the runtime adapter's protocol-only, host-only and guest-only configurations.

Since then, git range-diff shows that the rebases onto 3340bbd7, 7bc238eb and 3c3dfce1 changed neither commit's code. The only content changes are the SIGCHLD reset and its test, and the case matrix's row. The rest of CI's matrix is left to CI, which runs now that this pull request is Ready: the KVM, MSHV and WHP microVM suites, the guest artifact builds and the benchmarks.

Changes to existing tests

python3 scripts/check_test_changes.py --base origin/feature/nvx-refactor lists 15 changes to existing tests, hence the tests-modified label. It also finds 2 relocated unchanged and 9 added.

Modified:

  1. guest_session's apply helper. It is impl RootOperations for FakeRoot in tests/runtime-adapter/tests/guest_session.rs. The fake's injected announce failure is now the adapter's own AnnounceFailure { error: io::Error::other(problem), teardown: None }, instead of StartError::Spawn(io::Error::other(problem)), since StartError is deleted. The worker classifies both as ACTIVATION_NETWORK, so the tests that inject the failure expect the same status. The helper's doc comment changes to match.
  2. The imports of worker::activation::tests. They drop nvx::guest::ingress::StartError.
  3. an_announcer_whose_program_does_not_run_does_not_start. It moves from guest::ingress::announcer::tests to guest::ingress::tests. It now runs launch with a missing program, instead of Announcer::spawn. It checks the whole message, <path> did not start: No such file or directory (os error 2), instead of StartError::Launch with the exec stage and ENOENT, since the standard library reports the errno but no stage.
  4. ingress_start_fails_when_the_announcer_does_not_start (nvx-rs/tests/guest_tools.rs). The prefix that it accepts for a failed exec drops the exec launch stage failed: , for the same reason. The bind and port prefixes, and exit status 1, don't change.
  5. each_class_of_failure_ends_the_clone_with_its_own_status (worker::activation::tests). Its AnnounceFailure case carries an io::Error of kind AddrInUse, instead of StartError::NoPrivilegedPort, since that is now the field's type. It still expects ACTIVATION_NETWORK.

Removed:

  1. The rest of guest::ingress::announcer::tests goes with the deleted announcer.rs: the mod tests declaration in announcer.rs, the module's inner attributes and imports, and its helpers PATIENCE, program and ended. GATEWAY and socket move unchanged to guest::ingress::tests, the 2 relocated unchanged. The new announcer helper takes the place of program, and the tests no longer need ended, which polled an Announcer's pidfd, or PATIENCE.
  2. an_announcer_runs_its_program_with_its_socket_until_it_is_stopped. Its checks of the program's arguments and of the socket as standard input move to an_announcer_runs_its_program_with_its_socket_in_a_session_of_its_own, which also checks the session, its process group and the missing controlling terminal. Its check of stop retires with Announcer::stop, since start leaves the announcer to init. The adapter's announcer_launch_keeps_the_socket_and_monitors_its_owned_child checks the adapter's own stop.
  3. an_announcer_that_ends_polls_readable_and_keeps_its_status retires with Announcer::pidfd and Announcer::try_wait. Nothing in nvx holds a started announcer any more.
  4. a_dropped_announcer_ends retires with Announcer's Drop. The adapter's announcer_drop_stops_and_reaps_the_child_that_it_owns checks the drop of its own launcher.
  5. start_errors_name_their_cause retires with StartError. bind_announcer_socket keeps its socket, bind and port messages, which ingress_start_fails_when_the_announcer_does_not_start checks through the program, and every spawn failure reads did not start, as item 3 says.

Added:

  • guest::ingress::tests: the tests an_announcer_runs_its_program_with_its_socket_in_a_session_of_its_own, an_announcer_starts_with_every_signal_s_default_disposition_and_none_blocked and an_announcer_does_not_start_without_its_program_when_its_caller_ignores_sigchld, and the helpers announcer and launch_and_wait.
  • The runtime adapter's worker::tests: the tests announcer_launch_keeps_the_socket_and_monitors_its_owned_child, announcer_drop_stops_and_reaps_the_child_that_it_owns and announcer_failed_exec_reports_the_cause_and_leaves_no_child, and the helper announcement_command.

The openvmm gitlink doesn't move.

@ppenna Pedro Henrique Penna (ppenna) added tests-modified Changes existing tests, test data, or test wiring feat-nvx-refactor labels Nov 11, 2026
@github-actions

github-actions Bot commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

This pull request changes existing tests

It modifies or removes 15 existing test asset(s), listed below. Review each with care: a change to a test can hide a regression that the test caught. See doc/contribute.md#changes-to-existing-tests.

Test code

Change What Before After
modified helper fn apply in guest_session (tests), impl RootOperations for FakeRoot`` tests/runtime-adapter/tests/guest_session.rs:1415 tests/runtime-adapter/tests/guest_session.rs:1414
modified imports the imports of worker::activation::tests tests/runtime-adapter/src/worker/activation/tests.rs:1 tests/runtime-adapter/src/worker/activation/tests.rs:1
modified test fn an_announcer_whose_program_does_not_run_does_not_start in guest::ingress::announcer::tests (moved) nvx-rs/src/guest/ingress/announcer/tests.rs:88 nvx-rs/src/guest/ingress/tests.rs:104
modified test fn ingress_start_fails_when_the_announcer_does_not_start in guest_tools (tests) nvx-rs/tests/guest_tools.rs:946 nvx-rs/tests/guest_tools.rs:946
modified test fn each_class_of_failure_ends_the_clone_with_its_own_status in worker::activation::tests tests/runtime-adapter/src/worker/activation/tests.rs:80 tests/runtime-adapter/src/worker/activation/tests.rs:79
removed attributes the inner attributes of guest::ingress::announcer::tests nvx-rs/src/guest/ingress/announcer/tests.rs:1
removed helper const PATIENCE in guest::ingress::announcer::tests nvx-rs/src/guest/ingress/announcer/tests.rs:12
removed helper fn program in guest::ingress::announcer::tests nvx-rs/src/guest/ingress/announcer/tests.rs:19
removed helper fn ended in guest::ingress::announcer::tests nvx-rs/src/guest/ingress/announcer/tests.rs:34
removed imports the imports of guest::ingress::announcer::tests nvx-rs/src/guest/ingress/announcer/tests.rs:1
removed module mod tests in guest::ingress::announcer nvx-rs/src/guest/ingress/announcer.rs:198
removed test fn an_announcer_runs_its_program_with_its_socket_until_it_is_stopped in guest::ingress::announcer::tests nvx-rs/src/guest/ingress/announcer/tests.rs:39
removed test fn an_announcer_that_ends_polls_readable_and_keeps_its_status in guest::ingress::announcer::tests nvx-rs/src/guest/ingress/announcer/tests.rs:64
removed test fn a_dropped_announcer_ends in guest::ingress::announcer::tests nvx-rs/src/guest/ingress/announcer/tests.rs:77
removed test fn start_errors_name_their_cause in guest::ingress::announcer::tests nvx-rs/src/guest/ingress/announcer/tests.rs:106

Relocated unchanged: 2; added: 9. Compared the merge base 3c3dfce1c4c2 with 797e0ac096c8.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues remain to block the announcer-launch ownership refactor.

No open issues 🎉

What changed in this PR

This PR moves announcer launching into nvx-ingress start, removing its dependency on the library spawner ahead of the guest process-module removal tracked by #1120.

Changes:

  • Launches the announcer with std::process::Command, preserving privileged socket binding, session isolation and signal resets.
  • Removes Announcer, PROGRAM and StartError; updates nvx-init and gives the temporary runtime adapter its own launcher.
  • Updates launch regression tests, documentation and the public API snapshot.
File Description
tests/​runtime-adapter/​tests/​guest_session.rs Uses adapter-owned announcement failures in the fake.
tests/​runtime-adapter/​src/​worker/​tests.rs Tests announcer launch, cleanup and failed execution.
tests/​runtime-adapter/​src/​worker/​activation/​tests.rs Updates announcement failure classification coverage.
tests/​runtime-adapter/​src/​worker/​activation.rs Classifies the adapter’s own announcement error.
tests/​runtime-adapter/​src/​worker.rs Adds an adapter-owned launcher and child cleanup.
tests/​runtime-adapter/​README.md Documents adapter ownership and launcher tests.
nvx-rs/​tests/​guest_tools.rs Updates the expected launch-failure message.
nvx-rs/​src/​guest/​sys/​spawn.rs Adds announcer session and signal setup.
nvx-rs/​src/​guest/​sys/​socket.rs Updates socket ownership documentation.
nvx-rs/​src/​guest/​sys/​mod.rs Exposes the private announcer configuration helper.
nvx-rs/​src/​guest/​mod.rs Hides ingress and updates module documentation.
nvx-rs/​src/​guest/​init.rs Names the announcer executable directly.
nvx-rs/​src/​guest/​ingress/​tests.rs Tests socket inheritance, sessions, signals and launch failures.
nvx-rs/​src/​guest/​ingress/​mod.rs Implements direct socket binding and announcer spawning.
nvx-rs/​src/​guest/​ingress/​announcer/​tests.rs Removes the retired library spawner’s tests.
nvx-rs/​src/​guest/​ingress/​announcer.rs Removes the library spawner and its public types.
nvx-rs/​README.md Documents the revised start implementation.
nvx-rs/​public-api/​linux.txt Records removed APIs and the hidden ingress module.

Review effort: Balanced

Enrique Saurez and others added 2 commits November 11, 2026 13:57
The runtime adapter's guest worker starts the announcer of a clone's
listeners after the process-free application with
nvx::guest::ingress::Announcer::start, and classifies its StartError.
nvx-ingress start is to spawn its announcer itself, so that Announcer,
PROGRAM and StartError leave nvx (SL6.13c), and the adapter is their
last other user until SL5.2 deletes the adapter.

Give the worker a launcher of its own, Announcement, with the launch
that Announcer::start gave it: it binds a UDP socket to the highest
free privileged source port, from 1023 down to 512, runs
/sbin/nvx-ingress inherit GATEWAY_IPV4 through nvx::guest::spawn with
that socket as its standard input, in a session of its own, with every
signal's default disposition and none blocked, waits until the program
runs, and stops and collects the announcer when the worker tears its
root down or drops it. AnnounceFailure carries the launcher's io::Error,
and the guest-session fake fails with it, so both still end the clone
with ACTIVATION_NETWORK.

The worker's new unit tests check the launch, the stop and the drop,
and a failed exec, which leaves no child: they take over the cases of
nvx's Announcer tests, which the next commit retires with Announcer.
The case matrix gives them a fate: they retire with the adapter, and
it points to the tests of nvx-ingress start's own launch.

Validated on nvx-kvm-test (linux-kvm, virtual machine), where the
adapter's protocol-only, host-only and musl guest-only configurations
pass their CI checks, the new unit tests among them, and on
nvx-mshv-test (linux-mshv, virtual machine), where vm_clone's scenario
of the clones of every network policy passes: the host reaches a
clone's listener once the announcer that Announcement started announced
it.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
nvx-ingress start was the last user in nvx of Announcer, the library
spawner of the announcer of a clone's listeners, which depends on the
guest::spawn and guest::process modules that later PRs delete.

start now binds the announcer's socket through the shared
bind_privileged search, to the highest free privileged source port from
1023 down to 512, and spawns /sbin/nvx-ingress inherit GATEWAY_IPV4
with std::process::Command, with that socket as its standard input,
and a pre-exec hook of the private OS layer, sys::configure_announcer,
which gives it a session of its own and every signal's default
disposition, none blocked, as Announcer::start did. It still exits with
0 once the program runs, and with 1 when it does not start, without
waiting for any announcement. The message of a failed start no longer
names the launch stage, which the standard library does not report.

The standard library's spawn collects the status of a child that does
not run the program, and panics when the kernel collected it first, as
it does every child's when the caller ignores SIGCHLD, a disposition
that exec keeps. So start restores SIGCHLD's default disposition with
sys::reset_child_signal before it spawns, as nvx-init does before it
collects its children, and still exits with 1 then, as it did with
Announcer::start, which ignored a failure of that collection.

Announcer, PROGRAM and StartError go with their tests, and
guest::ingress, whose only public item is now its hidden main, becomes
hidden. nvx-init's restored announcer, which took its path from
PROGRAM, names /sbin/nvx-ingress itself; it still owns its announcer.

The launch's new tests run a script in place of the program, and check
its arguments, its socket as standard input, its own session without a
terminal, its signals, which none of the caller's ignored or blocked
ones reach, and a program that does not run, also from a caller that
ignores SIGCHLD, where the spawn panics without the reset. They take
over the cases of the retired Announcer tests that still apply; the
cases of Announcer's pidfd, stop, drop and StartError go with them.
ingress_start_fails_when_the_announcer_does_not_start takes the new
message of a failed exec.

Validated on nvx-kvm-test (linux-kvm, virtual machine), on
feature/nvx-refactor 7bc238e: format, the Lint step's five Clippy
runs, -p nvx --lib --no-default-features and the musl guest run,
documentation, public API, test layout, MSRV and macOS checks pass,
and so do the launch's tests, guest_tools's ingress cases and
nvx-init's restore tests on the GNU and musl targets. The SIGCHLD case
fails without the reset, with the standard library's panic, and passes
with it. The whole musl guest suite fails only the 26 tests that it
failed on that host's Linux 6.6 at the earlier base 8b77521. On
nvx-mshv-test (linux-mshv, virtual machine), with OpenVMM, a kernel
and an initramfs built from this change on 3340bbd, test-microvm's
untiered-network-policy and private-network-ingress pass: the untiered
restores whose policies publish the guest's listeners report their
announcer running, and the host reaches the guest's server through the
port that it publishes. Before the SIGCHLD reset, on 8b77521,
host-loopback-policy, platform-network-policy and network-snapshot
passed there too.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues remain for the announcer startup refactor.

No open issues 🎉

Review effort: Balanced

@ppenna
Pedro Henrique Penna (ppenna) merged commit 584c2dd into feature/nvx-refactor Nov 11, 2026
85 of 88 checks passed
@ppenna
Pedro Henrique Penna (ppenna) deleted the agents/slim-sl6-13c-ingress-announcer branch November 11, 2026 22:17
Pedro Henrique Penna (ppenna) added a commit that referenced this pull request Nov 11, 2026
The first draft of the guidelines predates the nvx-init that
feature/nvx-refactor now holds: #1453 routes the new sandbox boots
to it, #1431 serves capture requests, #1447 activates repaired
sessions, #1439 keeps a restore's announcer as a helper, and #1490
runs sandbox run through it too. Check each statement against that
code, and correct those that did not hold:

- an execution takes the VM's one workload identity, which nvx-init
  resolves, or creates, once before its switch, not an account mode
  of its own request, which nothing selects yet;
- the child also drops its capability bounding set, and nvx-init
  kills an execution's process group when its leader ends;
- nvx-init captures only the Fresh boot of a platform capture,
  refuses a session with a root with ENOTSUP, and shares one
  30-second deadline among its checks, its sweep and the capture;
- the restored broker restarts at its first epoch with a reset
  queued, and nvx-init fails on anything but that reset;
- the host sends no MAPS for an empty mapping table, which no
  nvx_maps token announces;
- no launch of NVX's CLI carries OpenVMM's older lifecycle token,
  which still routes a layered launch to the older init agent;
- since #1494, no call of nvx starts the announcer: nvx-init forks
  it and runs /sbin/nvx-ingress itself, and nvx-ingress start runs
  it for an agent that cannot hold it;
- the crate still keeps older calls that start processes, which
  nvx-init does not use.

Quote, and compile, the space's steps in the order of nvx-init's
cold boot and restore, and replace the capture excerpt with one that
handles each outcome and disposition. The steps compile in SL5.1a's
unit test of nvx-init's boot, the_reference_space_steps_compile,
which now holds them as the guidelines quote them, and the
guidelines link SL5.1a's guest-workflows example. Organize the page
by ownership, the space, the executions, the capture, the transport,
the restore, failures and replay. Trim design 4.2 and 4.3 to the
architecture and boundaries of nvx-init and of the older layered and
blockless roots, which still run. Link the guidelines from the
rustdoc of guest::activation too, list the page in the project
structure, and give the case matrix the doc tests that the
guidelines quote, and the lines to which the links move two others.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pedro Henrique Penna (ppenna) added a commit that referenced this pull request Nov 11, 2026
The first draft of the guidelines predates the nvx-init that
feature/nvx-refactor now holds: #1453 routes the new sandbox boots
to it, #1431 serves capture requests, #1447 activates repaired
sessions, #1439 keeps a restore's announcer as a helper, and #1490
runs sandbox run through it too. Check each statement against that
code, and correct those that did not hold:

- an execution takes the VM's one workload identity, which nvx-init
  resolves, or creates, once before its switch, not an account mode
  of its own request, which nothing selects yet;
- the child also drops its capability bounding set, and nvx-init
  kills an execution's process group when its leader ends;
- nvx-init captures only the Fresh boot of a platform capture,
  refuses a session with a root with ENOTSUP, and shares one
  30-second deadline among its checks, its sweep and the capture;
- the restored broker restarts at its first epoch with a reset
  queued, and nvx-init fails on anything but that reset;
- the host sends no MAPS for an empty mapping table, which no
  nvx_maps token announces;
- no launch of NVX's CLI carries OpenVMM's older lifecycle token,
  which still routes a layered launch to the older init agent;
- since #1494, no call of nvx starts the announcer: nvx-init forks
  it and runs /sbin/nvx-ingress itself, and nvx-ingress start runs
  it for an agent that cannot hold it;
- the crate still keeps older calls that start processes, which
  nvx-init does not use.

Quote, and compile, the space's steps in the order of nvx-init's
cold boot and restore, and replace the capture excerpt with one that
handles each outcome and disposition. The steps compile in SL5.1a's
unit test of nvx-init's boot, the_reference_space_steps_compile,
which now holds them as the guidelines quote them, and the
guidelines link SL5.1a's guest-workflows example. Organize the page
by ownership, the space, the executions, the capture, the transport,
the restore, failures and replay. Trim design 4.2 and 4.3 to the
architecture and boundaries of nvx-init and of the older layered and
blockless roots, which still run. Link the guidelines from the
rustdoc of guest::activation too, list the page in the project
structure, and give the case matrix the doc tests that the
guidelines quote, and the lines to which the links move two others.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pedro Henrique Penna (ppenna) added a commit that referenced this pull request Nov 13, 2026
The first draft of the guidelines predates the nvx-init that
feature/nvx-refactor now holds: #1453 routes the new sandbox boots
to it, #1431 serves capture requests, #1447 activates repaired
sessions, #1439 keeps a restore's announcer as a helper, and #1490
runs sandbox run through it too. Check each statement against that
code, and correct those that did not hold:

- an execution takes the VM's one workload identity, which nvx-init
  resolves, or creates, once before its switch, not an account mode
  of its own request, which nothing selects yet;
- the child also drops its capability bounding set, and nvx-init
  kills an execution's process group when its leader ends;
- nvx-init captures only the Fresh boot of a platform capture,
  refuses a session with a root with ENOTSUP, and shares one
  30-second deadline among its checks, its sweep and the capture;
- the restored broker restarts at its first epoch with a reset
  queued, and nvx-init fails on anything but that reset;
- the host sends no MAPS for an empty mapping table, which no
  nvx_maps token announces;
- no launch of NVX's CLI carries OpenVMM's older lifecycle token,
  which still routes a layered launch to the older init agent;
- since #1494, no call of nvx starts the announcer: nvx-init forks
  it and runs /sbin/nvx-ingress itself, and nvx-ingress start runs
  it for an agent that cannot hold it;
- the crate still keeps older calls that start processes, which
  nvx-init does not use.

Quote, and compile, the space's steps in the order of nvx-init's
cold boot and restore, and replace the capture excerpt with one that
handles each outcome and disposition. The steps compile in SL5.1a's
unit test of nvx-init's boot, the_reference_space_steps_compile,
which now holds them as the guidelines quote them, and the
guidelines link SL5.1a's guest-workflows example. Organize the page
by ownership, the space, the executions, the capture, the transport,
the restore, failures and replay. Trim design 4.2 and 4.3 to the
architecture and boundaries of nvx-init and of the older layered and
blockless roots, which still run. Link the guidelines from the
rustdoc of guest::activation too, list the page in the project
structure, and give the case matrix the doc tests that the
guidelines quote, and the lines to which the links move two others.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pedro Henrique Penna (ppenna) added a commit that referenced this pull request Nov 13, 2026
The first draft of the guidelines predates the nvx-init that
feature/nvx-refactor now holds: #1453 routes the new sandbox boots
to it, #1431 serves capture requests, #1447 activates repaired
sessions, #1439 keeps a restore's announcer as a helper, and #1490
runs sandbox run through it too. Check each statement against that
code, and correct those that did not hold:

- an execution takes the VM's one workload identity, which nvx-init
  resolves, or creates, once before its switch, not an account mode
  of its own request, which nothing selects yet;
- the child also drops its capability bounding set, and nvx-init
  kills an execution's process group when its leader ends;
- nvx-init captures only the Fresh boot of a platform capture,
  refuses a session with a root with ENOTSUP, and shares one
  30-second deadline among its checks, its sweep and the capture;
- the restored broker restarts at its first epoch with a reset
  queued, and nvx-init fails on anything but that reset;
- the host sends no MAPS for an empty mapping table, which no
  nvx_maps token announces;
- no launch of NVX's CLI carries OpenVMM's older lifecycle token,
  which still routes a layered launch to the older init agent;
- since #1494, no call of nvx starts the announcer: nvx-init forks
  it and runs /sbin/nvx-ingress itself, and nvx-ingress start runs
  it for an agent that cannot hold it;
- the crate still keeps older calls that start processes, which
  nvx-init does not use.

Quote, and compile, the space's steps in the order of nvx-init's
cold boot and restore, and replace the capture excerpt with one that
handles each outcome and disposition. The steps compile in SL5.1a's
unit test of nvx-init's boot, the_reference_space_steps_compile,
which now holds them as the guidelines quote them, and the
guidelines link SL5.1a's guest-workflows example. Organize the page
by ownership, the space, the executions, the capture, the transport,
the restore, failures and replay. Trim design 4.2 and 4.3 to the
architecture and boundaries of nvx-init and of the older layered and
blockless roots, which still run. Link the guidelines from the
rustdoc of guest::activation too, list the page in the project
structure, and give the case matrix the doc tests that the
guidelines quote, and the lines to which the links move two others.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat-nvx-refactor tests-modified Changes existing tests, test data, or test wiring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants