diff options
| author | Aleksandr Nogikh <nogikh@google.com> | 2025-05-15 16:34:15 +0200 |
|---|---|---|
| committer | Aleksandr Nogikh <nogikh@google.com> | 2025-05-16 17:54:53 +0000 |
| commit | f41472b03ad1c28c33fa0dcb999ded4c60d1247d (patch) | |
| tree | 45bd5044187115e536cf17903bd1d6c69b479219 /pkg | |
| parent | cfde82699d32eb8844da8b2f2538f45fa5a02f43 (diff) | |
pkg/manager: improve error accounting during diff fuzzing
When running the reproducer from the patched kernel on the base kernel,
stay on the safe side when encountering errors and context
cancellations.
Always demand 3 successful executions before declaring a bug
patched-only.
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/manager/diff.go | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/pkg/manager/diff.go b/pkg/manager/diff.go index 8f367b1e8..dd9c7eebc 100644 --- a/pkg/manager/diff.go +++ b/pkg/manager/diff.go @@ -573,6 +573,11 @@ type reproRunnerResult struct { repro *repro.Result } +// Run executes the reproducer 3 times with slightly different options. +// The objective is to verify whether the bug triggered by the reproducer affects the base kernel. +// To avoid reporting false positives, the function does not require the kernel to crash with exactly +// the same crash title as in the original crash report. Any single crash is accepted. +// The result is sent back over the rr.done channel. func (rr *reproRunner) Run(ctx context.Context, r *repro.Result) { pool := rr.kernel.pool cnt := int(rr.running.Add(1)) @@ -583,17 +588,19 @@ func (rr *reproRunner) Run(ctx context.Context, r *repro.Result) { }() ret := reproRunnerResult{origReport: r.Report, repro: r} - - var result *instance.RunResult - var err error - for i := 0; i < 3; i++ { + for doneRuns := 0; doneRuns < 3; { + if ctx.Err() != nil { + return + } opts := r.Opts opts.Repeat = true - if i == 0 || i == 1 { + if doneRuns < 2 { // Two times out of 3, test with Threaded=true. - // The third time we leave it as is in case it was important. + // The third time we leave it as it was in the reproducer (in case it was important). opts.Threaded = true } + var err error + var result *instance.RunResult runErr := pool.Run(ctx, func(ctx context.Context, inst *vm.Instance, updInfo dispatcher.UpdateInfo) { var ret *instance.ExecProgInstance ret, err = instance.SetupExecProg(inst, rr.kernel.cfg, rr.kernel.reporter, nil) @@ -606,20 +613,24 @@ func (rr *reproRunner) Run(ctx context.Context, r *repro.Result) { Opts: opts, }) }) + logPrefix := fmt.Sprintf("attempt #%d to run %q on base", doneRuns, ret.origReport.Title) if errors.Is(runErr, context.Canceled) { - break + // Just exit without sending anything over the channel. + log.Logf(1, "%s: aborting due to context cancelation", logPrefix) + return + } else if runErr != nil || err != nil { + log.Logf(1, "%s: skipping due to errors: %v / %v", logPrefix, runErr, err) + continue } - crashed := result != nil && result.Report != nil - log.Logf(1, "attempt #%d to run %q on base: crashed=%v", i, ret.origReport.Title, crashed) - if crashed { + doneRuns++ + if result != nil && result.Report != nil { + log.Logf(1, "%s: crashed with %s", logPrefix, result.Report.Title) ret.crashReport = result.Report break + } else { + log.Logf(1, "%s: did not crash", logPrefix) } } - if err != nil { - log.Errorf("failed to run repro: %v", err) - return - } select { case rr.done <- ret: case <-ctx.Done(): |
