Skip to content

Context Cancellation Select #105

@FarhanSajid1

Description

@FarhanSajid1

Describe the mistake

In section 8.6.4 "catching a context cancellation", we have the following solution for handling a context cancellation prior to reading/writing from a channel


func f(ctx context.Context) error {
    // ...
    select {
    case <-ctx.Done():
        return ctx.Err()
    case ch1 <- struct{}{}:
    }
    select {
    case <-ctx.Done():
        return ctx.Err()
    case v := <-ch2:
// ... }
}

Essentially, check if the context is done prior to reading/writing.

This is contradicted by mistake #64 (Expecting deterministic behavior using select and channels)

Which goes into detail about this

_If one or more of the communications can proceed, a single one that can proceed is chosen via a uniform pseudo-random selection.
_

Given that, we cannot use the following approach, what if both are able to be read, the go runtime will choose one at random and that could potentially block?

Solution

I've seen the following solution, it's not the best, but it should work

    ticker := time.NewTicker(time.Second)
    defer ticker.Stop()

    for {            
        //select as usual
        select {
        case <-ctx.Done():
            return
        case <-ticker.C:
            //give priority to a possible concurrent Done() event non-blocking way
            select {
              case <-ctx.Done():
              return
            default:
            }
            sendHeartbeat()
        }
    }

As outlined here: https://stackoverflow.com/a/51296312

Activity

pellared

pellared commented on Mar 13, 2025

@pellared
Contributor
            select {
              case <-ctx.Done():
              return
            default:
            }

can be simplified to

            if ctx.Err() != nil {
              return
            }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    community mistakeMistakes proposed by the community

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @pellared@FarhanSajid1

        Issue actions

          Context Cancellation Select · Issue #105 · teivah/100-go-mistakes