Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Don't crash if SIGINT happens while printing an exception#384

Merged
edolstra merged 3 commits into
mainfrom
eelcodolstra/nix-289-detsys-nix-crashes-on-sigint-with-internal-error
Mar 17, 2026
Merged

Don't crash if SIGINT happens while printing an exception#384
edolstra merged 3 commits into
mainfrom
eelcodolstra/nix-289-detsys-nix-crashes-on-sigint-with-internal-error

Conversation

@edolstra
Copy link
Copy Markdown
Collaborator

@edolstra edolstra commented Mar 16, 2026

Motivation

This prevents crashes like

Determinate Nix crashed. This is a bug. Please report this at https://github.com/DeterminateSystems/nix-src/issues with the following information included:

Exception: nix::Interrupted: error: interrupted by the user
Stack trace:
 0# 0x000000000038F279 in nix
 1# 0x00007FFFF6C2B1AA in /nix/store/dj06r96j515npcqi9d8af1d1c60bx2vn-gcc-14.3.0-lib/lib/libstdc++.so.6
 2# std::unexpected() in /nix/store/dj06r96j515npcqi9d8af1d1c60bx2vn-gcc-14.3.0-lib/lib/libstdc++.so.6
 3# 0x00007FFFF6C2B427 in /nix/store/dj06r96j515npcqi9d8af1d1c60bx2vn-gcc-14.3.0-lib/lib/libstdc++.so.6
 4# 0x00007FFFF7FABFD4 in /home/eelco/Dev/nix/outputs/out/lib/libnixutil.so.2.33.3
 5# nix::PosixSourceAccessor::readFile(nix::CanonPath const&, nix::Sink&, std::function<void (unsigned long)>) in /home/eelco/Dev/nix/outputs/out/lib/libnixutil.so.2.33.3
 6# nix::SourceAccessor::readFile[abi:cxx11](nix::CanonPath const&) in /home/eelco/Dev/nix/outputs/out/lib/libnixutil.so.2.33.3
 7# nix::ForwardingSourceAccessor::readFile[abi:cxx11](nix::CanonPath const&) in /home/eelco/Dev/nix/outputs/out/lib/libnixfetchers.so.2.33.3
 8# nix::MountedSourceAccessorImpl::readFile[abi:cxx11](nix::CanonPath const&) in /home/eelco/Dev/nix/outputs/out/lib/libnixutil.so.2.33.3
 9# nix::FilteringSourceAccessor::readFile[abi:cxx11](nix::CanonPath const&) in /home/eelco/Dev/nix/outputs/out/lib/libnixfetchers.so.2.33.3
10# nix::SourcePath::readFile[abi:cxx11]() const in /home/eelco/Dev/nix/outputs/out/lib/libnixutil.so.2.33.3
11# 0x00007FFFF7F2B9FA in /home/eelco/Dev/nix/outputs/out/lib/libnixutil.so.2.33.3
12# nix::Pos::getCodeLines() const in /home/eelco/Dev/nix/outputs/out/lib/libnixutil.so.2.33.3
13# 0x00007FFFF7EB5C20 in /home/eelco/Dev/nix/outputs/out/lib/libnixutil.so.2.33.3
14# 0x00007FFFF7EB5E40 in /home/eelco/Dev/nix/outputs/out/lib/libnixutil.so.2.33.3
15# nix::showErrorInfo(std::ostream&, nix::ErrorInfo const&, bool) in /home/eelco/Dev/nix/outputs/out/lib/libnixutil.so.2.33.3
16# nix::ProgressBar::logEI(nix::ErrorInfo const&) in /home/eelco/Dev/nix/outputs/out/lib/libnixmain.so.2.33.3
17# 0x00007FFFF715F1E0 in /home/eelco/Dev/nix/outputs/out/lib/libnixmain.so.2.33.3
18# 0x000000000044E4B4 in nix
19# 0x00007FFFF687647E in /nix/store/g8zyryr9cr6540xsyg4avqkwgxpnwj2a-glibc-2.40-66/lib/libc.so.6
20# __libc_start_main in /nix/store/g8zyryr9cr6540xsyg4avqkwgxpnwj2a-glibc-2.40-66/lib/libc.so.6
21# 0x0000000000349CE5 in nix

I.e. Ctrl-C is hit in PosixSourceAccessor::readFile() while printing the Nix stack trace. This causes an unhandled exception in handleExceptions() at top-level.

Context

Summary by CodeRabbit

  • Bug Fixes
    • Improved error handling so user-facing error messages still appear even if internal logging fails.
    • Made source-reading more resilient: failures to load source content are now gracefully handled, avoiding crashes or confusing behavior.

This wasn't handling Interrupted, since it's a subclass of BaseError,
not Error. Since this is called from handleExceptions() while printing
exceptions, the uncaught exception here was causing Nix to crash with
a call to std::unexpected().
This hardens Nix against uncaught exceptions (like Interrupted) while
printing exceptions.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 16, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3b82ff91-6305-4ee1-9e40-742bc7c016bb

📥 Commits

Reviewing files that changed from the base of the PR and between 47f1764 and 470d2a0.

📒 Files selected for processing (1)
  • src/libutil/position.cc
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/libutil/position.cc

