github.imxd.top/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 }