Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How an os.Signal channel is handled internally in Go?

Tags:

When having the code:

package main

import (
    "os"
    "os/signal"
)

func main() {
    sig := make(chan os.Signal, 1)
    signal.Notify(sig)
    <-sig
}

Runs without problem, of course, blocking until you send a signal that interrupts the program.

But:

package main

func main() {
    sig := make(chan int, 1)
    <-sig
}

throws this error:

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.main()
    /home/user/project/src/main.go:5 +0x4d
exit status 2

While I understand why reading from the int channel causes a deadlock, I have only a suspicion that the os.Signal doesn't because its channel can suffer writes from "the outside" as, well, it handles signals and they come from outside the program.

Is my suspicion somewhat correct? If so, how the runtime handles this differently from other channel types?

Thank you!

like image 490
Vanderson Mota Avatar asked Jun 12 '20 20:06

Vanderson Mota


1 Answers

You have a deadlock because try to receive message from channel but no other goroutine running that is no sender exists. In the same time call to signal.Notify starts watchSignalLoop() goroutine in background and you can verify implementation details here https://golang.org/src/os/signal/signal.go.

Channels don't care about element type unless your element type is larger than 64kB (strictly speaking, there are other nuances, please check the implementation).

Don't guess about how runtime works, make researches about it. For example, you can check what happens when you call make(chan int). You can do go tool compile -S main.go | grep main.go:line of make chan and check which function is called from runtime package. Then just jump to this file and invest your time to understand the implementation. You will see that implementation of channels is thin and straightforward comparing to other things

Hope it helps!

like image 60
Oleg Avatar answered Oct 02 '22 01:10

Oleg