From e2a736653a876aafce5b0955c42e734c34e55a83 Mon Sep 17 00:00:00 2001 From: Sascha Grunert Date: Fri, 3 Apr 2020 14:14:35 +0200 Subject: [PATCH] Retry exec commands on text file busy This makes the plugin validation a bit more robust by retrying the execution if the plugin is in text file busy state. This can happen if we write the config and the plugin at once. To avoid such races we now try up to 5 seconds for the plugin validation. Signed-off-by: Sascha Grunert --- pkg/invoke/raw_exec.go | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/pkg/invoke/raw_exec.go b/pkg/invoke/raw_exec.go index bb02af09..5ab5cc88 100644 --- a/pkg/invoke/raw_exec.go +++ b/pkg/invoke/raw_exec.go @@ -21,6 +21,8 @@ import ( "fmt" "io" "os/exec" + "strings" + "time" "github.com/containernetworking/cni/pkg/types" ) @@ -37,7 +39,24 @@ func (e *RawExec) ExecPlugin(ctx context.Context, pluginPath string, stdinData [ c.Stdin = bytes.NewBuffer(stdinData) c.Stdout = stdout c.Stderr = stderr - if err := c.Run(); err != nil { + + // 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()) }