Skip to content

Commit daf12cd

Browse files
committed
Improve error return from AnonDialer on Windows
AnonDialer will now return a "not found" error if the pipe is not found before the timeout is reached. If the pipe exists but the timeout is reached while attempting to connect, the timeout error will still be returned. This will allow the error handling logic to work properly when connecting to the shim log pipe. An error message is only logged if the error is not "not found", so now log noise from log pipes that were never intended to be created by the shim will be hidden. This change also cleans up the control flow for AnonDialer on Windows. The new code should be more easily readable, but the only semantic change is the error return value change. Signed-off-by: Kevin Parsons <[email protected]>
1 parent 29930e9 commit daf12cd

1 file changed

Lines changed: 24 additions & 26 deletions

File tree

runtime/v2/shim/util_windows.go

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -57,35 +57,33 @@ func SocketAddress(ctx context.Context, id string) (string, error) {
5757

5858
// AnonDialer returns a dialer for a npipe
5959
func AnonDialer(address string, timeout time.Duration) (net.Conn, error) {
60-
var c net.Conn
61-
var lastError error
62-
timedOutError := errors.Errorf("timed out waiting for npipe %s", address)
63-
start := time.Now()
60+
ctx, cancel := context.WithTimeout(context.Background(), timeout)
61+
defer cancel()
62+
63+
// If there is nobody serving the pipe we limit the timeout for this case to
64+
// 5 seconds because any shim that would serve this endpoint should serve it
65+
// within 5 seconds.
66+
serveTimer := time.NewTimer(5 * time.Second)
67+
defer serveTimer.Stop()
6468
for {
65-
remaining := timeout - time.Since(start)
66-
if remaining <= 0 {
67-
lastError = timedOutError
68-
break
69-
}
70-
c, lastError = winio.DialPipe(address, &remaining)
71-
if lastError == nil {
72-
break
73-
}
74-
if !os.IsNotExist(lastError) {
75-
break
76-
}
77-
// There is nobody serving the pipe. We limit the timeout for this case
78-
// to 5 seconds because any shim that would serve this endpoint should
79-
// serve it within 5 seconds. We use the passed in timeout for the
80-
// `DialPipe` timeout if the pipe exists however to give the pipe time
81-
// to `Accept` the connection.
82-
if time.Since(start) >= 5*time.Second {
83-
lastError = timedOutError
84-
break
69+
c, err := winio.DialPipeContext(ctx, address)
70+
if err != nil {
71+
if os.IsNotExist(err) {
72+
select {
73+
case <-serveTimer.C:
74+
return nil, errors.Wrap(os.ErrNotExist, "pipe not found before timeout")
75+
default:
76+
// Wait 10ms for the shim to serve and try again.
77+
time.Sleep(10 * time.Millisecond)
78+
continue
79+
}
80+
} else if err == context.DeadlineExceeded {
81+
return nil, errors.Wrapf(err, "timed out waiting for npipe %s", address)
82+
}
83+
return nil, err
8584
}
86-
time.Sleep(10 * time.Millisecond)
85+
return c, nil
8786
}
88-
return c, lastError
8987
}
9088

9189
// NewSocket returns a new npipe listener

0 commit comments

Comments
 (0)