Skip to content

chore: update submodule data_substrate for cc request bthread mutex deadlock fix - #491

Merged
liunyl merged 4 commits into
mainfrom
update-submodule-bthread-mutex-deadlock-fix
Jun 15, 2026
Merged

chore: update submodule data_substrate for cc request bthread mutex deadlock fix#491
liunyl merged 4 commits into
mainfrom
update-submodule-bthread-mutex-deadlock-fix

Conversation

@liunyl

@liunyl liunyl commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Bumps data_substrate to pull in eloqdata/tx_service#491, which fixes the same deadlock class as the CkptTsCc hang (tx_service#483) in the remaining CC requests.

Bug recap: a bthread::Mutex/ConditionVariable shared between CcRequest::Execute() (runs on the brpc worker main stack via the tx processor module) and a bthread waiter can hang the worker forever: the worker parks as a pthread waiter in the mutex's butex queue, and an unlock routes the wake to a bthread bound to that same blocked worker, which then can never be scheduled (_bound_rq is never stolen).

Requests fixed: ActiveTxMaxTsCc, WaitableCc, ClearCcNodeGroup, EscalateStandbyCcmCc, ClearTxCc, DbSizeCc/RemoteDbSizeCc, UploadBatchCc (+ CcNodeService::UploadBatch handler and the sk_generator upload path). All converted to atomic completion counts + bthread_usleep backoff polling, same as the #483 fix.

For eloqkv specifically this covers the Redis dbsize command (broadcast to all cores with the handler bthread blocked on the request mutex) as well as the standby subscribe/failover RPC paths.

Also picks up the upstream standby replication protocol documentation commit (f62f0fa).

Verification

  • Full Debug build via install/build.sh passes with the bumped submodule (exit 0).
  • Suggested runtime coverage: dbsize, standby subscribe/resubscribe, leader failover.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores
    • Updated an internal subproject/submodule reference to a newer commit (pointer-only change with no user-facing API impact).
  • Bug Fixes
    • Improved behavior and input validation in the eloqkv2rdb utility used for converting data, including more consistent handling of size options and thread-count checks in cloud builds.

@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

This PR updates the data_substrate Git submodule pointer from commit 887e352ac7a00b782e1ed444e75277613c56c75b to 302ef9a6df44dbd945a0038e3f7f4251e30f8fd3, and refactors src/tools/eloqkv2rdb/eloqkv2rdb.cpp to relocate the ParseSizeBytes helper function for broader availability, adjust includes, and reposition conditional compilation guards for cloud-specific validation.

Changes

EloqKV2RDB Tool Refactoring

Layer / File(s) Summary
Includes and ParseSizeBytes Helper Relocation
src/tools/eloqkv2rdb/eloqkv2rdb.cpp
Header includes are updated by adding <cctype> and removing redundant <algorithm>. The ParseSizeBytes inline helper (human-readable size string to byte count conversion) is moved earlier in the file to be available outside the ROCKSDB_CLOUD_EXPORT compilation block.
Conditional Compilation Guard Adjustment
src/tools/eloqkv2rdb/eloqkv2rdb.cpp
The #if ROCKSDB_CLOUD_EXPORT guard in main is repositioned to wrap only the --thread_count upper-bound validation, restricting that check to cloud builds.

Data Substrate Submodule Update

Layer / File(s) Summary
Submodule Reference Update
data_substrate
The data_substrate submodule commit reference is advanced to a new revision.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • eloqdata/eloqkv#482: Both PRs update the data_substrate submodule pointer to different commits with no other code changes.
  • eloqdata/eloqkv#462: Both PRs update the data_substrate submodule pointer to a different upstream commit hash with no other code changes.

Suggested reviewers

  • MrGuin

Poem

