Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to stop a timer correctly?

Tags:

go

goroutine

var timer *time.Timer

func A() {
    timer.Stop() // cancel old timer
    go B() // new timer
}

func B() {
    timer = time.NewTimer(100 * time.Millisecond)
    select {
    case <- timer.C:
    // do something for timeout, like change state
    }
}

Function A and B are all in different goroutines.

Say A is in a RPC goroutine. When application receives RPC request, it will cancel the old timer in B, and start a new timer in another goroutine.

The doc say:

Stop does not close the channel, to prevent a read from the channel succeeding incorrectly.

So how to break the select in B to avoid goroutine leak?

like image 249
lxyscls Avatar asked Oct 26 '25 09:10

lxyscls


1 Answers

Use an additional, independent cancellation signal. Since you already have a select statement in place, another channel is an obvious choice:

import "time"

var timer *time.Timer
var canceled = make(chan struct{})

func A() {
    // cancel all current Bs
    select {
    case canceled <- struct{}{}:
    default:
    }   

    timer.Stop()

    go B()       // new timer
}

func B() {
    timer = time.NewTimer(100 * time.Millisecond)
    select {
    case <-timer.C:
        // do something for timeout, like change state
    case <-canceled:
        // timer aborted
    }
}

Note that all As and Bs race against each other for the timer value. With the code above it is not necessary to have A stop the timer, so you don't need a global timer, eliminating the race:

import "time"

var canceled = make(chan struct{})

func A() {
    // cancel all current Bs
    select {
    case canceled <- struct{}{}:
    default:
    }

    go B()
}

func B() {
    select {
    case <-time.After(100 * time.Millisecond):
        // do something for timeout, like change state
    case <-canceled:
        // aborted
    }
}
like image 128
Peter Avatar answered Oct 29 '25 00:10

Peter



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!