Skip to content

fix(channelutil): stop join and clone workers on context cancel - #848

Open
dwisiswant0 wants to merge 1 commit into
mainfrom
dwisiswant0/fix/channelutil/stop-join-and-clone-workers-on-context-cancel
Open

dwisiswant0 wants to merge 1 commit into
mainfrom
dwisiswant0/fix/channelutil/stop-join-and-clone-workers-on-context-cancel

Conversation

@dwisiswant0

Copy link
Copy Markdown
Member

JoinChannels.Wait and CloneChannels.Wait could block forever after the
context was cancelled. Only some of the workers' blocking operations
selected on ctx.Done(): the join worker sent to its sink with a bare
"sink <- w", and the clone worker received from its source with a bare
"<-src". In clone, a cancelled drainAndReset also returned only from
the helper, so the worker loop called it again and spun on the
non-empty backlog. Relay workers blocked on a stopped parent kept the
whole tree alive.

Add sendCtx, a send that gives up once ctx is done, and use it for
every send in both workers. The clone worker now selects on ctx.Done()
when receiving from its source and returns when the drain is aborted.
On cancel, workers stop, drop undelivered values and close their sinks,
as before; this is now documented on Join and Clone.

Tests cover cancel with blocked senders and the uncancelled delivery
path for 1 to 7, 9 to 11, 25 and 26 sources and sinks, so
single-worker, padded and multi-level relay trees are all exercised.

Fixes: #838

JoinChannels.Wait and CloneChannels.Wait could block forever after the
context was cancelled. Only some of the workers' blocking operations
selected on ctx.Done(): the join worker sent to its sink with a bare
"sink <- w", and the clone worker received from its source with a bare
"<-src". In clone, a cancelled drainAndReset also returned only from
the helper, so the worker loop called it again and spun on the
non-empty backlog. Relay workers blocked on a stopped parent kept the
whole tree alive.

Add sendCtx, a send that gives up once ctx is done, and use it for
every send in both workers. The clone worker now selects on ctx.Done()
when receiving from its source and returns when the drain is aborted.
On cancel, workers stop, drop undelivered values and close their sinks,
as before; this is now documented on Join and Clone.

Tests cover cancel with blocked senders and the uncancelled delivery
path for 1 to 7, 9 to 11, 25 and 26 sources and sinks, so
single-worker, padded and multi-level relay trees are all exercised.

Fixes: #838
Signed-off-by: Dwi Siswanto <git@dw1.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

channelutil: JoinChannels and CloneChannels Wait never return after the context is cancelled

1 participant