func newSignalCancelCtx(parent context.Context) *signalCancelCtx {
	return &signalCancelCtx{
		Context: parent,
		sigchan: make(chan os.Signal, 1),
	}
}
newSignalCancelCtx returns an initialized signalCancelCtx.
package sigctx
import (
	"context"
	"errors"
	"os"
	"os/signal"
	"sync"
	"time"
)
var Canceled = errors.New("signal received")
type signalCtx struct {
	context.Context
	recv chan struct{}  
	mu      sync.Mutex
	signal  os.Signal
	sigchan chan os.Signal
}
type signalCancelCtx struct {
	context.Context
	mu      sync.Mutex
	err     error
	once    sync.Once
	signal  os.Signal
	sigchan chan os.Signal
}
func WithSignals(parent context.Context, sig ...os.Signal) context.Context {
	sigctx := newSignalCtx(parent)
	signal.Notify(sigctx.sigchan, sig...)
	go func() {
		for {
			select {
			case <-sigctx.Done():
				return
			case sigctx.signal = <-sigctx.sigchan:
				if sigctx.recv != nil {
					sigctx.mu.Lock()
					close(sigctx.recv)  
					sigctx.recv = make(chan struct{})
					sigctx.mu.Unlock()
				}
			}
		}
	}()
	return sigctx
}
func newSignalCtx(parent context.Context) *signalCtx {
	return &signalCtx{
		Context: parent,
		sigchan: make(chan os.Signal, 1),
	}
}
func Signal(ctx context.Context) (os.Signal, error) {
	if sigctx, ok := ctx.(*signalCtx); ok {
		sigctx.mu.Lock()
		defer sigctx.mu.Unlock()
		return sigctx.signal, nil
	}
	return nil, errors.New("Context is not sigctx type")
}
func Recv(ctx context.Context) <-chan struct{} {
	if sigctx, ok := ctx.(*signalCtx); ok {
		sigctx.mu.Lock()
		if sigctx.recv == nil {
			sigctx.recv = make(chan struct{})
		}
		r := sigctx.recv
		sigctx.mu.Unlock()
		return r
	}
	return nil
}
func (sigctx *signalCtx) Deadline() (deadline time.Time, ok bool) {
	return sigctx.Context.Deadline()
}
func (sigctx *signalCtx) Done() <-chan struct{} {
	return sigctx.Context.Done()
}
func (sigctx *signalCtx) Err() error {
	return sigctx.Context.Err()
}
func (sigctx *signalCtx) Value(key interface{}) interface{} {
	return sigctx.Context.Value(key)
}
func WithCancelSignals(parent context.Context, sig ...os.Signal) context.Context {
	cctx, cancel := context.WithCancel(parent)
	sigctx := newSignalCancelCtx(cctx)
	signal.Notify(sigctx.sigchan, sig...)
	go func() {
		for {
			select {
			case <-sigctx.Done():
				return
			case sigctx.signal = <-sigctx.sigchan:
				sigctx.once.Do(func() {
					sigctx.err = Canceled
					cancel()
				})
			}
		}
	}()
	return sigctx
}