Skip to content

🚨 test: Fix race condition in TestTimeout_ContextPropagation#4119

Open
adrian-lin-1-0-0 wants to merge 3 commits intogofiber:mainfrom
adrian-lin-1-0-0:chore/timeout-test-race-fix
Open

🚨 test: Fix race condition in TestTimeout_ContextPropagation#4119
adrian-lin-1-0-0 wants to merge 3 commits intogofiber:mainfrom
adrian-lin-1-0-0:chore/timeout-test-race-fix

Conversation

@adrian-lin-1-0-0
Copy link

Description

Fix a potential race condition in TestTimeout_ContextPropagation and strengthen its assertions. The original test used atomic.Bool which could be read before the handler goroutine had written to it, since the timeout middleware returns immediately via the Abandon mechanism. This change replaces it with a buffered channel for proper synchronization.

Relates to #3671

How to reproduce the race (before this fix)

go test -run TestTimeout_ContextPropagation -count=500 ./middleware/timeout/

output

--- FAIL: TestTimeout_ContextPropagation (0.05s)
    timeout_test.go:108: 
                Error Trace:./fiber/middleware/timeout/timeout_test.go:108
                Error:      Should be true
                Test:       TestTimeout_ContextPropagation
                Messages:   Handler should have detected context cancelation
FAIL
FAIL    github.com/gofiber/fiber/v3/middleware/timeout   26.277s
FAIL

Changes introduced

List the new features or adjustments introduced in this pull request. Provide details on benchmarks, documentation updates, changelog entries, and if applicable, the migration guide.

  • Benchmarks: Describe any performance benchmarks and improvements related to the changes.
  • Documentation Update: Detail the updates made to the documentation and links to the changed files.
  • Changelog/What's New: Include a summary of the additions for the upcoming release notes.
  • Migration Guide: If necessary, provide a guide or steps for users to migrate their existing code to accommodate these changes.
  • API Alignment with Express: Explain how the changes align with the Express API.
  • API Longevity: Discuss the steps taken to ensure that the new or updated APIs are consistent and not prone to breaking changes.
  • Examples: Provide examples demonstrating the new features or changes in action.

Type of change

  • Code consistency (non-breaking change which improves code reliability and robustness)

Checklist

  • Followed the inspiration of the Express.js framework for new functionalities, making them similar in usage.
  • Conducted a self-review of the code and provided comments for complex or critical parts.
  • Updated the documentation in the /docs/ directory for Fiber's documentation.
  • Added or updated unit tests to validate the effectiveness of the changes or new features.
  • Ensured that new and existing unit tests pass locally with the changes.
  • Verified that any new dependencies are essential and have been agreed upon by the maintainers/community.
  • Aimed for optimal performance with minimal allocations in the new code.
  • Provided benchmarks for the new code to analyze and improve upon.

Commit formatting

Please use emojis in commit messages for an easy way to identify the purpose or intention of a commit. Check out the emoji cheatsheet here: CONTRIBUTING.md

Copilot AI review requested due to automatic review settings February 28, 2026 17:33
@adrian-lin-1-0-0 adrian-lin-1-0-0 requested a review from a team as a code owner February 28, 2026 17:33
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request focuses on improving the stability and accuracy of a critical test case for the timeout middleware. It resolves a race condition that could lead to flaky test results and enhances the test's ability to verify correct context propagation under timeout conditions, ensuring the middleware behaves as expected.

Highlights

  • Race Condition Fix: Addressed a potential race condition in TestTimeout_ContextPropagation by replacing atomic.Bool with a buffered channel for proper synchronization, ensuring the handler goroutine's state is reliably captured.
  • Strengthened Assertions: Improved the assertions in TestTimeout_ContextPropagation to specifically check for context.DeadlineExceeded when the timeout occurs, providing a more robust validation of context propagation.
  • Test Reliability: Enhanced the reliability and robustness of the TestTimeout_ContextPropagation test, making it less prone to intermittent failures and more accurately reflecting the expected behavior of the timeout middleware.
Changelog
  • middleware/timeout/timeout_test.go
    • Fixed a race condition in TestTimeout_ContextPropagation by replacing atomic.Bool with a buffered channel for inter-goroutine communication.
    • Strengthened assertions in TestTimeout_ContextPropagation to explicitly check for context.DeadlineExceeded.
Activity
  • Conducted a self-review of the code and provided comments for complex or critical parts.
  • Added or updated unit tests to validate the effectiveness of the changes or new features.
  • Ensured that new and existing unit tests pass locally with the changes.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 28, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aec98e7 and ae4ebfb.

📒 Files selected for processing (1)
  • middleware/timeout/timeout_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • middleware/timeout/timeout_test.go

Walkthrough

Updates TestTimeout_ContextPropagation to observe handler completion via a buffered error channel (errCh) instead of an atomic flag, using a 500ms timer in the handler and asserting context.DeadlineExceeded when the request times out.

