Fix WaitReady for VPP client adapters 97/18697/1
authorOndrej Fabry <ofabry@cisco.com>
Fri, 5 Apr 2019 08:18:33 +0000 (10:18 +0200)
committerOndrej Fabry <ofabry@cisco.com>
Fri, 5 Apr 2019 08:18:33 +0000 (10:18 +0200)
Change-Id: I57d29a819132d4894691e1131b7d79e19c90456e
Signed-off-by: Ondrej Fabry <ofabry@cisco.com>
adapter/socketclient/socketclient.go
adapter/vppapiclient/vppapiclient.go

index f281955..4c576c3 100644 (file)
@@ -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
+                               }
                        }
                }
        }
index d43c832..037d3ac 100644 (file)
@@ -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