🐇 Headers refreshed, a helper takes flight,
ParseSizeBytes dances in broader light,
Cloud guards stand ready with conditions trim,
While data_substrate skips along slim,
Refactored paths make the code so right!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the primary change: updating the data_substrate submodule to fix a bthread mutex deadlock issue affecting CC requests, which is the main objective of the PR.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch update-submodule-bthread-mutex-deadlock-fix

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@liunyl
liunyl force-pushed the update-submodule-bthread-mutex-deadlock-fix branch from af65ebb to 440a66e Compare June 12, 2026 09:50

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@data_substrate`:
- Line 1: Update the submodule bump metadata and add runtime evidence: correct
the tx_service submodule attribution to reference the actual commit(s) (e.g.,
39b801d58e67d6539d1ceab5aed69b294ccea781 and doc commit f62f0fa) and remove or
fix the erroneous “#491” PR tag since the deadlock fix is the commit
9ff97842aaa00138faca6dfff8041864ef6de5c6; include a brief changelog entry that
cites these exact commits (or PR/issue links) for traceability, and attach
concrete runtime/soak test artifacts proving the deadlock fix
(automated/regression tests or logs showing scenarios exercising db size growth,
standby subscribe/resubscribe, and leader failover) so reviewers can validate
the concurrency fix rather than relying on “Debug build passes.”
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f5870113-aa6f-49c4-a06a-e6108397ceea

📥 Commits

Reviewing files that changed from the base of the PR and between af65ebb and 440a66e.

📒 Files selected for processing (1)
  • data_substrate

Comment thread data_substrate Outdated
@liunyl
liunyl force-pushed the update-submodule-bthread-mutex-deadlock-fix branch from 440a66e to c49c402 Compare June 12, 2026 10:07
@liunyl
liunyl force-pushed the update-submodule-bthread-mutex-deadlock-fix branch from c49c402 to 7eec40e Compare June 13, 2026 23:29

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@data_substrate`:
- Line 1: The current verification relies only on a successful build, which
cannot validate a concurrency deadlock fix since bthread mutex deadlocks
manifest at runtime under concurrent load, not compile-time. Execute and
document three categories of runtime tests before merging: (1) DBSIZE broadcast
under concurrent load to stress the CcRequest broadcast path, (2) Standby
replication scenarios (subscribe, resubscribe, failover) to exercise
EscalateStandbyCcmCc, ClearCcNodeGroup, and related request paths, and (3) a
sustained soak/stress test exercising the converted CcRequest types
(ActiveTxMaxTsCc, WaitableCc, ClearTxCc, DbSizeCc, UploadBatchCc) to validate
the atomic completion count and bthread_usleep polling approach prevents worker
thread parking deadlock. Document the test methodology, duration, and results
(logs showing successful completion under load or automated regression test
output).
- Line 1: The PR description incorrectly references tx_service#491 when it
should reference tx_service#470, which contains the actual bthread mutex
deadlock fix. Update the PR description to replace the reference from `#491` to
`#470` and clarify that this PR restructures the flush pipeline through
coroutine-friendly lock management to eliminate the deadlock issue.
Additionally, a Debug build passing does not adequately validate a bthread mutex
deadlock fix since these are runtime concurrency issues; add evidence of runtime
verification such as soak test results or concurrent load testing output (e.g.,
high throughput scenarios with leader failover) to demonstrate the fix resolves
the deadlock under real-world conditions before merging.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 592614e1-6ebc-491b-bc61-b78c07fc5848

📥 Commits

Reviewing files that changed from the base of the PR and between c49c402 and 7eec40e.

📒 Files selected for processing (1)
  • data_substrate

Comment thread data_substrate Outdated
@@ -1 +1 @@
Subproject commit 887e352ac7a00b782e1ed444e75277613c56c75b
Subproject commit 302ef9a6df44dbd945a0038e3f7f4251e30f8fd3

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.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Provide runtime verification for the bthread mutex deadlock fix.

