Skip to content

Commit ac1cb6d

Browse files
authored
Merge pull request #3467 from kevpar/dial-pipe-err
Improve error return from AnonDialer on Windows
2 parents adad947 + b16e7c5 commit ac1cb6d

2 files changed

Lines changed: 49 additions & 52 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
}

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)