aboutsummaryrefslogtreecommitdiffstats
path: root/vm
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2019-06-24 10:14:58 +0200
committerDmitry Vyukov <dvyukov@google.com>2019-06-24 10:14:58 +0200
commitdfc7d235f55e493e36003b415f64593dd9636e6d (patch)
tree9eab10fdfd553a0deb251ecc5682f7789616bb9d /vm
parent472f0082fd8a2f82b85ab0682086e10b71529a51 (diff)
vm: fix spurious crash detection caused by trimmed lines
We've got a case when "ODEBUG:" was incorrectly detected as crash. That was caused by a flaw in matchPos logic. Fix that. See the added test for details.
Diffstat (limited to 'vm')
-rw-r--r--vm/vm.go14
-rw-r--r--vm/vm_test.go22
2 files changed, 34 insertions, 2 deletions
diff --git a/vm/vm.go b/vm/vm.go
index 28eddeef0..96298912b 100644
--- a/vm/vm.go
+++ b/vm/vm.go
@@ -209,7 +209,19 @@ func (inst *Instance) MonitorExecution(outc <-chan []byte, errc <-chan error,
copy(mon.output, mon.output[len(mon.output)-beforeContext:])
mon.output = mon.output[:beforeContext]
}
+ // Find the starting position for crash matching on the next iteration.
+ // We step back from the end of output by maxErrorLength to handle the case
+ // when a crash line is currently split/incomplete. And then we try to find
+ // the preceeding '\n' to have a full line. This is required to handle
+ // the case when a particular pattern is ignored as crash, but a suffix
+ // of the pattern is detected as crash (e.g. "ODEBUG:" is trimmed to "BUG:").
mon.matchPos = len(mon.output) - maxErrorLength
+ for i := 0; i < maxErrorLength; i++ {
+ if mon.matchPos <= 0 || mon.output[mon.matchPos-1] == '\n' {
+ break
+ }
+ mon.matchPos--
+ }
if mon.matchPos < 0 {
mon.matchPos = 0
}
@@ -330,7 +342,7 @@ func (mon *monitor) waitForOutput() {
}
const (
- maxErrorLength = 512
+ maxErrorLength = 256
lostConnectionCrash = "lost connection to test machine"
noOutputCrash = "no output from test machine"
diff --git a/vm/vm_test.go b/vm/vm_test.go
index e55cf2184..73c3198a0 100644
--- a/vm/vm_test.go
+++ b/vm/vm_test.go
@@ -70,7 +70,7 @@ func (inst *testInstance) Close() {
}
func init() {
- beforeContext = 200
+ beforeContext = maxErrorLength + 100
tickerPeriod = 1 * time.Second
NoOutputTimeout = 5 * time.Second
waitForOutputTimeout = 3 * time.Second
@@ -275,6 +275,26 @@ var tests = []*Test{
errc <- vmimpl.ErrTimeout
},
},
+ {
+ Name: "split-line",
+ Exit: ExitNormal,
+ Body: func(outc chan []byte, errc chan error) {
+ // "ODEBUG:" lines should be ignored, however the matchPos logic
+ // used to trim the lines so that we could see just "BUG:" later
+ // and detect it as crash.
+ buf := new(bytes.Buffer)
+ for i := 0; i < 50; i++ {
+ buf.WriteString("[ 2886.597572] ODEBUG: Out of memory. ODEBUG disabled\n")
+ buf.Write(bytes.Repeat([]byte{'-'}, i))
+ buf.WriteByte('\n')
+ }
+ output := buf.Bytes()
+ for i := range output {
+ outc <- output[i : i+1]
+ }
+ errc <- nil
+ },
+ },
}
func TestMonitorExecution(t *testing.T) {