📝 Walkthrough

Walkthrough

Centralized and hardened error logging in exception handlers and broadened an exception catch in source-path reading to return std::nullopt on any thrown exception (not just Error).

Changes

Cohort / File(s) Summary
Error Handling Defense
src/libmain/shared.cc
Added a doLog lambda that wraps logError(...) with a fallback print; replaced direct logError calls in UsageError and BaseError handlers to ensure user-facing output even if logging throws.
Exception Handling Broadening
src/libutil/position.cc
Changed exception handler in Pos::getSource() from catching a specific Error to catch (...), returning std::nullopt for any exception thrown during readFile().

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 I nibble code where errors hide,
I wrap each log with careful pride,
If logging trips and stumbles tight,
I print the message into light,
Hoppy fixes — soft and bright.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: preventing crashes when SIGINT/Interrupted exceptions occur during exception printing, which is directly addressed by the code modifications.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch eelcodolstra/nix-289-detsys-nix-crashes-on-sigint-with-internal-error
📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can use Trivy to scan for security misconfigurations and secrets in Infrastructure as Code files.

Add a .trivyignore file to your project to customize which findings Trivy reports.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/libmain/shared.cc`:
- Around line 350-356: The fallback logging lambda doLog currently calls
printError(...) inside its catch handler which itself can throw and therefore
must be guarded; update doLog (used by handleExceptions) so that the call to
printError is wrapped in its own try-catch that swallows any exception (or falls
back to a non-throwing fallback such as writing a raw message to stderr) to
ensure no exception escapes the catch block and unwinds out of handleExceptions;
reference symbols: doLog, logError, printError, handleExceptions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 64ec2e94-8b32-4c4e-8b7b-85a1dd3d571d

📥 Commits

Reviewing files that changed from the base of the PR and between 2581135 and 47f1764.

📒 Files selected for processing (2)
  • src/libmain/shared.cc
  • src/libutil/position.cc

Comment thread src/libmain/shared.cc
Comment on lines +350 to +356
auto doLog = [&](BaseError & e) {
try {
logError(e.info());
} catch (...) {
printError(ANSI_RED "error:" ANSI_NORMAL " Exception while printing an exception.");
}
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Locate printError/logError declarations and implementations.
rg -nP --type=cpp --type=h -C3 '\b(printError|logError)\s*\('

# 2) Check whether printError is declared noexcept anywhere.
rg -nP --type=cpp --type=h '\bprintError\b[^{;]*\bnoexcept\b'

# 3) Inspect nearby bodies to confirm whether printError routes through logger paths.
rg -nP --type=cpp -C8 '\bprintError\s*\('

Repository: DeterminateSystems/nix-src

Length of output: 42788


Guard the fallback logging path from rethrowing.

At line 354, the fallback calls printError(...) without an inner guard. Since printError can throw exceptions (see the comment in util.cc: "printError() also throws when remote is closed"), this path risks unwinding from within a catch block in handleExceptions(), which can cause program termination or undefined behavior.

Proposed hardening
-    auto doLog = [&](BaseError & e) {
+    auto doLog = [&](BaseError & e) {
         try {
             logError(e.info());
         } catch (...) {
-            printError(ANSI_RED "error:" ANSI_NORMAL " Exception while printing an exception.");
+            static constexpr char msg[] = "error: Exception while printing an exception.\n";
+            try {
+                (void)!::write(STDERR_FILENO, msg, sizeof(msg) - 1);
+            } catch (...) {
+                // Never throw while handling exceptions.
+            }
         }
     };
🧰 Tools
🪛 Cppcheck (2.20.0)

[error] 354-354: There is an unknown macro here somewhere. Configuration is required. If ANSI_NORMAL is a macro then please configure it.

(unknownMacro)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/libmain/shared.cc` around lines 350 - 356, The fallback logging lambda
doLog currently calls printError(...) inside its catch handler which itself can
throw and therefore must be guarded; update doLog (used by handleExceptions) so
that the call to printError is wrapped in its own try-catch that swallows any
exception (or falls back to a non-throwing fallback such as writing a raw
message to stderr) to ensure no exception escapes the catch block and unwinds
out of handleExceptions; reference symbols: doLog, logError, printError,
handleExceptions.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Mar 16, 2026

@github-actions github-actions Bot temporarily deployed to pull request March 16, 2026 15:56 Inactive
@grahamc grahamc added this pull request to the merge queue Mar 16, 2026
@edolstra edolstra removed this pull request from the merge queue due to a manual request Mar 16, 2026
@edolstra edolstra enabled auto-merge March 16, 2026 20:13
@github-actions github-actions Bot temporarily deployed to pull request March 16, 2026 20:23 Inactive
@edolstra edolstra added this pull request to the merge queue Mar 16, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to no response for status checks Mar 16, 2026
@edolstra edolstra added this pull request to the merge queue Mar 16, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to no response for status checks Mar 17, 2026
@edolstra edolstra added this pull request to the merge queue Mar 17, 2026
Merged via the queue into main with commit e6364dd Mar 17, 2026
28 checks passed
@edolstra edolstra deleted the eelcodolstra/nix-289-detsys-nix-crashes-on-sigint-with-internal-error branch March 17, 2026 14:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants