-
Notifications
You must be signed in to change notification settings - Fork 18.3k
Description
1. What version of Go are you using (go version
)?
2. What operating system and processor architecture are you using (go env
)?
go version go1.6 linux/amd64
3. What did you do?
I have summoner process with large number of workers. When disconnected from the server, worker will exit its main loop and call signal.Stop()
on the SIGINT it had previously set-up with signal.Notify()
. At the same time, summoner will attempt to kill it with proc.Signal(os.Interrupt)
.
Sometimes, the interrupt signal gets lost - won't arrive to the channel and will not crash the program either. Below is an example I can replicate the race with, run it over and over and you will see some "signal missed" soon:
while true; do go run signaltest.go; done
package main
import (
"os/signal"
"os"
"fmt"
"time"
)
func connection(disconnected <-chan bool) bool {
in := make(chan os.Signal, 2)
signal.Notify(in, os.Interrupt)
defer signal.Stop(in)
for {
select {
case <-in:
return true
case <-disconnected:
goto check_signal
}
}
check_signal:
signal.Stop(in)
select {
case <- in:
return true
default:
return false
}
}
func killer(disconnected chan<- bool) {
proc, _ := os.FindProcess(os.Getpid())
time.Sleep(100*time.Millisecond)
disconnected <- true
proc.Signal(os.Interrupt)
}
func main() {
disconnected := make(chan bool)
for i := 0; true; i++ {
fmt.Printf("%d: start\n", i)
go killer(disconnected)
if connection(disconnected) {
fmt.Printf(" %d: got signal\n", i)
} else {
fmt.Printf(" %d: missed\n", i)
}
time.Sleep(500*time.Millisecond)
}
}
4. What did you expect to see?
I expected the signal not to get lost. The documentation only states that "When Stop returns, it is guaranteed that c will receive no more signals." , so I'm not sure whether it is the right expectation, if it isn't, then the fix is fairly easy - just keep the signal channel registered the whole time.
5. What did you see instead?
Some of the signals get lost.