Skip to content

Destroy MPSC queue elements before releasing nodes - #3620

Merged
chenBright merged 1 commit into
apache:masterfrom
songgaoye:fix-mpsc-queue-element-destruction
Oct 18, 2026
Merged

chenBright merged 1 commit into
apache:masterfrom
songgaoye:fix-mpsc-queue-element-destruction

Conversation

@songgaoye

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: resolve

Problem Summary:

MPSCQueue stores each queued value in ManualConstructor<T>, whose
destructor does not automatically destroy the contained object.

When a node is dequeued or discarded during queue destruction, the node is
returned to its allocator without destroying its T value. For non-trivial
types, this skips destructors and can leak resources held by queued elements.

What is changed and the side effects?

Changed:

  • Destroy the contained queue element before returning its node to the
    allocator.
  • Add regression tests covering both pending elements destroyed with the queue
    and elements destroyed after dequeue.

Side effects:

  • Performance effects:

  • Breaking backward compatibility:


Check List:

Copilot AI left a comment

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.

🟢 Approval recommended

The focused cleanup fix covers both removal paths, includes regression tests, and has no unresolved findings.

No open issues 🎉

What changed in this PR

This PR fixes resource leaks in MPSCQueue by destroying stored values before releasing their nodes.

Changes:

  • Add element destruction to the shared dequeue cleanup path.
  • Add regression tests for dequeued elements and elements left pending at queue destruction.
File Description
test/​mpsc_queue_unittest.cc Adds lifetime-tracking regression tests for both cleanup paths.
src/​butil/​containers/​mpsc_queue.h Destroys the stored value before freeing the node.

Review effort: Balanced

@chenBright chenBright left a comment

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.

LGTM

@chenBright
chenBright merged commit 7696e88 into apache:master Oct 18, 2026
25 checks passed
@songgaoye
songgaoye deleted the fix-mpsc-queue-element-destruction branch October 18, 2026 02:58
Sherlock0203 added a commit to Sherlock0203/brpc that referenced this pull request Oct 19, 2026
Bring the apache master line up to f0239d7 into this branch in a
single merge, replacing the two stacked merges with master@36c2d12e
and the macOS fix only. Everything the branch needs from that line is
included: the data-format negotiation (apache#3507), the IPC_V2 data path
(apache#3573), the macOS OpenSSL 4.0 build fix (apache#3616: X509 accessors return
const pointers in the current macos-26-arm64 runner image, fixed with
auto*), and the newer fixes, notably the null-termination of the peer
shm_name in HelloMessage::Deserialize (apache#3605), the MPSC queue node
release ordering (apache#3620) and the MultiFlatMap bucket-head erasure fix
(apache#3617).

Those master changes were built on the timerfd-era close path, which
this branch had replaced with the bthread timer facade,
generation-checked pool teardown and the cleanup worker, so both sides
evolved the same ubshm core after 9334389.

Resolution:
- Close/clear core (UbrTrxClose, UbrTrxCloseCallback,
  UbrClearResourceCheck, ClearTrxResource, UbrPassiveClearTrx,
  UbrTrxCloseCheck) keeps this branch's versions. Master's extra
  start_time/op parameters were unused, and UbrCloseType only chose
  between DeleteTimerSafe and DeleteTimer, which the facade subsumes:
  UbrTimerDelAndWait degrades to the non-blocking delete inside a
  callback. The unused UbrCloseType enum is therefore dropped.
- Master's format-aware initialization is kept: UbrServerTrxInit keeps
  the UbrDataFormat parameter and the Initialize*LegacyFormat split,
  UbrAllocateServerShm/UbrMapRemoteShm(UbrMapRemoteShmAddTimer) keep
  passing it, and ApplyAndMapLocalShm no longer presets the rx capacity
  (InitializeClientLocalLegacyFormat owns that now). All IPC_V2 ring
  code and the negotiation handshake are master's, unchanged, with
  master-side UNLIKELY/LIKELY converted to the module's BAIDU_* macros.
- This branch's fixes that master lacked merge on top: the poller
  re-ADD refresh, butil::atomic for the poller-group flag, the lazy
  bthread timers replacing TimerInit, and the cleanup-worker changes
  (leaked queue, start retry instead of the terminal latch).
- test/brpc_ubring_unittest.cpp: master's IPC_V2 assertions on the
  removed timer_fd/hb_timer_fd fields check the unarmed
  close_timer/hb_timer slots instead, and the UbrCleanupWorkerTest that
  PR LinQuickDev#74's squash dropped is restored alongside master's apache#3605
  hardening of the full_shm_name test. Both sides' suites run.

Tested: the close/cleanup/IPC_V2 resolution was verified on the
equivalent tree before apache#3605 came in -- cmake WITH_UBRING=ON build,
31/31 unit tests, the same under ASAN (detect_leaks=0), and an
example/ubring_performance e2e over the IPC backend (negotiated IPC_V2
path at ~148k QPS, clean teardowns, server kill -9 handled). The new
master commits are additive to that resolution; cmake --build build
--target brpc_ubring_unittest and ./build/test/brpc_ubring_unittest
pass on this exact tree as well.
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