(ctx context.Context)
| 990 | } |
| 991 | |
| 992 | func (p *ConnPool) queuedNewConn(ctx context.Context) (*Conn, error) { |
| 993 | select { |
| 994 | case p.dialsInProgress <- struct{}{}: |
| 995 | // Got permission, proceed to create connection |
| 996 | case <-ctx.Done(): |
| 997 | p.freeTurn() |
| 998 | return nil, ctx.Err() |
| 999 | } |
| 1000 | |
| 1001 | // Don't apply DialTimeout via context here; dialConn applies DialTimeout per attempt. |
| 1002 | dialCtx, cancel := context.WithCancel(context.Background()) |
| 1003 | |
| 1004 | w := &wantConn{ |
| 1005 | ctx: dialCtx, |
| 1006 | cancelCtx: cancel, |
| 1007 | result: make(chan wantConnResult, 1), |
| 1008 | } |
| 1009 | var err error |
| 1010 | defer func() { |
| 1011 | if err != nil { |
| 1012 | if cn := w.cancel(); cn != nil && p.putIdleConn(ctx, cn) { |
| 1013 | p.freeTurn() |
| 1014 | } |
| 1015 | } |
| 1016 | }() |
| 1017 | |
| 1018 | p.dialsQueue.discardDoneAtFront() |
| 1019 | p.dialsQueue.enqueue(w) |
| 1020 | |
| 1021 | go func(w *wantConn) { |
| 1022 | var freeTurnCalled bool |
| 1023 | defer func() { |
| 1024 | if err := recover(); err != nil { |
| 1025 | w.tryDeliver(nil, errPanicInQueuedNewConn) |
| 1026 | p.dialsQueue.discardDoneAtFront() |
| 1027 | if !freeTurnCalled { |
| 1028 | p.freeTurn() |
| 1029 | } |
| 1030 | internal.Logger.Printf(context.Background(), "queuedNewConn panic: %+v", err) |
| 1031 | } |
| 1032 | }() |
| 1033 | |
| 1034 | defer w.cancelCtx() |
| 1035 | defer func() { <-p.dialsInProgress }() // Release connection creation permission |
| 1036 | |
| 1037 | dialCtx := w.getCtxForDial() |
| 1038 | cn, cnErr := p.newConn(dialCtx, true) |
| 1039 | if cnErr != nil { |
| 1040 | w.tryDeliver(nil, cnErr) // deliver error to caller, notify connection creation failed |
| 1041 | p.dialsQueue.discardDoneAtFront() |
| 1042 | p.freeTurn() |
| 1043 | freeTurnCalled = true |
| 1044 | return |
| 1045 | } |
| 1046 | |
| 1047 | delivered := w.tryDeliver(cn, cnErr) |
| 1048 | p.dialsQueue.discardDoneAtFront() |
| 1049 | if !delivered && p.putIdleConn(dialCtx, cn) { |
no test coverage detected