Make stderr output exclusive to fatal paths and consistent across all fatal paths

オープン
#8,623 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

@achamayou がすでに取り組んでいます。

2026年11月5日 から。

  • #8690 @achamayou による — オープン

評価

難易度
5/5
見積もり時間
1週間以上
初心者へのやさしさ
35/100
issue の種類
機能追加
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
cpp, rust

調査の方向性

Start by reading the console logger and fatal reporting code in include/ccf/ds/logger.h and src/host/runtime_control.h, then trace the join callers in src/node/node_state.h and the post-join failure examples in src/node/rpc/frontend.h and src/host/socket.h. Review the Rust panic-hook handling in src/rust/ccf-app/src/lib.rs and existing regression tests for process output. Done means documenting the stderr contract and scope, covering fatal and recoverable paths, and ensuring fatal diagnostics avoid confidential request or KV data.

索引モデルが issue の本文から書いたものです。

説明

Is your feature request related to a problem? Please describe.
CCF's stderr is not currently a consistent indicator of fatal failure.
Some fatal paths write to stderr, while others log only to stdout before aborting or exiting.
Operators therefore cannot rely on an empty stderr to mean that no fatal error occurred, or use stderr alone to capture fatal diagnostics.

Source inspection found the following behavior:

  • Normal framework and application logging uses stdout at every severity, including fail and fatal, for both text and JSON console loggers. LOG_FATAL_FMT and CCF_APP_FATAL do not themselves terminate execution or write to stderr.
  • RuntimeControlImpl::report_fatal_error() writes and flushes the first reported error to stderr, then requests enclave shutdown. All four current production call sites are on the join path: oversized join responses; non-retryable transport/TLS failures, including certificate trust failures; fatal join client errors, except the supported fresh-snapshot retry case; and startup-snapshot installation failures during join completion.
  • CLI11 writes command-line parsing errors to stderr. Help and version output use stdout.
  • files::slurp() writes required-file open/read failures to stderr and exits when optional == false.
  • Post-join fatal paths can log to stdout and call abort() without a CCF stderr diagnostic. Examples include transaction serialisation failure in the RPC frontend and socket resolve/listen failure handlers. abort() itself does not print a diagnostic; a supervising shell may separately report the signal.
  • Native assertion failures can emit stderr diagnostics when assertions are enabled. Uncaught C++ exceptions and Rust's default panic hook can also produce runtime diagnostics. The experimental Rust SDK suppresses panic diagnostics for caught application-callback panics, but forwards other panics to the previously installed hook.
  • Applications and dependencies can write directly to stderr, for example through Rust's eprint!/eprintln!. Such output is not governed by CCF's logger today.

Describe the solution you'd like
Establish and enforce the following contract for CCF node stderr:

  1. Only fatal paths write to stderr. Recoverable errors, warnings, and ordinary application logging must not produce stderr output.
  2. All fatal paths consistently write a useful diagnostic to stderr before the node terminates, including failures after joining the network. This must not depend on whether the path uses report_fatal_error(), logs and aborts, or exits through another mechanism.

Preserve useful stdout logging while ensuring stderr has the same meaning across startup, join, and steady-state operation.
Document the contract and its scope, including application/dependency writes and runtime-generated diagnostics.
Distinguish actual fatal termination paths from the fatal log-level label: emitting a log entry at that level does not currently imply termination.
Fatal diagnostics must not expose confidential request or KV data.
Add regression coverage demonstrating both sides of the contract: fatal paths emit stderr diagnostics, and recoverable paths do not.

Describe alternatives you've considered
Continue parsing stdout severity labels and combining them with process exit status.
This leaves stderr inconsistent, and the fatal severity label alone is not equivalent to a fatal termination path.
Routing all fail or fatal log entries to stderr without considering control flow would not establish the requested fatal-path-only contract.

Additional context
Findings are based on source inspection at commit 4bb1570da7264b0daa417f2c6e4e497124f0b8d0, rather than an exhaustive runtime reproduction.
Relevant source locations:

主要言語
C++
スター
876
フォーク
264
平均マージ
1日 16時間
マージ済み PR(30日)
127

環境構築

Codespaces で開く

このプロジェクトの開発コンテナを、あなたの GitHub アカウントでブラウザ上に起動します。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

microsoft/CCF のほかの issue

microsoft/CCF の issue をすべて見る

似ている issue

C++ の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。