github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/pkg/fuzzer/queue/retry.go (about)

     1  // Copyright 2024 syzkaller project authors. All rights reserved.
     2  // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
     3  
     4  package queue
     5  
     6  import (
     7  	"fmt"
     8  )
     9  
    10  type retryer struct {
    11  	pq   *PlainQueue
    12  	base Source
    13  }
    14  
    15  // Retry adds a layer that resends results with Status=Restarted.
    16  func Retry(base Source) Source {
    17  	return &retryer{
    18  		base: base,
    19  		pq:   Plain(),
    20  	}
    21  }
    22  
    23  func (r *retryer) Next() *Request {
    24  	req := r.pq.tryNext()
    25  	if req == nil {
    26  		req = r.base.Next()
    27  	}
    28  	if req != nil {
    29  		req.OnDone(r.done)
    30  	}
    31  	return req
    32  }
    33  
    34  func (r *retryer) done(req *Request, res *Result) bool {
    35  	switch res.Status {
    36  	case Success, ExecFailure, Hanged:
    37  		return true
    38  	case Restarted:
    39  		// The input was on a restarted VM.
    40  		r.pq.Submit(req)
    41  		return false
    42  	case Crashed:
    43  		// Retry important requests from crashed VMs once.
    44  		if req.Important && !req.onceCrashed {
    45  			req.onceCrashed = true
    46  			r.pq.Submit(req)
    47  			return false
    48  		}
    49  		return true
    50  	default:
    51  		panic(fmt.Sprintf("unhandled status %v", res.Status))
    52  	}
    53  }