add a thread safe context that can be used downstream and mutated#4172
add a thread safe context that can be used downstream and mutated#4172rubensayshi wants to merge 1 commit intogin-gonic:masterfrom
Conversation
905cdca to
443ef77
Compare
|
@rubensayshi Please update the PR to the latest source code for the CI/CD flow. |
443ef77 to
cd8ad99
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #4172 +/- ##
==========================================
- Coverage 99.21% 98.70% -0.51%
==========================================
Files 42 44 +2
Lines 3182 2937 -245
==========================================
- Hits 3157 2899 -258
- Misses 17 26 +9
- Partials 8 12 +4
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
happy to increase the coverage if there's an actual chance this would get merged! :D |
|
can we get someone to look into it ? it's failing many of our concurrency tests because of the race condition |
|
I will take a look. |
There was a problem hiding this comment.
Pull Request Overview
This PR introduces thread-safe context management capabilities to Gin by adding an internal context mechanism that allows safe mutations without race conditions on c.Request.Context(). The implementation addresses known race detection issues when using context values in concurrent scenarios.
- Adds
UseInternalContextfeature flag to enable thread-safe internal context management - Implements
WithInternalContext()andInternalContext()methods with proper mutex protection - Modifies existing context methods to support internal context fallback when enabled
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
context.go |
Core implementation of thread-safe internal context with mutex protection and context interface methods |
gin.go |
Adds UseInternalContext configuration flag and updates comment formatting |
context_test.go |
Comprehensive test coverage for all internal context methods and edge cases |
test_helpers.go |
Enhances CreateTestContext with optional configuration functions for testing |
Comments suppressed due to low confidence (1)
context.go:1357
- [nitpick] The function name
useInternalContextis ambiguous - it reads like an action rather than a predicate. Consider renaming tohasInternalContextorisInternalContextEnabledto better indicate it's a boolean check.
func (c *Context) useInternalContext() bool {
|
@appleboy any chance that we can pick this up again? seems like with go1.25 either the race detector go more aggressive or things just got more optimized that the race is more easily detectable... |
|
@appleboy sorry for pinging again, but I'd be happy to put in the effort to polish this MR if neccesary! |
@rubensayshi, please help update the PR to the master branch. |
cd8ad99 to
4218569
Compare
|
@appleboy sorry, did the rebase now. I don't see the pipeline running anymore for the MR 🤔 ? |
|
hmm after some testing we realized this no longer propagates the |
4218569 to
5a59ab2
Compare
5a59ab2 to
a7b757e
Compare
|
move to next milestone |

It's currently unsafe to use
c.Request.Contextfrom the*gin.Contextto pass to downstream functions AND do any mutations to thec.Request.Context.Even when you do
c.Request = c.Request.WithContext(...)you'll end up with the go race detector flagging the unsafe reading of thec.Requestand writing toc.Request.And even when you're not really doing anything
.WithContextthere's a chance that the context pool causes the race detector to get angryHowever it would be really nice to be able to put values into the
*gin.Contextwithcontext.WithValue()in a thread-safe way that allows downstream usage of*gin.Contextascontext.Contextto access those values.For example, an auth middleware adding some debugging /loggin related values with
context.WithValue()will not be lost along the way, or adding aotel.Tracerto the context with additional options etc.Making all the places where gin touches
c.Requestthread-safe with a lock would be a significant undertaking and would have an impact on performance (probably talking about nano seconds, but still non zero impact).With the MR we're adding a thread-safe way to carry around and mutate a
context.Contextinside*gin.Contextwithout having to protectc.Request.In practice the
c.Request.Contextisn't going to be very interesting to wrap anyway, so loosing that as the "root" context probably isn't a issue for anyone.It's trivial to make the root
InternalContextthec.Request.Contextwhen we do.reset()(ifContextWithFallbackis enabled), but I wanted to keep this MR as small as possible.And it would have one quirky downside that if someone uses
UseInternalContextand does something likec.Request = c.Request.WithContext(...)then it wouldn't have any effect.There's a couple of mentions of issues around this before:
DATA RACEwith Go1.21, Go1.22 #3931func (c *Context) Copy() *Context#1118