Changes

Cohort / File(s) Summary
Test Refactor
middleware/timeout/timeout_test.go
Replaced atomic flag with a buffered errCh to observe handler outcome; handler uses a 500ms timer and sends nil on normal completion or the context error on cancellation. Test waits (≤1s) for context.DeadlineExceeded and asserts StatusRequestTimeout.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Suggested reviewers

  • sixcolors
  • efectn
  • gaby

Poem

🐰 I tapped my nose and set a chime,
A tiny channel kept the time.
No flags to flop, just errors true,
Deadline whispered, off it flew —
Hooray, the timeout hopped in rhyme! 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title uses an emoji and mentions 'test: Fix race condition in TestTimeout_ContextPropagation', which clearly describes the primary change - fixing a race condition in a specific test.
Description check ✅ Passed The description is comprehensive, including the problem statement, reproduction steps, root cause, and solution. It follows the template structure with type of change and checklist items marked appropriately.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request addresses a race condition in the TestTimeout_ContextPropagation test by replacing an atomic.Bool with a buffered channel for proper synchronization between the test goroutine and the handler goroutine. The changes also improve the test by using time.NewTimer to prevent resource leaks and by strengthening the assertions to check for the specific context.DeadlineExceeded error. The fix is well-implemented and effectively resolves the race condition, making the test more robust and reliable. I have reviewed the changes and found no issues.

@adrian-lin-1-0-0 adrian-lin-1-0-0 changed the title 🩹 chore(timeout): fix race and strengthen assertions in TestTimeout_ContextPropagation 🚨 Test: Fix race condition in TestTimeout_ContextPropagation Feb 28, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Improves reliability of the timeout middleware test suite by removing a race in TestTimeout_ContextPropagation and making the assertion depend on synchronized handler observation of context cancellation (relates to #3671).

Changes:

  • Replace atomic.Bool with a buffered errCh to synchronize between the abandoned handler goroutine and the test.
  • Strengthen the test to assert the handler reports context.DeadlineExceeded and to fail fast if the handler never reports.

Comment on lines +94 to 105
timer := time.NewTimer(500 * time.Millisecond)
defer timer.Stop()

select {
case <-timer.C:
errCh <- nil
return c.SendString("completed")

case <-c.Context().Done():
contextCanceled.Store(true)
errCh <- c.Context().Err()
return c.Context().Err()
case <-time.After(500 * time.Millisecond):
return c.SendString("completed")
}
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

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

The handler’s select can become nondeterministic if it isn’t scheduled until after both the 500ms timer has fired and c.Context().Done() is already closed; in that case Go may choose the timer branch and send nil, making this test flaky even though the context was canceled. To make the assertion deterministic, prefer a pattern that prioritizes the canceled context (e.g., check c.Context().Err()/Done() first in a non-blocking way before waiting on the timer), or make the timer duration so large that it can’t realistically become ready before the handler observes cancellation.

Copilot uses AI. Check for mistakes.
Copy link
Author

Choose a reason for hiding this comment

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

The timer is 500ms while the timeout is 50ms — a 10x gap. For both cases to be ready simultaneously, the goroutine would need to go unscheduled for 500ms, which is not realistic in practice.

This is also the same select pattern used in other tests in this file (e.g. TestTimeout_PanicAfterTimeout, TestTimeout_ContextCleanup) and in the existing sleepWithContext helper. Changing only this test to a different pattern would be inconsistent.

Dismissing this as not actionable.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.

Comment on lines 114 to 118
select {
case handlerErr := <-errCh:
require.ErrorIs(t, handlerErr, context.DeadlineExceeded, "handler should report DeadlineExceeded")

case <-time.After(1 * time.Second):
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

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

The select timeout uses time.After(1s). In repeated runs (e.g., -count=500) this leaves many pending timers until they fire, which can add avoidable allocations and noise. Prefer a time.NewTimer with defer Stop() (using timer.C in the select) so the timer can be stopped/drained when the handlerErr case wins.

Suggested change
select {
case handlerErr := <-errCh:
require.ErrorIs(t, handlerErr, context.DeadlineExceeded, "handler should report DeadlineExceeded")
case <-time.After(1 * time.Second):
timer := time.NewTimer(1 * time.Second)
defer func() {
if !timer.Stop() {
<-timer.C
}
}()
select {
case handlerErr := <-errCh:
require.ErrorIs(t, handlerErr, context.DeadlineExceeded, "handler should report DeadlineExceeded")
case <-timer.C:

Copilot uses AI. Check for mistakes.
@adrian-lin-1-0-0 adrian-lin-1-0-0 changed the title 🚨 Test: Fix race condition in TestTimeout_ContextPropagation 🚨 test: Fix race condition in TestTimeout_ContextPropagation Feb 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

3 participants