summaryrefslogtreecommitdiff
path: root/vendor/github.com/containernetworking
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/containernetworking')
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go56
-rw-r--r--vendor/github.com/containernetworking/plugins/pkg/ns/ns_linux.go5
2 files changed, 44 insertions, 17 deletions
diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go b/vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go
index 4f89a5dda..5ab5cc885 100644
--- a/vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go
+++ b/vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go
@@ -21,6 +21,8 @@ import (
"fmt"
"io"
"os/exec"
+ "strings"
+ "time"
"github.com/containernetworking/cni/pkg/types"
)
@@ -31,34 +33,54 @@ type RawExec struct {
func (e *RawExec) ExecPlugin(ctx context.Context, pluginPath string, stdinData []byte, environ []string) ([]byte, error) {
stdout := &bytes.Buffer{}
+ stderr := &bytes.Buffer{}
c := exec.CommandContext(ctx, pluginPath)
c.Env = environ
c.Stdin = bytes.NewBuffer(stdinData)
c.Stdout = stdout
- c.Stderr = e.Stderr
- if err := c.Run(); err != nil {
- return nil, pluginErr(err, stdout.Bytes())
+ c.Stderr = stderr
+
+ // Retry the command on "text file busy" errors
+ for i := 0; i <= 5; i++ {
+ err := c.Run()
+
+ // Command succeeded
+ if err == nil {
+ break
+ }
+
+ // If the plugin is currently about to be written, then we wait a
+ // second and try it again
+ if strings.Contains(err.Error(), "text file busy") {
+ time.Sleep(time.Second)
+ continue
+ }
+
+ // All other errors except than the busy text file
+ return nil, e.pluginErr(err, stdout.Bytes(), stderr.Bytes())
}
+ // Copy stderr to caller's buffer in case plugin printed to both
+ // stdout and stderr for some reason. Ignore failures as stderr is
+ // only informational.
+ if e.Stderr != nil && stderr.Len() > 0 {
+ _, _ = stderr.WriteTo(e.Stderr)
+ }
return stdout.Bytes(), nil
}
-func pluginErr(err error, output []byte) error {
- if exitError, ok := err.(*exec.ExitError); ok {
- emsg := types.Error{}
- if len(output) == 0 {
- if len(exitError.Stderr) == 0 {
- emsg.Msg = "netplugin failed with no error message"
- } else {
- emsg.Msg = fmt.Sprintf("netplugin failed: %q", string(exitError.Stderr))
- }
- } else if perr := json.Unmarshal(output, &emsg); perr != nil {
- emsg.Msg = fmt.Sprintf("netplugin failed but error parsing its diagnostic message %q: %v", string(output), perr)
+func (e *RawExec) pluginErr(err error, stdout, stderr []byte) error {
+ emsg := types.Error{}
+ if len(stdout) == 0 {
+ if len(stderr) == 0 {
+ emsg.Msg = fmt.Sprintf("netplugin failed with no error message: %v", err)
+ } else {
+ emsg.Msg = fmt.Sprintf("netplugin failed: %q", string(stderr))
}
- return &emsg
+ } else if perr := json.Unmarshal(stdout, &emsg); perr != nil {
+ emsg.Msg = fmt.Sprintf("netplugin failed but error parsing its diagnostic message %q: %v", string(stdout), perr)
}
-
- return err
+ return &emsg
}
func (e *RawExec) FindInPath(plugin string, paths []string) (string, error) {
diff --git a/vendor/github.com/containernetworking/plugins/pkg/ns/ns_linux.go b/vendor/github.com/containernetworking/plugins/pkg/ns/ns_linux.go
index a34f97170..3b745d491 100644
--- a/vendor/github.com/containernetworking/plugins/pkg/ns/ns_linux.go
+++ b/vendor/github.com/containernetworking/plugins/pkg/ns/ns_linux.go
@@ -26,6 +26,11 @@ import (
// Returns an object representing the current OS thread's network namespace
func GetCurrentNS() (NetNS, error) {
+ // Lock the thread in case other goroutine executes in it and changes its
+ // network namespace after getCurrentThreadNetNSPath(), otherwise it might
+ // return an unexpected network namespace.
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
return GetNS(getCurrentThreadNetNSPath())
}