From f40a43b1a99f488da1400c74482b9c97eaf08515 Mon Sep 17 00:00:00 2001 From: Ondrej Fabry Date: Fri, 5 Apr 2019 10:18:33 +0200 Subject: [PATCH] Fix WaitReady for VPP client adapters Change-Id: I57d29a819132d4894691e1131b7d79e19c90456e Signed-off-by: Ondrej Fabry --- adapter/socketclient/socketclient.go | 31 ++++++++++++++++++++++--------- adapter/vppapiclient/vppapiclient.go | 31 +++++++++++++++++++++---------- 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/adapter/socketclient/socketclient.go b/adapter/socketclient/socketclient.go index f281955..4c576c3 100644 --- a/adapter/socketclient/socketclient.go +++ b/adapter/socketclient/socketclient.go @@ -4,7 +4,6 @@ import ( "bufio" "bytes" "fmt" - "github.com/fsnotify/fsnotify" "io" "net" "os" @@ -13,6 +12,8 @@ import ( "sync" "time" + "github.com/fsnotify/fsnotify" + "github.com/lunixbochs/struc" logger "github.com/sirupsen/logrus" @@ -33,6 +34,10 @@ var ( ConnectTimeout = time.Second * 3 DisconnectTimeout = time.Second + // MaxWaitReady defines maximum duration before waiting for socket file + // times out + MaxWaitReady = time.Second * 15 + Debug = os.Getenv("DEBUG_GOVPP_SOCK") != "" DebugMsgIds = os.Getenv("DEBUG_GOVPP_SOCKMSG") != "" @@ -76,7 +81,7 @@ func nilCallback(msgID uint16, data []byte) { // WaitReady checks socket file existence and waits for it if necessary func (c *vppClient) WaitReady() error { - // verify file existence + // check if file at the path already exists if _, err := os.Stat(c.sockAddr); err == nil { return nil } else if os.IsExist(err) { @@ -93,17 +98,25 @@ func (c *vppClient) WaitReady() error { Log.Errorf("failed to close file watcher: %v", err) } }() - path := filepath.Dir(c.sockAddr) - if err := watcher.Add(path); err != nil { + + // start watching directory + if err := watcher.Add(filepath.Dir(c.sockAddr)); err != nil { return err } for { - ev := <-watcher.Events - if ev.Name == path { - if (ev.Op & fsnotify.Create) == fsnotify.Create { - // socket ready - return nil + select { + case <-time.After(MaxWaitReady): + return fmt.Errorf("waiting for socket file timed out (%s)", MaxWaitReady) + case e := <-watcher.Errors: + return e + case ev := <-watcher.Events: + Log.Debugf("watcher event: %+v", ev) + if ev.Name == c.sockAddr { + if (ev.Op & fsnotify.Create) == fsnotify.Create { + // socket was created, we are ready + return nil + } } } } diff --git a/adapter/vppapiclient/vppapiclient.go b/adapter/vppapiclient/vppapiclient.go index d43c832..037d3ac 100644 --- a/adapter/vppapiclient/vppapiclient.go +++ b/adapter/vppapiclient/vppapiclient.go @@ -78,12 +78,19 @@ import ( "os" "path/filepath" "reflect" + "time" "unsafe" "git.fd.io/govpp.git/adapter" "github.com/fsnotify/fsnotify" ) +var ( + // MaxWaitReady defines maximum duration before waiting for shared memory + // segment times out + MaxWaitReady = time.Second * 15 +) + const ( // shmDir is a directory where shared memory is supposed to be created. shmDir = "/dev/shm/" @@ -173,16 +180,15 @@ func (a *vppClient) SetMsgCallback(cb adapter.MsgCallback) { // WaitReady blocks until shared memory for sending // binary api calls is present on the file system. func (a *vppClient) WaitReady() error { - var path string - // join the path to the shared memory segment + var path string if a.shmPrefix == "" { path = filepath.Join(shmDir, vppShmFile) } else { path = filepath.Join(shmDir, a.shmPrefix+"-"+vppShmFile) } - // check if file at the path exists + // check if file at the path already exists if _, err := os.Stat(path); err == nil { // file exists, we are ready return nil @@ -197,21 +203,26 @@ func (a *vppClient) WaitReady() error { } defer watcher.Close() + // start watching directory if err := watcher.Add(shmDir); err != nil { return err } for { - ev := <-watcher.Events - if ev.Name == path { - if (ev.Op & fsnotify.Create) == fsnotify.Create { - // file was created, we are ready - break + select { + case <-time.After(MaxWaitReady): + return fmt.Errorf("waiting for shared memory segment timed out (%s)", MaxWaitReady) + case e := <-watcher.Errors: + return e + case ev := <-watcher.Events: + if ev.Name == path { + if (ev.Op & fsnotify.Create) == fsnotify.Create { + // file was created, we are ready + return nil + } } } } - - return nil } //export go_msg_callback -- 2.16.6