Skip to content

mu.lock: after acquiring m.ch, why does the re-check only look at closed and not ctx? #573

Description

@dangquyitt

Hi, I was looking at mu.lock and had a question about this part:

func (m *mu) lock(ctx context.Context) error {
	select {
	case <-m.c.closed:
		return net.ErrClosed
	case <-ctx.Done():
		return fmt.Errorf("failed to acquire lock: %w", ctx.Err())
	case m.ch <- struct{}{}:
		// To make sure the connection is certainly alive.
		// As it's possible the send on m.ch was selected
		// over the receive on closed.
		select {
		case <-m.c.closed:
			// Make sure to release.
			m.unlock()
			return net.ErrClosed
		default:
		}
		return nil
	}
}

After acquiring the lock, closed is checked again in case both branches were ready.

Why isn't ctx.Done() checked here as well?

Could ctx be canceled right after m.ch is selected, causing lock to return nil while holding the lock with an already-canceled context?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions