Can unbuffered channel be used to receive signal?

Viewed 2076

In the below code:

package main

import (
    "fmt"
    "os"
    "os/signal"
    "syscall"
)

func main() {

    sigs := make(chan os.Signal, 1)
    done := make(chan bool, 1)

    signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)

    go func() {
        sig := <-sigs
        fmt.Println()
        fmt.Println(sig)
        done <- true
    }()

    fmt.Println("awaiting signal")
    <-done
    fmt.Println("exiting")
}

Size one buffered channel is used for receiving signal.

Unbuffered channels provide guarantee of delivery.

Size one buffered channel provides delayed guarantee


Can we use unbuffered channel in this scenario? sigs := make(chan os.Signal)

1 Answers

From the signal.Notify documentation

Package signal will not block sending to c: the caller must ensure that c has sufficient buffer space to keep up with the expected signal rate. For a channel used for notification of just one signal value, a buffer of size 1 is sufficient.

So, to answer your question:

Unbuffered channels provide guarantee of delivery.

This is incorrect. Delivery can only be guaranteed if you know both the behavior of the sender and receiver.

In this case, the sender is non-blocking. So if the receiver is not waiting for a signal, the message will be discarded.

Size one buffered channel provides delayed guarantee

There is no “delay” in a channel. The buffer is just how many items can be stored in the channel.

Can we use unbuffered channel in this scenario?

The code will probably work, but it is not guaranteed to work. The problem is that you don’t know when this line will get executed:

sig := <-sigs

Any signal which arrives after signal.Notify but before <-sigs will get discarded (if the channel is unbuffered). Remember that signal.Notify is non-blocking—this just means that it will give up instead of wait.

If you don’t want signals to get discarded, use a buffered channel.

This scenario is unlikely, sure. But it is technically possible.

Related