Update unix dialer to keep retrying if socket is gone
This is needed to support daemon restart as the unix socket is recreated at every start. Signed-off-by: Kenfe-Mickael Laventure <mickael.laventure@gmail.com>
This commit is contained in:
parent
f27f8dd120
commit
24aac336f3
@ -64,8 +64,9 @@ func New(address string, opts ...ClientOpt) (*Client, error) {
|
|||||||
gopts := []grpc.DialOption{
|
gopts := []grpc.DialOption{
|
||||||
grpc.WithBlock(),
|
grpc.WithBlock(),
|
||||||
grpc.WithInsecure(),
|
grpc.WithInsecure(),
|
||||||
grpc.WithTimeout(100 * time.Second),
|
grpc.WithTimeout(60 * time.Second),
|
||||||
grpc.FailOnNonTempDialError(true),
|
grpc.FailOnNonTempDialError(true),
|
||||||
|
grpc.WithBackoffMaxDelay(3 * time.Second),
|
||||||
grpc.WithDialer(dialer),
|
grpc.WithDialer(dialer),
|
||||||
}
|
}
|
||||||
if len(copts.dialOptions) > 0 {
|
if len(copts.dialOptions) > 0 {
|
||||||
|
@ -5,13 +5,68 @@ package containerd
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func isNoent(err error) bool {
|
||||||
|
if err != nil {
|
||||||
|
if nerr, ok := err.(*net.OpError); ok {
|
||||||
|
if serr, ok := nerr.Err.(*os.SyscallError); ok {
|
||||||
|
if serr.Err == syscall.ENOENT {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
type dialResult struct {
|
||||||
|
c net.Conn
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
func dialer(address string, timeout time.Duration) (net.Conn, error) {
|
func dialer(address string, timeout time.Duration) (net.Conn, error) {
|
||||||
|
var (
|
||||||
|
stopC = make(chan struct{})
|
||||||
|
synC = make(chan *dialResult)
|
||||||
|
)
|
||||||
address = strings.TrimPrefix(address, "unix://")
|
address = strings.TrimPrefix(address, "unix://")
|
||||||
return net.DialTimeout("unix", address, timeout)
|
go func() {
|
||||||
|
defer close(synC)
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-stopC:
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
c, err := net.DialTimeout("unix", address, timeout)
|
||||||
|
if isNoent(err) {
|
||||||
|
<-time.After(10 * time.Millisecond)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
synC <- &dialResult{c, err}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
select {
|
||||||
|
case dr := <-synC:
|
||||||
|
return dr.c, dr.err
|
||||||
|
case <-time.After(timeout):
|
||||||
|
close(stopC)
|
||||||
|
go func() {
|
||||||
|
dr := <-synC
|
||||||
|
if dr != nil {
|
||||||
|
dr.c.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return nil, errors.Errorf("dial %s: no such file or directory", address)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func dialAddress(address string) string {
|
func dialAddress(address string) string {
|
||||||
|
Loading…
Reference in New Issue
Block a user