The PR description states "full Debug build with the bumped submodule passes via install/build.sh (exit 0)" as verification. A successful build cannot validate a concurrency deadlock fix—bthread mutex deadlocks manifest under concurrent load at runtime, not at compile time. The suggested runtime coverage (dbsize, standby subscribe/resubscribe, leader failover) must be executed and results documented before merging.

📋 Required runtime verification

Before merging, provide evidence of runtime testing covering the affected code paths:

  1. DBSIZE broadcast: Execute Redis DBSIZE commands under concurrent load to stress the broadcast path that uses the updated CcRequest implementations.

  2. Standby replication: Test standby subscribe, resubscribe, and failover scenarios to exercise the EscalateStandbyCcmCc, ClearCcNodeGroup, and related request paths.

  3. Soak/stress test: Run a sustained concurrent workload that exercises the converted CcRequest types (ActiveTxMaxTsCc, WaitableCc, ClearTxCc, DbSizeCc, UploadBatchCc) to increase confidence that the atomic completion count + bthread_usleep polling approach prevents the worker thread parking deadlock.

Document test methodology, duration, and results (logs showing successful completion under load, or ideally automated regression test output).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@data_substrate` at line 1, The current verification relies only on a
successful build, which cannot validate a concurrency deadlock fix since bthread
mutex deadlocks manifest at runtime under concurrent load, not compile-time.
Execute and document three categories of runtime tests before merging: (1)
DBSIZE broadcast under concurrent load to stress the CcRequest broadcast path,
(2) Standby replication scenarios (subscribe, resubscribe, failover) to exercise
EscalateStandbyCcmCc, ClearCcNodeGroup, and related request paths, and (3) a
sustained soak/stress test exercising the converted CcRequest types
(ActiveTxMaxTsCc, WaitableCc, ClearTxCc, DbSizeCc, UploadBatchCc) to validate
the atomic completion count and bthread_usleep polling approach prevents worker
thread parking deadlock. Document the test methodology, duration, and results
(logs showing successful completion under load or automated regression test
output).

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

NEW_DS_SHA="302ef9a6df44dbd945a0038e3f7f4251e30f8fd3"
DS_REPO="https://github.com/eloqdata/data_substrate.git"
work_dir="temp_ds_verify"

rm -rf "$work_dir"
mkdir -p "$work_dir"
cd "$work_dir"

echo "=== Cloning data_substrate at $NEW_DS_SHA ==="
git clone --no-checkout "$DS_REPO" ds_repo
cd ds_repo
git fetch origin "$NEW_DS_SHA"
git checkout "$NEW_DS_SHA"

echo -e "\n=== Commit message for data_substrate $NEW_DS_SHA ==="
git show -s --format='%s%n%b' "$NEW_DS_SHA" | head -n 40

echo -e "\n=== Check for tx_service submodule pointer ==="
if [ -f .gitmodules ]; then
  cat .gitmodules
  git submodule status || echo "No submodules initialized"
  
  # Get tx_service commit if it exists
  if git config -f .gitmodules --get-regexp 'submodule\..*\.path' | grep -q tx_service; then
    echo -e "\n=== tx_service submodule commit ==="
    git ls-tree HEAD tx_service || echo "tx_service not found in tree"
  fi
else
  echo "No .gitmodules file found"
fi

echo -e "\n=== Search commit message for '`#491`' or 'PR 491' references ==="
git log --oneline --max-count=50 "$NEW_DS_SHA" --grep -E "(`#491`|\bPR.?491\b)" || echo "No '`#491`' references found in last 50 commits"

cd ../..
rm -rf "$work_dir"

Repository: eloqdata/eloqkv

Length of output: 350


🌐 Web query:

eloqdata tx_service PR 491 deadlock bthread mutex

💡 Result:

