github.hscsec.cn/openshift/source-to-image@v1.2.0/pkg/util/timeout.go (about)

     1  package util
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  )
     7  
     8  // TimeoutError is error returned after timeout occurred.
     9  type TimeoutError struct {
    10  	after   time.Duration
    11  	message string
    12  }
    13  
    14  // Error implements the Go error interface.
    15  func (t *TimeoutError) Error() string {
    16  	if len(t.message) > 0 {
    17  		return fmt.Sprintf("%s timed out after %v", t.message, t.after)
    18  	}
    19  	return fmt.Sprintf("function timed out after %v", t.after)
    20  }
    21  
    22  // TimeoutAfter executes the provided function and returns TimeoutError in the
    23  // case that the execution time of the function exceeded the provided duration.
    24  // The provided function is passed the timer in case it wishes to reset it.  If
    25  // so, the following pattern must be used:
    26  // if !timer.Stop() {
    27  //   return &TimeoutError{}
    28  // }
    29  // timer.Reset(timeout)
    30  func TimeoutAfter(t time.Duration, errorMsg string, f func(*time.Timer) error) error {
    31  	c := make(chan error, 1)
    32  	timer := time.NewTimer(t)
    33  	go func() {
    34  		err := f(timer)
    35  		if !IsTimeoutError(err) {
    36  			c <- err
    37  		}
    38  	}()
    39  	select {
    40  	case err := <-c:
    41  		timer.Stop()
    42  		return err
    43  	case <-timer.C:
    44  		return &TimeoutError{after: t, message: errorMsg}
    45  	}
    46  }
    47  
    48  // IsTimeoutError checks if the provided error is a TimeoutError.
    49  func IsTimeoutError(e error) bool {
    50  	_, ok := e.(*TimeoutError)
    51  	return ok
    52  }