51 lines
1.1 KiB
Go
51 lines
1.1 KiB
Go
// Package ctrlc provides an easy way of having a task that is
|
|
// context-aware and that also deals with interrupt and term signals.
|
|
package ctrlc
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
)
|
|
|
|
// Task is function that can be executed by a ctrlc
|
|
type Task func() error
|
|
|
|
// Ctrlc is the task ctrlc
|
|
type Ctrlc struct {
|
|
signals chan os.Signal
|
|
errs chan error
|
|
}
|
|
|
|
// New returns a new ctrlc with its internals setup.
|
|
func New() *Ctrlc {
|
|
return &Ctrlc{
|
|
signals: make(chan os.Signal, 1),
|
|
errs: make(chan error, 1),
|
|
}
|
|
}
|
|
|
|
// Default ctrlc instance
|
|
var Default = New()
|
|
|
|
// Run executes a given task with a given context, dealing with its timeouts,
|
|
// cancels and SIGTERM and SIGINT signals.
|
|
// It will return an error if the context is canceled, if deadline exceeds,
|
|
// if a SIGTERM or SIGINT is received and of course if the task itself fails.
|
|
func (c *Ctrlc) Run(ctx context.Context, task Task) error {
|
|
go func() {
|
|
c.errs <- task()
|
|
}()
|
|
signal.Notify(c.signals, syscall.SIGINT, syscall.SIGTERM)
|
|
select {
|
|
case err := <-c.errs:
|
|
return err
|
|
case <-ctx.Done():
|
|
return ctx.Err()
|
|
case sig := <-c.signals:
|
|
return fmt.Errorf("received: %s", sig)
|
|
}
|
|
}
|