vm: better handle VM diagnosis output

1. Always append diagnosis output at the end.
Don't intermix it with kernel output. It's confusing and not useful.

2. Don't include diagnosis output into Report.
It's too verbose and is not the crash. Keep it only in the Output.
This commit is contained in:
Dmitry Vyukov 2020-03-21 16:30:35 +01:00
parent d60b9c6b0e
commit 78267cec1a
3 changed files with 43 additions and 11 deletions

View File

@ -120,6 +120,8 @@ func NewReporter(cfg *mgrconfig.Config) (Reporter, error) {
}
const (
VMDiagnosisStart = "\nVM DIAGNOSIS:\n"
unexpectedKernelReboot = "unexpected kernel reboot"
memoryLeakPrefix = "memory leak in "
dataRacePrefix = "KCSAN: data-race"
@ -179,6 +181,9 @@ func (wrap *reporterWrapper) Parse(output []byte) *Report {
if match := reportFrameRe.FindStringSubmatch(rep.Title); match != nil {
rep.Frame = match[1]
}
if pos := bytes.Index(rep.Report, []byte(VMDiagnosisStart)); pos != -1 {
rep.Report = rep.Report[:pos]
}
return rep
}

View File

@ -279,13 +279,16 @@ type monitor struct {
}
func (mon *monitor) extractError(defaultError string) *report.Report {
var diagOutput []byte
appendDiagOutput := func() {
if len(diagOutput) > 0 {
mon.output = append(mon.output, report.VMDiagnosisStart...)
mon.output = append(mon.output, diagOutput...)
}
}
if defaultError != "" {
// N.B. we always wait below for other errors.
diag, _ := mon.inst.Diagnose()
if len(diag) > 0 {
mon.output = append(mon.output, "DIAGNOSIS:\n"...)
mon.output = append(mon.output, diag...)
}
diagOutput, _ = mon.inst.Diagnose()
}
// Give it some time to finish writing the error message.
mon.waitForOutput()
@ -296,6 +299,7 @@ func (mon *monitor) extractError(defaultError string) *report.Report {
if defaultError == "" {
return nil
}
appendDiagOutput()
rep := &report.Report{
Title: defaultError,
Output: mon.output,
@ -304,15 +308,13 @@ func (mon *monitor) extractError(defaultError string) *report.Report {
return rep
}
if defaultError == "" {
diag, wait := mon.inst.Diagnose()
if len(diag) > 0 {
mon.output = append(mon.output, "DIAGNOSIS:\n"...)
mon.output = append(mon.output, diag...)
}
wait := false
diagOutput, wait = mon.inst.Diagnose()
if wait {
mon.waitForOutput()
}
}
appendDiagOutput()
rep := mon.reporter.Parse(mon.output[mon.matchPos:])
if rep == nil {
panic(fmt.Sprintf("reporter.ContainsCrash/Parse disagree:\n%s", mon.output[mon.matchPos:]))

View File

@ -138,7 +138,32 @@ var tests = []*Test{
Report: &report.Report{
Title: lostConnectionCrash,
Output: []byte(
"DIAGNOSIS:\nDIAGNOSE\n",
"\n" +
"VM DIAGNOSIS:\n" +
"DIAGNOSE\n",
),
},
},
{
Name: "diagnose-bug-no-wait",
Body: func(outc chan []byte, errc chan error) {
outc <- []byte("BUG: bad\n")
time.Sleep(time.Second)
outc <- []byte("other output\n")
},
DiagnoseNoWait: true,
Report: &report.Report{
Title: "BUG: bad",
Report: []byte(
"BUG: bad\n" +
"other output\n",
),
Output: []byte(
"BUG: bad\n" +
"other output\n" +
"\n" +
"VM DIAGNOSIS:\n" +
"DIAGNOSE\n",
),
},
},