aboutsummaryrefslogtreecommitdiffstats
path: root/pkg
diff options
context:
space:
mode:
authorAndrey Konovalov <andreyknvl@google.com>2017-06-19 14:42:50 +0200
committerAndrey Konovalov <andreyknvl@google.com>2017-06-19 14:51:53 +0200
commit864a841818e1764fab25cae8f3a415e39b01f836 (patch)
treeef904152f088adf6b160ff94214b62036ac26fb5 /pkg
parent02483b6e8ecc8a21f9f525088905211671363d55 (diff)
repro: split ctx.repro() into smaller methods
Diffstat (limited to 'pkg')
-rw-r--r--pkg/repro/repro.go89
1 files changed, 65 insertions, 24 deletions
diff --git a/pkg/repro/repro.go b/pkg/repro/repro.go
index bde09db20..a3f54b9a5 100644
--- a/pkg/repro/repro.go
+++ b/pkg/repro/repro.go
@@ -128,15 +128,7 @@ func Run(crashLog []byte, cfg *mgrconfig.Config, vmPool *vm.Pool, vmIndexes []in
return res, err
}
-func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, error) {
- // Cut programs that were executed after crash.
- for i, ent := range entries {
- if ent.Start > crashStart {
- entries = entries[:i]
- break
- }
- }
-
+func (ctx *context) reproExtractProg(entries []*prog.LogEntry) (*Result, error) {
// Extract last program on every proc.
procs := make(map[int]int)
for i, ent := range entries {
@@ -165,6 +157,7 @@ func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, er
Debug: true,
Repro: true,
}
+
// Execute the suspected programs.
// We first try to execute each program for 10 seconds, that should detect simple crashes
// (i.e. no races and no hangs). Then we execute each program for 5 minutes
@@ -200,11 +193,14 @@ func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, er
Logf(0, "reproducing crash '%v': no program crashed", ctx.crashDesc)
return nil, nil
}
- defer func() {
- res.Opts.Repro = false
- }()
+ return res, nil
+}
+
+func (ctx *context) reproMinimizeProg(res *Result) (*Result, error) {
Logf(2, "reproducing crash '%v': minimizing guilty program", ctx.crashDesc)
+
+ // Minimize calls and arguments.
call := -1
if res.Opts.Fault {
call = res.Opts.FaultCall
@@ -218,8 +214,8 @@ func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, er
return crashed
}, true)
- // Try to "minimize" threaded/collide/sandbox/etc to find simpler reproducer.
- opts = res.Opts
+ // Minimize repro options (threaded, collide, sandbox, etc).
+ opts := res.Opts
opts.Collide = false
crashed, err := ctx.testProg(res.Prog, res.Duration, opts)
if err != nil {
@@ -270,19 +266,27 @@ func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, er
}
}
+ return res, nil
+}
+
+func (ctx *context) reproExtractC(res *Result) (*Result, error) {
+ Logf(2, "reproducing crash '%v': testing C reproducer", ctx.crashDesc)
+
// Try triggering crash with a C reproducer.
- crashed, err = ctx.testCProg(res.Prog, res.Duration, res.Opts)
+ crashed, err := ctx.testCProg(res.Prog, res.Duration, res.Opts)
if err != nil {
return res, err
}
res.CRepro = crashed
- if !crashed {
- return res, nil
- }
+ return res, nil
+}
+
+func (ctx *context) reproMinimizeC(res *Result) (*Result, error) {
+ Logf(2, "reproducing crash '%v': minimizing C reproducer", ctx.crashDesc)
// Try to simplify the C reproducer.
if res.Opts.EnableTun {
- opts = res.Opts
+ opts := res.Opts
opts.EnableTun = false
crashed, err := ctx.testCProg(res.Prog, res.Duration, opts)
if err != nil {
@@ -293,7 +297,7 @@ func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, er
}
}
if res.Opts.Sandbox != "" {
- opts = res.Opts
+ opts := res.Opts
opts.Sandbox = ""
crashed, err := ctx.testCProg(res.Prog, res.Duration, opts)
if err != nil {
@@ -304,7 +308,7 @@ func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, er
}
}
if res.Opts.UseTmpDir {
- opts = res.Opts
+ opts := res.Opts
opts.UseTmpDir = false
crashed, err := ctx.testCProg(res.Prog, res.Duration, opts)
if err != nil {
@@ -315,7 +319,7 @@ func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, er
}
}
if res.Opts.HandleSegv {
- opts = res.Opts
+ opts := res.Opts
opts.HandleSegv = false
crashed, err := ctx.testCProg(res.Prog, res.Duration, opts)
if err != nil {
@@ -326,7 +330,7 @@ func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, er
}
}
if res.Opts.WaitRepeat {
- opts = res.Opts
+ opts := res.Opts
opts.WaitRepeat = false
crashed, err := ctx.testCProg(res.Prog, res.Duration, opts)
if err != nil {
@@ -337,7 +341,7 @@ func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, er
}
}
if res.Opts.Debug {
- opts = res.Opts
+ opts := res.Opts
opts.Debug = false
crashed, err := ctx.testCProg(res.Prog, res.Duration, opts)
if err != nil {
@@ -351,6 +355,43 @@ func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, er
return res, nil
}
+func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, error) {
+ // Cut programs that were executed after crash.
+ for i, ent := range entries {
+ if ent.Start > crashStart {
+ entries = entries[:i]
+ break
+ }
+ }
+
+ res, err := ctx.reproExtractProg(entries)
+ if err != nil {
+ return res, err
+ }
+
+ res, err = ctx.reproMinimizeProg(res)
+ if err != nil {
+ return res, err
+ }
+
+ res, err = ctx.reproExtractC(res)
+ if err != nil {
+ return res, err
+ }
+ if !res.CRepro {
+ res.Opts.Repro = false
+ return res, nil
+ }
+
+ res, err = ctx.reproMinimizeC(res)
+ if err != nil {
+ return res, err
+ }
+
+ res.Opts.Repro = false
+ return res, nil
+}
+
func (ctx *context) testProg(p *prog.Prog, duration time.Duration, opts csource.Options) (crashed bool, err error) {
inst := <-ctx.instances
if inst == nil {