-
Notifications
You must be signed in to change notification settings - Fork 1k
fix(tests): stop leaked RabbitMQ test container on process exit #1573
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
ytallo
wants to merge
1
commit into
main
Choose a base branch
from
fix/rabbitmq-test-container-leak
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+32
−0
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: iii-hq/iii
Length of output: 5862
🏁 Script executed:
# Also check if there's a git diff available to see what changed git diff HEAD -- engine/tests/common/rabbitmq_helpers.rsRepository: iii-hq/iii
Length of output: 36
🏁 Script executed:
# Check what changed in the file around lines 2, 18-37, 60-67 git log --oneline -1 -- engine/tests/common/rabbitmq_helpers.rsRepository: iii-hq/iii
Length of output: 127
🏁 Script executed:
Repository: iii-hq/iii
Length of output: 4055
🌐 Web query:
atexit handler safety constraints libc async-safe functions eprintln💡 Result:
atexit handlers in libc have strict safety constraints: they must terminate normally without calling exit again (undefined behavior), avoid longjmp, and cannot rely on consistent global state since they run during process shutdown after static destructors in some cases (e.g., Rust). They are NOT required to be async-signal-safe by POSIX; only _exit and _Exit are signal-safe among termination functions, and stdio functions like printf are unsafe in signal handlers due to buffering and locks. Using eprintln! (Rust's stderr println macro) in an atexit handler is unsafe: - It accesses global Stderr state via Lazy/OnceCell, which may be deinitialized during shutdown, causing panics like "cannot access stderr during shutdown". - println!/eprintln! use thread-local RefCell-wrapped stdout/stderr locks; concurrent calls (e.g., from signal interrupting print) panic on BorrowMutError. - In Rust+C interop, libc::atexit handlers run after Rust's at_exit queue, during/after TLS/static destruction, making std::io access unreliable. Safe alternatives in atexit handlers: - Use low-level write(2) to fd 2 (stderr), which is async-signal-safe. - libc::printf may work if no Rust runtime interference, but not guaranteed async-safe. - Avoid heap allocation, locks, or complex logic. For Rust programs, prefer std::process::exit over libc::exit to run Rust cleanup; for signal safety, use crates like signal-hook and async-signal-safe primitives. No source confirms eprintln! safe in atexit; evidence shows failures.
Citations:
Handle initialization and cleanup errors explicitly, but use safe atexit patterns.
The new exit-cleanup path silently discards both
libc::atexit()registration status anddocker rmexit codes. While the implementation is new (not a regression), it should surface failures to prevent silent leaks.However, the suggested fix has two critical issues:
eprintln!is unsafe in atexit handlers. It accesses global Stderr state which may be deinitialized during process shutdown, causing panics. Use low-levelwrite(2)to stderr fd 2 instead, or avoid output altogether.Suggested ordering is backwards. The proposed diff registers the atexit handler before setting
CONTAINER_ID, so the handler would run with no ID to clean up.Safer approaches:
assert_eq!(libc::atexit(stop_rabbitmq_container), 0, "failed to register RabbitMQ cleanup hook");(now runs at init time, fails early and explicitly)write(2)if diagnostics are needed.🤖 Prompt for AI Agents