In the eloqdata/tx_service repository, the issue relating to deadlocks, bthread mutexes, and flush worker operations is primarily addressed in Pull Request #470, titled "refactor flush data worker" [1][2]. While there is no single PR explicitly numbered 491 associated with a deadlock fix in the provided technical logs, PR #470 was a significant architectural change aimed at resolving deadlocks and concurrency issues in the flush data worker pipeline [2]. Key technical details regarding this resolution include: 1. Deadlock Prevention via Coroutine Yielding: The refactor introduced coroutine-friendly yield/resume behavior [1][2]. Previously, the system used bthread::Mutex to synchronize flush work, which could lead to deadlocks when a worker thread waited for a condition while holding a lock that a resuming coroutine needed [1]. The update ensures that locks are unlocked before invoking a resume function if that function might acquire other critical locks [1]. 2. Architectural Changes: The flush workflow was restructured to use per-worker queues and buffers, replacing centralized locking mechanisms that were prone to contention and deadlocks [2]. The changes also included updating datastore handlers to accept optional yield/resume callbacks, preventing blocking operations during data synchronization [2]. 3. Broader Concurrency Management: The codebase includes other mechanisms for deadlock management, such as explicit deadlock detection logic integrated into transaction operations (e.g., in AcquireAllOp and blocking command processing) [3][4]. Earlier fixes in the repository also addressed similar issues, such as ensuring proper cleanup of lock state and avoiding unnecessary blocking when waiting for task completion [5][6][7].

Citations:


Correct PR description: Reference tx_service#470, not #491, for the bthread mutex deadlock fix.

The PR description claims "eloqdata/tx_service#491" addresses the deadlock issue, but web search confirms there is no PR #491 related to deadlock fixes in tx_service. The actual fix is in PR #470 ("refactor flush data worker"), which restructures the flush pipeline to eliminate bthread::Mutex deadlocks through coroutine-friendly lock management. Update the PR description to reference the correct issue.

Additionally, a Debug build passing cannot validate a bthread mutex deadlock fix—these are runtime concurrency issues requiring soak tests or concurrent load testing (e.g., high throughput with leader failover scenarios). Provide runtime verification evidence before merging.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@data_substrate` at line 1, The PR description incorrectly references
tx_service#491 when it should reference tx_service#470, which contains the
actual bthread mutex deadlock fix. Update the PR description to replace the
reference from `#491` to `#470` and clarify that this PR restructures the flush
pipeline through coroutine-friendly lock management to eliminate the deadlock
issue. Additionally, a Debug build passing does not adequately validate a
bthread mutex deadlock fix since these are runtime concurrency issues; add
evidence of runtime verification such as soak test results or concurrent load
testing output (e.g., high throughput scenarios with leader failover) to
demonstrate the fix resolves the deadlock under real-world conditions before
merging.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/tools/eloqkv2rdb/eloqkv2rdb.cpp`:
- Around line 870-873: The multiplication operation in the `ParseSizeBytes`
function at the line where `std::stoull(number_part) * multiplier` is calculated
can silently overflow when processing very large input values, causing the
result to wrap to an invalid smaller value that still passes downstream checks.
Add an overflow guard before the multiplication by checking if `number_part >
UINT64_MAX / multiplier` would be true; if so, either cap the value at
UINT64_MAX, throw an exception, or return an error to prevent the silent
misconfiguration of size thresholds.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b70da788-4f67-4241-8033-03da3e9f516c

📥 Commits

Reviewing files that changed from the base of the PR and between 7eec40e and 938ba5c.

📒 Files selected for processing (1)
  • src/tools/eloqkv2rdb/eloqkv2rdb.cpp

Comment on lines +870 to +873
try
{
bytes = std::stoull(number_part) * multiplier;
}

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.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

find . -name "eloqkv2rdb.cpp" -type f

Repository: eloqdata/eloqkv

Length of output: 97


🏁 Script executed:

wc -l src/tools/eloqkv2rdb/eloqkv2rdb.cpp

Repository: eloqdata/eloqkv

Length of output: 100


🏁 Script executed:

sed -n '820,880p' src/tools/eloqkv2rdb/eloqkv2rdb.cpp

Repository: eloqdata/eloqkv

Length of output: 1561


Add overflow check in ParseSizeBytes multiplication.

At line 872, multiplying std::stoull(number_part) * multiplier can silently overflow. If a very large numeric value (e.g., "18446744073709551615KB") is parsed, std::stoull succeeds and returns a uint64_t within range, but the subsequent multiplication overflows and wraps to a smaller positive value. This wrapped value passes the bytes > 0 check and is returned as valid, silently misconfiguring write-buffer flush thresholds.

Proposed fix
     try
     {
-        bytes = std::stoull(number_part) * multiplier;
+        const uint64_t value = std::stoull(number_part);
+        if (value > (std::numeric_limits<uint64_t>::max() / multiplier))
+        {
+            return false;
+        }
+        bytes = value * multiplier;
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/tools/eloqkv2rdb/eloqkv2rdb.cpp` around lines 870 - 873, The
multiplication operation in the `ParseSizeBytes` function at the line where
`std::stoull(number_part) * multiplier` is calculated can silently overflow when
processing very large input values, causing the result to wrap to an invalid
smaller value that still passes downstream checks. Add an overflow guard before
the multiplication by checking if `number_part > UINT64_MAX / multiplier` would
be true; if so, either cap the value at UINT64_MAX, throw an exception, or
return an error to prevent the silent misconfiguration of size thresholds.

