actors.go 949 B

1234567891011121314151617181920212223242526272829303132333435363738
  1. package run
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "os/signal"
  7. )
  8. // SignalHandler returns an actor, i.e. an execute and interrupt func, that
  9. // terminates with SignalError when the process receives one of the provided
  10. // signals, or the parent context is canceled.
  11. func SignalHandler(ctx context.Context, signals ...os.Signal) (execute func() error, interrupt func(error)) {
  12. ctx, cancel := context.WithCancel(ctx)
  13. return func() error {
  14. c := make(chan os.Signal, 1)
  15. signal.Notify(c, signals...)
  16. select {
  17. case sig := <-c:
  18. return SignalError{Signal: sig}
  19. case <-ctx.Done():
  20. return ctx.Err()
  21. }
  22. }, func(error) {
  23. cancel()
  24. }
  25. }
  26. // SignalError is returned by the signal handler's execute function
  27. // when it terminates due to a received signal.
  28. type SignalError struct {
  29. Signal os.Signal
  30. }
  31. // Error implements the error interface.
  32. func (e SignalError) Error() string {
  33. return fmt.Sprintf("received signal %s", e.Signal)
  34. }