Sitelet https://github.com/PECOS-packages/PECOS/pull/1041
Skip to content

Latch failed native shot_end and plugin init so a failed shot is never certified - #1041

Open
ciaranra wants to merge 3 commits into
devfrom
fix/shot-end-failure-latches
Open

ciaranra wants to merge 3 commits into
devfrom
fix/shot-end-failure-latches

Conversation

@ciaranra

@ciaranra ciaranra commented Oct 6, 2026

Copy link
Copy Markdown
Member

Fixes #1036.

SeleneRuntime must not certify a shot, or keep running work, after a native lifecycle call failed. Two calls broke that.

shot_end

shot_end takes active_shot before calling the plugin's shot_end_fn. When the descriptor lookup or the native call failed, the error was returned but not latched, so a second shot_end() found no active shot, skipped the plugin and returned Ok(Shot). Now the failure latches the runtime's failure state (batch_failure) and returns the real error. Every operation, including another shot_end, errors until a reset succeeds, because the plugin may have partly finalized the shot.

Plugin init

On the flat and metadata routes, prepare_runtime_input runs outside with_native_mutation, so a failed init_fn (nonzero errno, or success with a null handle) was not latched either: shot_end then certified an empty shot for a plugin that never started, and later input retried init without a reset. Both init failures now latch too. Ordinary input rejections (capacity, duplicate allocation) are unchanged.

A sweep of the other plugin lifecycle calls found them already latched (lowering, draining, measurement delivery and shot_start run under with_native_mutation; a failed exit latches since #1034). QisEngine already latched a shot_end failure at engine level, so through the engine the shot_end case was only reachable by using SeleneRuntime directly.

Tests

Both run in a child process, because the descriptor fixture is process-wide.

  • failed_shot_end_is_never_certified_on_retry: the plugin's shot_end fails once (errno 9), and rxy and shot_end calls are counted. On every lowering route: the first shot_end() reports the error; a retry fails with no second native call; a valid X(0) reports the latched error and never reaches the plugin; after a successful reset a full shot runs and finalizes for real. Removing the latch fails at the retry; removing it and skipping the retry check fails at X(0).
  • failed_init_is_latched_until_reset (replaces the null-instance test from Keep qubit handles live through measurement and start every qubit lifetime with exactly one prep #1017): for an init that returns errno 5 and one that returns success with a null handle, on every route: the error names the failure, shot_end() fails, and further input reports the latched error without calling init again. Removing the init latch fails at shot_end().

Verification

@ciaranra ciaranra added the ci:full-rust Run full Rust tests on Linux, macOS, and Windows before merge label Oct 6, 2026
@ciaranra
ciaranra force-pushed the fix/shot-end-failure-latches branch from 91701f5 to 500b613 Compare October 6, 2026 03:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci:full-rust Run full Rust tests on Linux, macOS, and Windows before merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SeleneRuntime::shot_end certifies a shot on retry after native shot_end failed

1 participant