liunyl and others added 4 commits June 15, 2026 02:40
…eadlock fix

Pulls in eloqdata/tx_service#491, which fixes the same deadlock class as
the CkptTsCc hang (#483) in the remaining CC requests (ActiveTxMaxTsCc,
WaitableCc, ClearCcNodeGroup, EscalateStandbyCcmCc, ClearTxCc, DbSizeCc,
UploadBatchCc): a bthread::Mutex shared between tx processors (the brpc
worker main stack) and bthread waiters can park the worker forever when
the butex wake is routed to a bthread bound to that worker. For eloqkv
this also covers the Redis dbsize command path.

Also picks up the upstream standby replication protocol documentation
commit (f62f0fa).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
eloqkv_to_rdb is built for WITH_DATA_STORE=ROCKSDB as well as the
RocksDB-Cloud backends, but ParseSizeBytes and ShardProgressPrinter
were defined only inside `#if ROCKSDB_CLOUD_EXPORT` while main()
referenced ParseSizeBytes and ShardProgressPrinter::kMaxScanThreads
unconditionally. In a non-cloud build (the cloud data-store macros are
undefined, so ROCKSDB_CLOUD_EXPORT is undefined) those symbols do not
exist and the tool fails to compile -- a latent regression since #485.

ParseSizeBytes parses --write_block_size into write_block_size_bytes,
which the non-cloud writer (ParseWorker / Rocksdb2RDB) also reads, so it
must be available in both builds: move it (and its <algorithm>/<cctype>
includes) out of the cloud-only block and keep its validation in main()
unconditional. ShardProgressPrinter is genuinely cloud-only, so guard
only its kMaxScanThreads check with ROCKSDB_CLOUD_EXPORT.

Verified with -fsyntax-only in both the non-cloud and cloud configs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
tx_service#491 (bthread-mutex CC-request deadlock fix) was squash-merged
to tx_service main as 4621885. Re-point the submodule from the now-merged
feature-branch commit to that main commit. The squash also brings main
forward to include tx_service#507 (test-only multi-process cluster
harness, under tests/).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@liunyl
liunyl force-pushed the update-submodule-bthread-mutex-deadlock-fix branch from 7819ab4 to dce49a6 Compare June 15, 2026 02:42
@liunyl
liunyl merged commit 547a0e4 into main Jun 15, 2026
4 of 5 checks passed
@liunyl
liunyl deleted the update-submodule-bthread-mutex-deadlock-fix branch June 15, 2026 02:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants