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