From 2283c8d4c2f57c0ccc42adf91463932df2c35b71 Mon Sep 17 00:00:00 2001 From: katarzyna-z Date: Mon, 3 Oct 2016 12:17:59 +0200 Subject: [PATCH] Fix for issue #1167, added handling of errors which are returned by scanner --- control/plugin/execution.go | 77 ++++++++++++++----- .../snap-plugin-collector-mock2/mock/mock.go | 18 ++++- 2 files changed, 73 insertions(+), 22 deletions(-) diff --git a/control/plugin/execution.go b/control/plugin/execution.go index 18a32f2ed..250c8ac96 100644 --- a/control/plugin/execution.go +++ b/control/plugin/execution.go @@ -115,21 +115,41 @@ func (e *ExecutablePlugin) Run(timeout time.Duration) (Response, error) { e.cmd.Start() e.captureStderr() go func() { - for stdOutScanner.Scan() { - // The first chunk from the scanner is the plugin's response to the - // handshake. Once we've received that, we can begin to forward - // logs on to snapd's log. - if !respReceived { - respBytes := stdOutScanner.Bytes() - err = json.Unmarshal(respBytes, &resp) - respReceived = true - close(doneChan) - } else { - execLogger.WithFields(log.Fields{ - "plugin": path.Base(e.cmd.Path()), - "io": "stdout", - }).Debug(stdOutScanner.Text()) + for { + for stdOutScanner.Scan() { + // The first chunk from the scanner is the plugin's response to the + // handshake. Once we've received that, we can begin to forward + // logs on to snapd's log. + if !respReceived { + respBytes := stdOutScanner.Bytes() + err = json.Unmarshal(respBytes, &resp) + respReceived = true + close(doneChan) + } else { + execLogger.WithFields(log.Fields{ + "plugin": path.Base(e.cmd.Path()), + "io": "stdout", + }).Debug(stdOutScanner.Text()) + } } + + if errScanner := stdOutScanner.Err(); errScanner != nil { + reader := bufio.NewReader(e.stdout) + log, errRead := reader.ReadString('\n') + if errRead == io.EOF { + break + } + + execLogger. + WithField("plugin", path.Base(e.cmd.Path())). + WithField("io", "stdout"). + WithField("scanner_err", errScanner). + WithField("read_string_err", errRead). + Warn(log) + + continue //scanner finished with errors so try to scan once again + } + break //scanner finished scanning without errors so break the loop } }() @@ -167,12 +187,31 @@ func (e *ExecutablePlugin) Kill() error { func (e *ExecutablePlugin) captureStderr() { stdErrScanner := bufio.NewScanner(e.stderr) go func() { - for stdErrScanner.Scan() { - execLogger. - WithField("io", "stderr"). - WithField("plugin", path.Base(e.cmd.Path())). - Debug(stdErrScanner.Text()) + for { + for stdErrScanner.Scan() { + execLogger. + WithField("plugin", path.Base(e.cmd.Path())). + WithField("io", "stderr"). + Debug(stdErrScanner.Text()) + } + if errScanner := stdErrScanner.Err(); errScanner != nil { + reader := bufio.NewReader(e.stderr) + log, errRead := reader.ReadString('\n') + if errRead == io.EOF { + break + } + + execLogger. + WithField("plugin", path.Base(e.cmd.Path())). + WithField("io", "stderr"). + WithField("scanner_err", errScanner). + WithField("read_string_err", errRead). + Warn(log) + + continue //scanner finished with errors so try to scan once again + } + break //scanner finished scanning without errors so break the loop } }() } diff --git a/plugin/collector/snap-plugin-collector-mock2/mock/mock.go b/plugin/collector/snap-plugin-collector-mock2/mock/mock.go index 1d8d73deb..7dc551f1a 100644 --- a/plugin/collector/snap-plugin-collector-mock2/mock/mock.go +++ b/plugin/collector/snap-plugin-collector-mock2/mock/mock.go @@ -20,9 +20,11 @@ limitations under the License. package mock import ( + "bufio" "fmt" "log" "math/rand" + "os" "strings" "time" @@ -57,14 +59,24 @@ func (f *Mock) CollectMetrics(mts []plugin.MetricType) ([]plugin.MetricType, err rand.Seed(time.Now().UTC().UnixNano()) metrics := []plugin.MetricType{} for i := range mts { - if c, ok := mts[i].Config().Table()["long_print"]; ok && c.(ctypes.ConfigValueBool).Value { + if c, ok := mts[i].Config().Table()["long_stdout_log"]; ok && c.(ctypes.ConfigValueBool).Value { letterBytes := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" longLine := []byte{} - for i := 0; i < 8193; i++ { + for i := 0; i < bufio.MaxScanTokenSize; i++ { longLine = append(longLine, letterBytes[rand.Intn(len(letterBytes))]) } - fmt.Println(string(longLine)) + fmt.Fprintln(os.Stdout, string(longLine)) } + + if c, ok := mts[i].Config().Table()["long_stderr_log"]; ok && c.(ctypes.ConfigValueBool).Value { + letterBytes := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + longLine := []byte{} + for i := 0; i < bufio.MaxScanTokenSize; i++ { + longLine = append(longLine, letterBytes[rand.Intn(len(letterBytes))]) + } + fmt.Fprintln(os.Stderr, string(longLine)) + } + if c, ok := mts[i].Config().Table()["panic"]; ok && c.(ctypes.ConfigValueBool).Value { panic("Oops!") }