From f8e4ce85b34ad4836281a734f3c747102588c684 Mon Sep 17 00:00:00 2001 From: Hui Zhu Date: Thu, 28 Nov 2019 10:22:57 +0800 Subject: [PATCH] client.go: HybridVSockDialer: Change Read EOT to recv peek Rust agent(grpc-rs) cannot work with firecacker because the first package will be dropped or truncated by HybridVSockDialer read EOT code. This issue was reported in https://github.com/kata-containers/kata-containers/issues/79 Golang agent(grpc-golang) is also affected by this issue. But it is first package is 9 bytes FRAME_SETTINGS. Drop it will not affect subsequent communications. This commit change to use recv peek that will do same check with read EOT but not drop any package. Fixes: #695 Signed-off-by: Hui Zhu --- protocols/client/client.go | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/protocols/client/client.go b/protocols/client/client.go index 911c252ef8..e46e873908 100644 --- a/protocols/client/client.go +++ b/protocols/client/client.go @@ -13,12 +13,14 @@ import ( "net/url" "strconv" "strings" + "syscall" "time" "github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc" "github.com/hashicorp/yamux" "github.com/mdlayher/vsock" opentracing "github.com/opentracing/opentracing-go" + "golang.org/x/sys/unix" "google.golang.org/grpc" "google.golang.org/grpc/codes" grpcStatus "google.golang.org/grpc/status" @@ -407,12 +409,19 @@ func HybridVSockDialer(sock string, timeout time.Duration) (net.Conn, error) { return nil, err } - // Read EOT (End of transmission) byte - eot := make([]byte, 32) - if _, err = conn.Read(eot); err != nil { - // Just close the connection, gRPC will dial again - // without errors - conn.Close() + // Receive the packet from the connection without removing it from + // the receive queue (MSG_PEEK), ensuring the connection is usable. + if uc, ok := conn.(*net.UnixConn); ok { + file, err := uc.File() + if err != nil { + conn.Close() + return nil, err + } + eot := make([]byte, 1) + if _, _, err = unix.Recvfrom(int(file.Fd()), eot, syscall.MSG_PEEK); err != nil { + conn.Close() + return nil, err + } } return conn, nil