Skip to content

Fix issues in valkeyClusterAsyncCallback#306

Open
bjosv wants to merge 3 commits intovalkey-io:mainfrom
bjosv:fix-valkeyClusterAsyncCallback
Open

Fix issues in valkeyClusterAsyncCallback#306
bjosv wants to merge 3 commits intovalkey-io:mainfrom
bjosv:fix-valkeyClusterAsyncCallback

Conversation

@bjosv
Copy link
Copy Markdown
Collaborator

@bjosv bjosv commented Apr 20, 2026

Fix several issues in the async cluster command callback:

  • NULL dereference on MOVED redirect.
    If valkeyClusterGetValkeyAsyncContext failed after a MOVED redirect, ac_retry was used without a NULL check, causing a crash.
  • Silent callback drop.
    When a retry send or ASKING command failed, the user callback was never invoked, leaving the caller unaware of the failure and unable to clean up privdata.
  • Removed unnecessary NULL check on &acc->cc.

Also restructured the function to use a single exit path, eliminating the retry: and error: goto labels and making the control flow easier to follow. Added asserts to document invariants and a function-level doc comment.

bjosv added 3 commits April 20, 2026 13:24
If valkeyClusterGetValkeyAsyncContext returns NULL for MOVED,
it falls through to goto retry with ac_retry == NULL,
which would crash in valkeyAsyncFormattedCommand.
The ASK case handles this, but MOVED doesn't.

Signed-off-by: Björn Svensson <bjorn.a.svensson@est.tech>
cc is the address of a struct member (&acc->cc).
It can never be NULL unless acc itself is at address 0, which was already checked.
This is dead code that suggests a misunderstanding.

Signed-off-by: Björn Svensson <bjorn.a.svensson@est.tech>
Restructure valkeyClusterAsyncCallback to use a single exit path
ensuring the user callback is always invoked on a failure instead of
being silently dropped when:
- The ASKING command failed to send
- The retry valkeyAsyncFormattedCommand failed

Signed-off-by: Björn Svensson <bjorn.a.svensson@est.tech>
@bjosv bjosv requested a review from zuiderkwast April 22, 2026 07:29
Copy link
Copy Markdown
Collaborator

@zuiderkwast zuiderkwast left a comment

Choose a reason for hiding this comment

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

I haven't read the logic carefully yet but I found some mistakes.

Comment thread src/cluster.c
Comment on lines +2956 to +2958
assert(cad != NULL);
if (cad == NULL)
return;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

assert + if...? Pick one.

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.

Its due to NDEBUG, get asserts in debug builds and tests, but don't crash in release builds.
Maybe its not worth it? I believe we have some legacy code like it

Comment thread src/cluster.c
Comment on lines +2961 to 2962
assert(acc != NULL);
if (acc == NULL) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Same here; either assert or if, not both.

Comment thread src/cluster.c
Comment on lines +2970 to +2972
assert(command != NULL);
if (command == NULL)
goto done;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

And here.

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