Skip to content

Conversation

@wfltaylor
Copy link

Description

If a value is sent to the subject while handleNewConsumer() is running, it is possible for the new consumer to miss this value. This is because the currentValue is read before the state is updated with the channel. This is addressed by setting the current value at the same point that the channel is added to the state.

Checklist

  • this PR is based on the main branch and is up-to-date, if not please rebase your branch on the top of main
  • the commits inside this PR have explicit commit messages
  • unit tests cover the new feature or the bug fix
  • the feature is documented in the README.md if it makes sense
  • the CHANGELOG is up-to-date

@DanDolog
Copy link

DanDolog commented Jun 2, 2025

Hello! I encountered a similar problem. This fix seems to help me. Is there a plan to merge?
Thanks anyway!

@twittemb
Copy link
Contributor

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 29ad29a4ad

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 103 to 107
let consumerId = self.state.withCriticalRegion { state -> Int in
state.ids += 1
state.channels[state.ids] = asyncBufferedChannel
asyncBufferedChannel.send(state.current)
return state.ids

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Avoid resuming consumers while holding subject lock

Calling asyncBufferedChannel.send(state.current) while inside state.withCriticalRegion can synchronously resume an awaiting consumer. If that consumer’s code touches the subject again (e.g., reads value or calls send), it will try to re-enter the same ManagedCriticalState that uses a non‑reentrant os_unfair_lock, leading to a deadlock. This only occurs when a consumer awaits the channel and then re-enters the subject on receipt, but that pattern is common in for‑await loops.

Useful? React with 👍 / 👎.

Copy link
Contributor

@twittemb twittemb Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@codex What do you suggest that solves the initial issue while avoiding re-entrency ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@codex What do you suggest that solves the initial issue while avoiding re-entrency ?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex couldn't complete this request. Try again later.

Comment on lines 114 to 118
let consumerId = self.state.withCriticalRegion { state -> Int in
state.ids += 1
state.channels[state.ids] = asyncBufferedChannel
asyncBufferedChannel.send(state.current)
return state.ids

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Avoid resuming consumers while holding subject lock

Calling asyncBufferedChannel.send(state.current) while inside state.withCriticalRegion can synchronously resume an awaiting consumer. If that consumer’s code touches the subject again (e.g., reads value or calls send), it will try to re-enter the same ManagedCriticalState that uses a non‑reentrant os_unfair_lock, leading to a deadlock. This only occurs when a consumer awaits the channel and then re-enters the subject on receipt, but that pattern is common in for‑await loops.

Useful? React with 👍 / 👎.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@codex What do you suggest that solves the initial issue while avoiding re-entrency ?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

3 participants