Skip to content

Commit b16e7c5

Browse files
committed
Update pkg/ttrpcutil with improved pipe dial logic
Signed-off-by: Kevin Parsons <[email protected]>
1 parent daf12cd commit b16e7c5

1 file changed

Lines changed: 25 additions & 26 deletions

File tree

pkg/ttrpcutil/client_windows.go

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
package ttrpcutil
2020

2121
import (
22+
"context"
2223
"net"
2324
"os"
2425
"time"
@@ -28,33 +29,31 @@ import (
2829
)
2930

3031
func ttrpcDial(address string, timeout time.Duration) (net.Conn, error) {
31-
var c net.Conn
32-
var lastError error
33-
timedOutError := errors.Errorf("timed out waiting for npipe %s", address)
34-
start := time.Now()
32+
ctx, cancel := context.WithTimeout(context.Background(), timeout)
33+
defer cancel()
34+
35+
// If there is nobody serving the pipe we limit the timeout for this case to
36+
// 5 seconds because any shim that would serve this endpoint should serve it
37+
// within 5 seconds.
38+
serveTimer := time.NewTimer(5 * time.Second)
39+
defer serveTimer.Stop()
3540
for {
36-
remaining := timeout - time.Since(start)
37-
if remaining <= 0 {
38-
lastError = timedOutError
39-
break
41+
c, err := winio.DialPipeContext(ctx, address)
42+
if err != nil {
43+
if os.IsNotExist(err) {
44+
select {
45+
case <-serveTimer.C:
46+
return nil, errors.Wrap(os.ErrNotExist, "pipe not found before timeout")
47+
default:
48+
// Wait 10ms for the shim to serve and try again.
49+
time.Sleep(10 * time.Millisecond)
50+
continue
51+
}
52+
} else if err == context.DeadlineExceeded {
53+
return nil, errors.Wrapf(err, "timed out waiting for npipe %s", address)
54+
}
55+
return nil, err
4056
}
41-
c, lastError = winio.DialPipe(address, &remaining)
42-
if lastError == nil {
43-
break
44-
}
45-
if !os.IsNotExist(lastError) {
46-
break
47-
}
48-
// There is nobody serving the pipe. We limit the timeout for this case
49-
// to 5 seconds because any shim that would serve this endpoint should
50-
// serve it within 5 seconds. We use the passed in timeout for the
51-
// `DialPipe` timeout if the pipe exists however to give the pipe time
52-
// to `Accept` the connection.
53-
if time.Since(start) >= 5*time.Second {
54-
lastError = timedOutError
55-
break
56-
}
57-
time.Sleep(10 * time.Millisecond)
57+
return c, nil
5858
}
59-
return c, lastError
6059
}

0 commit comments

Comments
 (0)