diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2019-06-24 10:14:58 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2019-06-24 10:14:58 +0200 |
| commit | dfc7d235f55e493e36003b415f64593dd9636e6d (patch) | |
| tree | 9eab10fdfd553a0deb251ecc5682f7789616bb9d /vm | |
| parent | 472f0082fd8a2f82b85ab0682086e10b71529a51 (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.go | 14 | ||||
| -rw-r--r-- | vm/vm_test.go | 22 |
2 files changed, 34 insertions, 2 deletions
@@ -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) { |
