aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/manager/diff.go
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2025-06-25 11:57:03 +0200
committerAleksandr Nogikh <nogikh@google.com>2025-06-26 12:49:47 +0000
commit803ce19b0a8969a6e25644dad041eb2cffcda94f (patch)
tree1d9e6496b3095c83b5590a74863eae4d2e29f29b /pkg/manager/diff.go
parentc3f8bb06ed4d6ad6211729efcd0d5aa4a26d5c4d (diff)
pkg/manager: use reproducer reliability scores
During diff fuzzing, ignore too unreliable reproducers completely. For moderately reliable ones, do a larger number of runs.
Diffstat (limited to 'pkg/manager/diff.go')
-rw-r--r--pkg/manager/diff.go26
1 files changed, 22 insertions, 4 deletions
diff --git a/pkg/manager/diff.go b/pkg/manager/diff.go
index 61fc91731..3e5a8bf35 100644
--- a/pkg/manager/diff.go
+++ b/pkg/manager/diff.go
@@ -197,8 +197,8 @@ loop:
if ret.Repro.Report.Title == origTitle {
origTitle = "-SAME-"
}
- log.Logf(1, "found repro for %q (orig title: %q), took %.2f minutes",
- ret.Repro.Report.Title, origTitle, ret.Stats.TotalTime.Minutes())
+ log.Logf(1, "found repro for %q (orig title: %q, reliability: %2.f), took %.2f minutes",
+ ret.Repro.Report.Title, origTitle, ret.Repro.Reliability, ret.Stats.TotalTime.Minutes())
g.Go(func() error {
runner.Run(ctx, ret.Repro)
return nil
@@ -575,12 +575,30 @@ type reproRunnerResult struct {
repro *repro.Result
}
+const (
+ // We want to avoid false positives as much as possible, so let's use
+ // a stricter relibability cut-off than what's used inside pkg/repro.
+ reliabilityCutOff = 0.4
+ // 80% reliability x 3 runs is a 0.8% chance of false positives.
+ // 6 runs at 40% reproducibility gives a ~4% false positive chance.
+ reliabilityThreshold = 0.8
+)
+
// 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) {
+ if r.Reliability < reliabilityCutOff {
+ log.Logf(1, "%s: repro is too unreliable, skipping", r.Report.Title)
+ return
+ }
+ needRuns := 3
+ if r.Reliability < reliabilityThreshold {
+ needRuns = 6
+ }
+
pool := rr.kernel.pool
cnt := int(rr.running.Add(1))
pool.ReserveForRun(min(cnt, pool.Total()))
@@ -590,13 +608,13 @@ func (rr *reproRunner) Run(ctx context.Context, r *repro.Result) {
}()
ret := reproRunnerResult{origReport: r.Report, repro: r}
- for doneRuns := 0; doneRuns < 3; {
+ for doneRuns := 0; doneRuns < needRuns; {
if ctx.Err() != nil {
return
}
opts := r.Opts
opts.Repeat = true
- if doneRuns < 2 {
+ if doneRuns%3 != 2 {
// Two times out of 3, test with Threaded=true.
// The third time we leave it as it was in the reproducer (in case it was important).
opts.Threaded = true