nvx-rs: a guest execution's discards stop when its caller lends no buffer
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 初心者へのやさしさ
- 35/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 活発
- 技術スタック
- rust
調査の方向性
Start with nvx-rs/src/guest/exec.rs and nvx-rs/src/guest/exec/binding.rs to trace how caller buffers control discarded stream reads, then inspect the test adapter worker at tests/runtime-adapter/src/worker/executions.rs:656-677. Compare both proposed behavior options and check every repository and downstream user of Execution::next_event and Binding::next; completion requires a recorded decision, matching implementation and documentation with a test, an updated worker, user findings, and a release note.
索引モデルが issue の本文から書いたものです。
説明
Related: #748 (the execution engine and its guest binding), #784 (the test adapter's executions on the shared engine), #858 (signals to an execution). Needs: nothing.
Goal. Decide whether a guest caller can pause the output that it reads from an execution without also pausing the streams that the execution discards. Then make the library's behavior and its documentation agree. The answer changes what callers of nvx::guest::exec may rely on, so this lands with a check of the library's users.
Today (dev 236fd4e0):
- Discards go through the caller's buffer.
Execution::next_event(buffer)reads every output stream into the buffer that the caller lends, "whether the execution returns the bytes or discards them; an empty buffer reads nothing" (nvx-rs/src/guest/exec.rs:849-851).- A discarded stream is read as far as that buffer goes:
Output::read(exec.rs:467-494),Execution::discard(exec.rs:708-713), and the module's flow-control section (exec.rs:32-41). Binding::next(now, buffer)passes its buffer on (nvx-rs/src/guest/exec/binding.rs:201-229, withSTEPSatbinding.rs:60-64). It applies the runner'sRequest::DiscardwithExecution::discard(binding.rs:323).
- Credit is the documented flow-control seam. A stalled peer, sink or transport withholds credit, "so the binding stops reading the stream that waits on it, and nothing else" (
binding.rs:22-24). - Callers also pause reads with an empty buffer. Some callers pause their reads while their own messages wait on a slow transport, so that the output waits in the program's pipes, not in the caller's memory. The only way to pause is to lend an empty buffer.
- The test adapter's worker does this while its connection is backlogged, and once an execution has read its share of a turn (
tests/runtime-adapter/src/worker/executions.rs:656-677). - The managed agent always lends its whole buffer (
nvx-rs/src/guest/managed_agent/exec.rs:281-297).
- The test adapter's worker does this while its connection is backlogged, and once an execution has read its share of a turn (
- The runner discards every open stream at once. On a detach, at once, or when the grace after a cancellation, a timeout, a reset, a drop or a disconnection ends, it drops its queues and discards each stream that is still open (
Runner::detachandRunner::end_grace,nvx-rs/src/exec/runner.rs:757-784). The managed agent also discards both streams together, once its output cap is reached (managed_agent/exec.rs:306-307).
The problem. A stream is discarded once nobody will take the rest of it; today, that is after the workload was asked to end. Draining it lets the stream reach end of file, so that the execution can end and settle. A caller that pauses its reads with an empty buffer stops that draining too:
- The end waits. The execution can't end while the pause lasts: its discarded streams don't reach end of file, so its terminal outcome waits.
- A long pause fences. If the pause outlasts the runner's give-up deadline (the grace and the settlement time after the termination), the runner gives up, and fences an execution that would have settled.
- A writer blocks. A process that still writes to a discarded stream blocks on the full pipe, for example a descendant that the termination hasn't reached.
The test adapter's worker has this problem today: while its connection is backlogged, a discarded stream drains nothing until the backlog clears.
A caller can avoid it only by detecting when every read would be a discard, and lending its buffer then: for example, when the runner buffers nothing and allows no read on any stream. That works only because the runner discards every open stream at once, which no documentation promises. A runner that discarded one stream while the other still flowed would bring the stall back.
Options:
- Discards stop depending on the caller's buffer. The execution reads a discarded stream into a small buffer of its own, so an empty lent buffer pauses only the output that the caller takes. Executions that discard nothing pay nothing.
next_event,Binding::nextandSTEPSdocument the new bound. - The behavior stays, as a documented contract.
- Document that discards read into the lent buffer and stop with it, and that the runner discards every open stream at once.
- Give callers an accessor that says when every read would be a discard, so that no caller has to infer it.
Users of the library to check. Either option changes what callers may rely on. So the change lands with a check of every user of Execution::next_event and Binding::next, in this repository and downstream. Check each for:
- reads paused with an empty or shortened buffer, and any logic that keeps discarded streams draining meanwhile. Option 1 makes such logic unnecessary; option 2 requires it to match the documented contract;
- reliance on an empty buffer reading nothing at all, which option 1 changes;
- a stream discarded with
Execution::discardwhile the other one is still read.
Downstream consumers of the published nvx crate may need to change with the release that carries this. Its release notes say what changed, and what callers must do.
Deliverables:
- a decision between the options, recorded here;
- the change, with its test:
- for option 1, a discarded stream that drains while the caller lends no buffer;
- for option 2, the documented contract and its accessor;
- the test adapter's worker, updated to match;
- the check of the library's users, with its findings posted here.
Done when:
- the behavior and its documentation agree;
- the test adapter no longer stalls a discarded stream while its connection is backlogged;
- the check of the library's users and the release note are done.
- 主要言語
- Rust
- スター
- 758
- フォーク
- 48
- 平均マージ
- 18時間 27分
- マージ済み PR(30日)
- 446
環境構築
このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
microsoft/nvx のほかの issue
-
難易度 1/5 1時間未満 初心者へのやさしさ 85/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 69/100
メンテナーはふだん 1 日以内に返信
-
難易度 4/5 3〜5日 初心者へのやさしさ 35/100
microsoft/nvx#1055 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
ci: move the performance history's commits off dev対応中かも @ppenna が今日担当しました。 オープン
難易度 4/5 3〜5日 初心者へのやさしさ 25/100
メンテナーはふだん 1 日以内に返信
-
難易度 4/5 3〜5日 初心者へのやさしさ 25/100
メンテナーはふだん 1 日以内に返信
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
メンテナーはふだん 1 日以内に返信
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 77/100
yunfie-twitter/Palleria#474 ·
メンテナーはふだん 1 日以内に返信
-
good first issue help wanted
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
servo/rust-smallvec#827 ·
メンテナーはふだん 1 日以内に返信
-
bug tests
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
メンテナーはふだん 1 日以内に返信