diff options
| author | Brad Fitzpatrick <bradfitz@tailscale.com> | 2025-11-08 17:23:33 -0800 |
|---|---|---|
| committer | Brad Fitzpatrick <brad@danga.com> | 2025-11-13 19:20:07 -0800 |
| commit | 146ea42822cce4d9743218c94aaf13d3d171e0a4 (patch) | |
| tree | d6fbfdb59eec1ced6355f126db25c157ba430d6b /util/execqueue/execqueue.go | |
| parent | 08e74effc0f0099b33ef266a098c52a406b76a5b (diff) | |
| download | tailscale-146ea42822cce4d9743218c94aaf13d3d171e0a4.tar.xz tailscale-146ea42822cce4d9743218c94aaf13d3d171e0a4.zip | |
ipn/ipnlocal: remove all the weird locking (LockedOnEntry, UnlockEarly, etc)
Fixes #11649
Updates #16369
Co-authored-by: James Sanderson <jsanderson@tailscale.com>
Change-Id: I63eaa18fe870ddf81d84b949efac4d1b44c3db86
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Diffstat (limited to 'util/execqueue/execqueue.go')
| -rw-r--r-- | util/execqueue/execqueue.go | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/util/execqueue/execqueue.go b/util/execqueue/execqueue.go index 889cea255..dce70c542 100644 --- a/util/execqueue/execqueue.go +++ b/util/execqueue/execqueue.go @@ -12,6 +12,8 @@ import ( type ExecQueue struct { mu sync.Mutex + ctx context.Context // context.Background + closed on Shutdown + cancel context.CancelFunc // closes ctx closed bool inFlight bool // whether a goroutine is running q.run doneWaiter chan struct{} // non-nil if waiter is waiting, then closed @@ -24,6 +26,7 @@ func (q *ExecQueue) Add(f func()) { if q.closed { return } + q.initCtxLocked() if q.inFlight { q.queue = append(q.queue, f) } else { @@ -79,18 +82,32 @@ func (q *ExecQueue) Shutdown() { q.mu.Lock() defer q.mu.Unlock() q.closed = true + if q.cancel != nil { + q.cancel() + } } -// Wait waits for the queue to be empty. +func (q *ExecQueue) initCtxLocked() { + if q.ctx == nil { + q.ctx, q.cancel = context.WithCancel(context.Background()) + } +} + +// Wait waits for the queue to be empty or shut down. func (q *ExecQueue) Wait(ctx context.Context) error { q.mu.Lock() + q.initCtxLocked() waitCh := q.doneWaiter if q.inFlight && waitCh == nil { waitCh = make(chan struct{}) q.doneWaiter = waitCh } + closed := q.closed q.mu.Unlock() + if closed { + return errors.New("execqueue shut down") + } if waitCh == nil { return nil } @@ -98,6 +115,8 @@ func (q *ExecQueue) Wait(ctx context.Context) error { select { case <-waitCh: return nil + case <-q.ctx.Done(): + return errors.New("execqueue shut down") case <-ctx.Done(): return ctx.Err() } |
