Skip to content

Fix[bmqc]: first clean and block queues, then unset d_started - #1669

Open
678098 wants to merge 1 commit into
bloomberg:mainfrom
678098:260729_mqtp_set_stopped
Open

Fix[bmqc]: first clean and block queues, then unset d_started#1669
678098 wants to merge 1 commit into
bloomberg:mainfrom
678098:260729_mqtp_set_stopped

Conversation

@678098

@678098 678098 commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

MQTP::stop sets d_started = false first before stopping each dispatcher queue.
This leads to a thread race where dispatcher events being processed in its thread might try to enqueue another event through a dispatcher that is going to close. Since we've set d_started = false, enqueue attempt fails on assertion.

The fix is to set d_started flag only after we've disabled push to each dispatcher queue and cleared its contents. During stop, we just drop any events in queues, so disabling push is equivalent to just dropping a dispatcher event, which is fine at shutdown.

mqtp_crash_sequence

Signed-off-by: Evgeny Malygin <emalygin@bloomberg.net>
@678098
678098 requested a review from a team as a code owner July 29, 2026 23:45
@678098
678098 requested a review from chrisbeard July 30, 2026 00:30
@678098 678098 changed the title Fix[bmqc]: first clean and block queues, then set d_isStopped Fix[bmqc]: first clean and block queues, then unset d_started Jul 30, 2026
{
BSLS_ASSERT_SAFE(isStarted() && "MQTP has not been started");

d_started = false;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It feels like this is a logical bug because we use d_started to indicate the started and stopping states. If the stopping state were distinct, we would be able to test that condition and avoid asserting?

@678098 678098 Jul 30, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

If we have one variable d_state = {stopped, starting, stopping}, it will still assert, unless we change the condition to BSLS_ASSERT(d_state != stopped) everywhere.
If we have a second independent bool flag d_stopped that we set to true during stop() without changing d_started, the assertion will be gone; however, d_stopped flag is useless on its own.
We can achieve the same behavior without introducing a new variable or state.

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.

2 participants