Skip to content

Reject module cross-slot BlockClientOnKeys in cluster mode - #4541

Open
enjoy-binbin wants to merge 1 commit into
valkey-io:unstablefrom
enjoy-binbin:test_assert_repo
Open

Reject module cross-slot BlockClientOnKeys in cluster mode#4541
enjoy-binbin wants to merge 1 commit into
valkey-io:unstablefrom
enjoy-binbin:test_assert_repo

Conversation

@enjoy-binbin

Copy link
Copy Markdown
Member

If a module blocks a client on keys from different slots, the blocked
client is later checked by clientsCronHandleTimeout(), which calls
clusterRedirectBlockedClientIfNeeded(). There it hits the slot == c->slot
assertion (added in #2165), since we do not allow cross-slot commands,
and the server aborts.

A module can reach this through incorrect use of the API. Even though
it is a misuse, it should not be able to crash the server, so reject it
in moduleBlockClient() and reply with an error instead of blocking.

This adds one more error path that aborts after the blocked handle has
been allocated. Such paths must reset bc->client to NULL, otherwise a
later VM_UnblockClient() dereferences will crash the server. Only the
Lua/MULTI path did this; apply the same to the other paths as well.

If a module blocks a client on keys from different slots, the blocked
client is later checked by clientsCronHandleTimeout(), which calls
clusterRedirectBlockedClientIfNeeded(). There it hits the slot == c->slot
assertion (added in valkey-io#2165), since we do not allow cross-slot commands,
and the server aborts.

A module can reach this through incorrect use of the API. Even though
it is a misuse, it should not be able to crash the server, so reject it
in moduleBlockClient() and reply with an error instead of blocking.

This adds one more error path that aborts after the blocked handle has
been allocated. Such paths must reset bc->client to NULL, otherwise a
later VM_UnblockClient() dereferences will crash the server. Only the
Lua/MULTI path did this; apply the same to the other paths as well.

Signed-off-by: Binbin <binloveplay1314@qq.com>
@coderabbitai

coderabbitai Bot commented Aug 28, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8be080a9-77f8-46b5-81d0-a9df5e35f1e3

📥 Commits

Reviewing files that changed from the base of the PR and between 7bf7daa and 8b23d87.

📒 Files selected for processing (4)
  • src/module.c
  • tests/modules/blockonkeys.c
  • tests/unit/moduleapi/blockonkeys.tcl
  • tests/unit/moduleapi/cluster.tcl

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

moduleBlockClient now clears its client pointer on aborted blocking paths and rejects cross-slot blocking in cluster mode. Module commands and unit tests cover timeout, transaction, Lua, immediate-unblock, and multi-slot cases.

Changes

Module blocking validation

Layer / File(s) Summary
Aborted handle cleanup
src/module.c, tests/modules/blockonkeys.c, tests/unit/moduleapi/blockonkeys.tcl
moduleBlockClient initializes and clears bc->client across blocking error paths. Test commands exercise immediate unblocking, timeout overflow, MULTI, and Lua execution.
Cluster slot validation
src/module.c, tests/modules/blockonkeys.c, tests/unit/moduleapi/cluster.tcl
Cluster mode rejects blocking requests whose keys use different hash slots. Tests verify the error, server responsiveness, and zero blocked clients.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to 8b23d

The PR rejects invalid cross-slot module blocking requests and safely cleans up rejected handles, preventing a server crash without changing valid blocking behavior. No actionable merge-blocking risk remains after normal checks and review.

Suggested reviewers: zuiderkwast, quanyeyang, eifrah-aws

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 1 files. (3 skipped: 2… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the primary change: rejecting cross-slot module BlockClientOnKeys requests in cluster mode.
Description check ✅ Passed The description directly explains the cluster-mode crash risk, the new rejection behavior, and the bc->client reset changes across error paths.
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.
Full details: Docstring Coverage

Explanation

Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 1 files. (3 skipped: 2 unsupported, 1 too large.)

  • Fix all pre-merge checks with AI

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.

@valkey-review-bot

Copy link
Copy Markdown
Contributor

DCO is failing for commit 3b9fdd2: the commit message is missing a matching Signed-off-by: trailer. Please amend/sign off the commit and force-push the branch.

@valkey-review-bot valkey-review-bot 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.

The implementation builds cleanly, but one cluster-mode compatibility case is lost.

Comment thread src/module.c
} else {
if (keys) {
/* In cluster mode, reject blocking on keys from different slots. */
if (server.cluster_enabled) {

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.

This rejects cross-slot blocking even when a module has set VALKEYMODULE_CLUSTER_FLAG_NO_REDIRECTION. That flag explicitly gives modules freedom to access every key regardless of slot (VM_SetClusterFlags at src/module.c:9889), and the normal cluster gate honors it in getNodeByQuery (src/cluster.c:1060). Keep the same exemption here (and in clusterRedirectBlockedClientIfNeeded, which otherwise still asserts on these clients), so modules implementing their own distribution can continue to block across slots.

@codecov

codecov Bot commented Aug 28, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 15 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.75%. Comparing base (7bf7daa) to head (8b23d87).

Files with missing lines Patch % Lines
src/module.c 0.00% 15 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##           unstable    #4541      +/-   ##
============================================
- Coverage     78.83%   78.75%   -0.09%     
============================================
  Files           171      171              
  Lines         89857    89871      +14     
============================================
- Hits          70838    70774      -64     
- Misses        19019    19097      +78     
Files with missing lines Coverage Δ
src/module.c 25.30% <0.00%> (-0.07%) ⬇️

... and 21 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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.

1 participant