Update pkg/ttrpcutil with improved pipe dial logic
Signed-off-by: Kevin Parsons <kevpar@microsoft.com>
This commit is contained in:
		| @@ -19,6 +19,7 @@ | |||||||
| package ttrpcutil | package ttrpcutil | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"context" | ||||||
| 	"net" | 	"net" | ||||||
| 	"os" | 	"os" | ||||||
| 	"time" | 	"time" | ||||||
| @@ -28,33 +29,31 @@ import ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| func ttrpcDial(address string, timeout time.Duration) (net.Conn, error) { | func ttrpcDial(address string, timeout time.Duration) (net.Conn, error) { | ||||||
| 	var c net.Conn | 	ctx, cancel := context.WithTimeout(context.Background(), timeout) | ||||||
| 	var lastError error | 	defer cancel() | ||||||
| 	timedOutError := errors.Errorf("timed out waiting for npipe %s", address) |  | ||||||
| 	start := time.Now() | 	// If there is nobody serving the pipe we limit the timeout for this case to | ||||||
|  | 	// 5 seconds because any shim that would serve this endpoint should serve it | ||||||
|  | 	// within 5 seconds. | ||||||
|  | 	serveTimer := time.NewTimer(5 * time.Second) | ||||||
|  | 	defer serveTimer.Stop() | ||||||
| 	for { | 	for { | ||||||
| 		remaining := timeout - time.Since(start) | 		c, err := winio.DialPipeContext(ctx, address) | ||||||
| 		if remaining <= 0 { | 		if err != nil { | ||||||
| 			lastError = timedOutError | 			if os.IsNotExist(err) { | ||||||
| 			break | 				select { | ||||||
| 		} | 				case <-serveTimer.C: | ||||||
| 		c, lastError = winio.DialPipe(address, &remaining) | 					return nil, errors.Wrap(os.ErrNotExist, "pipe not found before timeout") | ||||||
| 		if lastError == nil { | 				default: | ||||||
| 			break | 					// Wait 10ms for the shim to serve and try again. | ||||||
| 		} |  | ||||||
| 		if !os.IsNotExist(lastError) { |  | ||||||
| 			break |  | ||||||
| 		} |  | ||||||
| 		// There is nobody serving the pipe. We limit the timeout for this case |  | ||||||
| 		// to 5 seconds because any shim that would serve this endpoint should |  | ||||||
| 		// serve it within 5 seconds. We use the passed in timeout for the |  | ||||||
| 		// `DialPipe` timeout if the pipe exists however to give the pipe time |  | ||||||
| 		// to `Accept` the connection. |  | ||||||
| 		if time.Since(start) >= 5*time.Second { |  | ||||||
| 			lastError = timedOutError |  | ||||||
| 			break |  | ||||||
| 		} |  | ||||||
| 					time.Sleep(10 * time.Millisecond) | 					time.Sleep(10 * time.Millisecond) | ||||||
|  | 					continue | ||||||
|  | 				} | ||||||
|  | 			} else if err == context.DeadlineExceeded { | ||||||
|  | 				return nil, errors.Wrapf(err, "timed out waiting for npipe %s", address) | ||||||
|  | 			} | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  | 		return c, nil | ||||||
| 	} | 	} | ||||||
| 	return c, lastError |  | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Kevin Parsons
					Kevin Parsons