Skip to content

Instantly share code, notes, and snippets.

@vyskocilm
Created February 28, 2022 12:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vyskocilm/3fd3cb1a3dacd90d8cf1ca4aa204baf3 to your computer and use it in GitHub Desktop.
Save vyskocilm/3fd3cb1a3dacd90d8cf1ca4aa204baf3 to your computer and use it in GitHub Desktop.
Double signal.NotifyContext
package main
import (
"context"
"log"
"os"
"os/signal"
"sync"
"time"
)
type namedContext struct {
ame string
ctx context.Context
}
func waitAll(ctxs []namedContext) chan struct{} {
var wg sync.WaitGroup
ret := make(chan struct{})
for _, n := range ctxs {
wg.Add(1)
n := n
go func() {
defer wg.Done()
<-n.ctx.Done()
log.Printf("%s.Done()", n.ame)
}()
}
go func() {
wg.Wait()
close(ret)
}()
return ret
}
func main() {
ctx1, cancel1 := signal.NotifyContext(context.Background(), os.Interrupt)
defer func() {
log.Printf("cancel1()")
cancel1()
}()
ctx2, cancel2 := signal.NotifyContext(ctx1, os.Interrupt)
defer func() {
log.Printf("cancel2()")
cancel2()
}()
go func() {
log.Printf("INFO: waiting before killing myself")
time.Sleep(2 * time.Second)
me, err := os.FindProcess(os.Getpid())
if err != nil {
log.Fatal(err)
}
log.Printf("INFO: kill %d", os.Getpid())
me.Signal(os.Interrupt)
}()
ctxs := []namedContext{
{"ctx1", ctx1},
{"ctx2", ctx2},
}
select {
case <-context.TODO().Done():
log.Printf("context.TODO().Done()")
case <-waitAll(ctxs):
log.Printf("ctx1.Done(), ctx2.Done()")
}
log.Println("fini")
}
@vyskocilm
Copy link
Author

Output when running:

2022/02/28 13:54:23 INFO: waiting before killing myself
2022/02/28 13:54:25 INFO: kill 6084
2022/02/28 13:54:25 ctx2.Done()
2022/02/28 13:54:25 ctx1.Done()
2022/02/28 13:54:25 ctx1.Done(), ctx2.Done()
2022/02/28 13:54:25 fini
2022/02/28 13:54:25 cancel2()
2022/02/28 13:54:25 cancel1()

BTW: you can't run this in Go playground 🤷

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment