@@ -1037,6 +1037,64 @@ var _ = Describe("queuedNewConn", func() {
10371037 testPool .Put (ctx , reqBConn )
10381038 Eventually (func () int { return testPool .QueueLen () }, "600ms" ).Should (Equal (0 ))
10391039 })
1040+ // Test for race condition where nil context can be passed to newConn
1041+ // This reproduces the issue reported in GitHub where queuedNewConn panics
1042+ // with "cannot create context from nil parent"
1043+ It ("should handle nil context race condition in queuedNewConn" , func () {
1044+ // Create a pool with very short timeouts to trigger the race condition
1045+ testPool := pool .NewConnPool (& pool.Options {
1046+ Dialer : func (ctx context.Context ) (net.Conn , error ) {
1047+ // Add a small delay to increase chance of race condition
1048+ time .Sleep (50 * time .Millisecond )
1049+ return dummyDialer (ctx )
1050+ },
1051+ PoolSize : int32 (10 ),
1052+ MaxConcurrentDials : 10 ,
1053+ PoolTimeout : 10 * time .Millisecond , // Very short timeout
1054+ DialTimeout : 100 * time .Millisecond ,
1055+ ConnMaxIdleTime : time .Millisecond ,
1056+ })
1057+ defer testPool .Close ()
1058+
1059+ // Try to trigger the race condition by making many concurrent requests
1060+ // with short timeouts
1061+ const numGoroutines = 50
1062+ var wg sync.WaitGroup
1063+ errors := make (chan error , numGoroutines )
1064+
1065+ for i := 0 ; i < numGoroutines ; i ++ {
1066+ wg .Add (1 )
1067+ go func () {
1068+ defer GinkgoRecover ()
1069+ defer wg .Done ()
1070+
1071+ // Use a very short context timeout to trigger the race
1072+ ctx , cancel := context .WithTimeout (context .Background (), 5 * time .Millisecond )
1073+ defer cancel ()
1074+
1075+ _ , err := testPool .Get (ctx )
1076+ if err != nil {
1077+ // We expect timeout errors, but not panics
1078+ errors <- err
1079+ }
1080+ }()
1081+ }
1082+
1083+ wg .Wait ()
1084+ close (errors )
1085+
1086+ // Check that we got timeout errors (expected) but no panics
1087+ // The test passes if it doesn't panic
1088+ timeoutCount := 0
1089+ for err := range errors {
1090+ if err == context .DeadlineExceeded || err == pool .ErrPoolTimeout {
1091+ timeoutCount ++
1092+ }
1093+ }
1094+
1095+ // We should have at least some timeouts due to the short timeout
1096+ Expect (timeoutCount ).To (BeNumerically (">" , 0 ))
1097+ })
10401098})
10411099
10421100func init () {
0 commit comments