diff options
| author | Aleksandr Nogikh <nogikh@google.com> | 2024-07-11 12:24:08 +0200 |
|---|---|---|
| committer | Aleksandr Nogikh <nogikh@google.com> | 2024-07-22 09:10:35 +0000 |
| commit | edb73b3601f18f3fe4bfc4dbb4f2aaf2b4b764c3 (patch) | |
| tree | 620b5538c9c019191b781de2166e555765bf9bb7 | |
| parent | cc2c251549aa339bba0fefed38dba52a1cde5e3a (diff) | |
syz-manager: prioritize manual repro requests
Explicitly enforce the prioritization rules. Add a test to verify them.
| -rw-r--r-- | syz-manager/manager.go | 2 | ||||
| -rw-r--r-- | syz-manager/repro.go | 25 | ||||
| -rw-r--r-- | syz-manager/repro_test.go | 38 |
3 files changed, 62 insertions, 3 deletions
diff --git a/syz-manager/manager.go b/syz-manager/manager.go index 105117ef0..b7c69558a 100644 --- a/syz-manager/manager.go +++ b/syz-manager/manager.go @@ -155,6 +155,7 @@ type Crash struct { instanceName string fromHub bool // this crash was created based on a repro from syz-hub fromDashboard bool // .. or from dashboard + manual bool *report.Report } @@ -1614,6 +1615,7 @@ func (mgr *Manager) dashboardReproTasks() { if len(resp.CrashLog) > 0 { mgr.externalReproQueue <- &Crash{ fromDashboard: true, + manual: resp.Type == dashapi.ManualLog, Report: &report.Report{ Title: resp.Title, Output: resp.CrashLog, diff --git a/syz-manager/repro.go b/syz-manager/repro.go index 8a4e75c27..3e2b2a315 100644 --- a/syz-manager/repro.go +++ b/syz-manager/repro.go @@ -127,14 +127,33 @@ func (m *reproManager) popCrash() *Crash { m.mu.Lock() defer m.mu.Unlock() + newBetter := func(base, new *Crash) bool { + // First, serve manual requests. + if new.manual != base.manual { + return new.manual + } + // Then, deprioritize hub reproducers. + if new.fromHub != base.fromHub { + return !new.fromHub + } + return false + } + + idx := -1 for i, crash := range m.queue { if m.reproducing[crash.FullTitle()] { continue } - m.queue = slices.Delete(m.queue, i, i+1) - return crash + if idx == -1 || newBetter(m.queue[idx], m.queue[i]) { + idx = i + } + } + if idx == -1 { + return nil } - return nil + crash := m.queue[idx] + m.queue = slices.Delete(m.queue, idx, idx+1) + return crash } func (m *reproManager) Loop(ctx context.Context) { diff --git a/syz-manager/repro_test.go b/syz-manager/repro_test.go index 79b482d36..8042c7042 100644 --- a/syz-manager/repro_test.go +++ b/syz-manager/repro_test.go @@ -67,6 +67,44 @@ func TestReproManager(t *testing.T) { t.Fatal("reserved VMs must have dropped to 0") } +func TestReproOrder(t *testing.T) { + mock := &reproMgrMock{ + run: make(chan runCallback), + } + obj := newReproManager(mock, 3, false) + + // The right order is A B C. + crashes := []*Crash{ + { + Report: &report.Report{Title: "A"}, + fromDashboard: true, + manual: true, + }, + { + Report: &report.Report{Title: "B"}, + fromDashboard: true, + }, + { + Report: &report.Report{Title: "C"}, + fromHub: true, + }, + } + + obj.Enqueue(crashes[2]) + obj.Enqueue(crashes[1]) + obj.Enqueue(crashes[0]) + assert.Equal(t, crashes[0], obj.popCrash()) + assert.Equal(t, crashes[1], obj.popCrash()) + assert.Equal(t, crashes[2], obj.popCrash()) + + obj.Enqueue(crashes[1]) + obj.Enqueue(crashes[0]) + obj.Enqueue(crashes[2]) + assert.Equal(t, crashes[0], obj.popCrash()) + assert.Equal(t, crashes[1], obj.popCrash()) + assert.Equal(t, crashes[2], obj.popCrash()) +} + type reproMgrMock struct { reserved atomic.Int64 run chan runCallback |
