Skip to content

CLIENT UNBLOCK should't be able to unpause paused clients#2117

Merged
enjoy-binbin merged 3 commits intovalkey-io:unstablefrom
enjoy-binbin:fix_block
Jun 10, 2025
Merged

CLIENT UNBLOCK should't be able to unpause paused clients#2117
enjoy-binbin merged 3 commits intovalkey-io:unstablefrom
enjoy-binbin:fix_block

Conversation

@enjoy-binbin
Copy link
Member

When a client is blocked by something like CLIENT PAUSE, we should not
allow CLIENT UNBLOCK timeout to unblock it, since some blocking types
does not has the timeout callback, it will trigger a panic in the core,
people should use CLIENT UNPAUSE to unblock it.

Also using CLIENT UNBLOCK error is not right, it will return a UNBLOCKED
error to the command, people don't expect a SET command to get an error.

So in this commit, in these cases, we will return 0 to CLIENT UNBLOCK
to indicate the unblock is fail. The reason is that we assume that if
a command doesn't expect to be timedout, it also doesn't expect to be
unblocked by CLIENT UNBLOCK.

The old behavior of the following command will trigger panic in timeout
and get UNBLOCKED error in error. Under the new behavior, client unblock
will get the result of 0.

client 1> client pause 100000 write
client 2> set x x

client 1> client unblock 2 timeout
or
client 1> client unblock 2 error

Potentially breaking change, previously allowed CLIENT UNBLOCK error.
Fixes #2111.

…meout callback

When a client is blocked by something like `CLIENT PAUSE`, we should not
allow `CLIENT UNBLOCK timeout` to unblock it, since some blocking types
does not has the timeout callback, it will trigger a panic in the core,
people should use `CLIENT UNPAUSE` to unblock it.

Also using `CLIENT UNBLOCK error` is not right, it will return a UNBLOCKED
error to the command, people don't expect a `SET` command to get an error.

So in this commit, in these cases, we will return 0 to `CLIENT UNBLOCK`
to indicate the unblock is fail. The reason is that we assume that if
a command doesn't expect to be timedout, it also doesn't expect to be
unblocked by `CLIENT UNBLOCK`.

The old behavior of the following command will trigger panic in timeout
and get UNBLOCKED error in error. Under the new behavior, client unblock
will get the result of 0.
```
client 1> client pause 100000 write
client 2> set x x

client 1> client unblock 2 timeout
or
client 1> client unblock 2 error
```

Potentially breaking change, previously allowed `CLIENT UNBLOCK error`.
Fixes valkey-io#2111.

Signed-off-by: Binbin <[email protected]>
@codecov
Copy link

codecov bot commented May 22, 2025

Codecov Report

Attention: Patch coverage is 87.50000% with 1 line in your changes missing coverage. Please review.

Project coverage is 71.21%. Comparing base (36b51c9) to head (4db45f8).
Report is 38 commits behind head on unstable.

Files with missing lines Patch % Lines
src/blocked.c 85.71% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##           unstable    #2117      +/-   ##
============================================
+ Coverage     71.19%   71.21%   +0.02%     
============================================
  Files           122      122              
  Lines         66046    66053       +7     
============================================
+ Hits          47020    47039      +19     
+ Misses        19026    19014      -12     
Files with missing lines Coverage Δ
src/networking.c 87.29% <100.00%> (+0.10%) ⬆️
src/server.h 100.00% <ø> (ø)
src/blocked.c 91.31% <85.71%> (-0.12%) ⬇️

... and 13 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.

Copy link
Contributor

@gmbnomis gmbnomis left a comment

Choose a reason for hiding this comment

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

Although this could be regarded as a breaking change (of undocumented behavior), I think the behavior proposed by this PR is the most consistent option.

Copy link
Member

@ranshid ranshid left a comment

Choose a reason for hiding this comment

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

Overall LGTM. small comment which I myself am not sure of.

@ranshid ranshid added release-notes This issue should get a line item in the release notes breaking-change Indicates a possible backwards incompatible change labels May 26, 2025
Copy link
Contributor

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

LGTM.

Conceptually, for users, blocked clients and paused clients are two separate concepts. They can't be mixed.

We just use the same mechanism internally.

@zuiderkwast zuiderkwast changed the title CLIENT UNBLOCK should't be able to unblock client that doesn't has timeout callback CLIENT UNBLOCK should't be able to unpause paused clients May 26, 2025
@zuiderkwast
Copy link
Contributor

zuiderkwast commented May 26, 2025

Let's backport it to all versions, ok?

Or only backport the client unblock timeout case where it could crash?

@ranshid
Copy link
Member

ranshid commented May 26, 2025

Let's backport it to all versions, ok?

Or only backport the client unblock timeout case where it could crash?

I think cherry picking the exact code would be easier and not a problem. I am not sure why the error is ever used (as I am also not sure when is this API ever used in realtime scenarios and not testing)

@gmbnomis
Copy link
Contributor

gmbnomis commented May 26, 2025

I wonder if the change is more severe than it appears at first glance. One could implement the "monitor a changing set of keys" idea from the documentation of CLIENT UNBLOCK as follows:

Loop forever:

  1. BLPOP <current set of observed keys> 0
  2. If not timed out: work on result

And in parallel:

Trigger when set of keys changes:

  1. Update current set of observed keys
  2. CLIENT UNBLOCK <client id>

Key property today: Client unblocking works even during CLIENT PAUSE, ensuring the key set gets updated on next iteration. (Note that there is no need to even look at the reply of CLIENT UNBLOCK)

The proposed change in this PR creates ambiguity in the CLIENT UNBLOCK response:

"0" reply could now mean either:

  1. Client wasn't blocked
  2. Client couldn't be unblocked due to pause (new meaning)

This will break the code above if the trigger occurs when BLPOP is blocking due to CLIENT PAUSE: The BLPOP will continue to wait using the outdated set of keys even if the clients will be unpaused later.

I still think that unblocking the client is wrong (as said by @zuiderkwast CLIENT PAUSE and blocking commands are two different concepts). But maybe CLIENT UNBLOCK should return an error if the command can't be unblocked due to a CLIENT PAUSE? (or should CLIENT UNBLOCK block?)

@zuiderkwast
Copy link
Contributor

@gmbnomis Good point. It seems that we should unblock the client if it's blocked and paused at the same time. I.e. it should be possible to unblock a BLPOP even during client pause write. Makes sense?

@gmbnomis
Copy link
Contributor

gmbnomis commented May 26, 2025

It seems that we should unblock the client if it's blocked and paused at the same time. I.e. it should be possible to unblock a BLPOP even during client pause write.

That's an interesting perspective. Basically, because pausing clients and blocking commands are different concepts from a user's perspective, we could argue that the user does not need to be concerned with the underlying reason why a blocking command is blocked.

So yes, it makes sense that CLIENT UNBLOCK will just unblock it. And, as this neither reads or writes, this does no harm even if done during a read-write pause. (but I suppose it will be a pain to implement this behavior)

OTOH, my scenario from above turns out to be not fully correct: Today, the server panics when a CLIENT UNBLOCK TIMEOUT is issued for a client that is paused (even if it is a blocking command). Only a CLIENT UNBLOCK ERROR works. So, I wonder if anybody is actually using this pattern...

@zuiderkwast
Copy link
Contributor

zuiderkwast commented May 27, 2025

Today, the server panics when a CLIENT UNBLOCK TIMEOUT is issued for a client that is paused (even if it is a blocking command).

Yes, I can confirm this. This is an even worse bug IMO. It means the server can crash when you try to CLIENT UNBLOCK a client that is blocking on BLPOP. The user may not know that CLIENT PAUSE is in action, for example during a failover or something like that.

The fix prevents the crash, but unfortunately it prevents unblocking BLPOP while clients are paused, but this depends on which was first: block or pause.

  • If a command was blocked before paused, it is possible to unblock it using CLIENT UNBLOCK.
  • If clients were paused before a blocking command was called and blocked, it's not possible to unblock it using CLIENT UNBLOCK.

@gmbnomis
Copy link
Contributor

gmbnomis commented Jun 2, 2025

The fix prevents the crash, but unfortunately it prevents unblocking BLPOP while clients are paused, but this depends on which was first: block or pause.

* If a command was blocked before paused, it is possible to unblock it using CLIENT UNBLOCK.

* If clients were paused before a blocking command was called and blocked, it's not possible to unblock it using CLIENT UNBLOCK.

@zuiderkwast Yes, this is true. I think that none of the alternatives to this behavior is optimal:

  1. Unblock clients regardless of pause/block state
    • Pros: Consistent unblocking behavior.
    • Cons: When clients are paused early in command processing, we lack the necessary context (command type, expected reply) to generate a proper timeout response, especially for module commands. This would likely require a new module API to communicate this information.
  2. Return an error when paused
    • Pros: Simple to implement.
    • Cons: Unexpected for clients, as they may not anticipate this error.
  3. Postpone CLIENT UNBLOCK of a paused command until the pause expires/is lifted
    • Pros: From the client’s perspective, this is similar to option 1 but with some delay—in certain cases (like WAIT), this may be the most logical behavior.
    • Cons: This introduces a (new?) edge case where one command is deferred by another. We’d need to ensure that commands are unblocked and executed in the correct order, but since blocked commands are already managed in a linked list, this might be feasible.

Overall, option 3 makes most sense to me.

@zuiderkwast
Copy link
Contributor

All options have pros and cons. 🤔 They also require more work, and these cases are very unusual. Maybe there is no use case for these combinations?

IMO we can merge this PR. It is simple and it prevents the crash, which is the most important problem to fix. OK?

@enjoy-binbin
Copy link
Member Author

@gmbnomis Thank you for your summary comment
@valkey-io/core-team Please also take a look at the comments above and vote.

@ranshid
Copy link
Member

ranshid commented Jun 3, 2025

The fix prevents the crash, but unfortunately it prevents unblocking BLPOP while clients are paused, but this depends on which was first: block or pause.

* If a command was blocked before paused, it is possible to unblock it using CLIENT UNBLOCK.

* If clients were paused before a blocking command was called and blocked, it's not possible to unblock it using CLIENT UNBLOCK.

@zuiderkwast Yes, this is true. I think that none of the alternatives to this behavior is optimal:

  1. Unblock clients regardless of pause/block state

    • Pros: Consistent unblocking behavior.
    • Cons: When clients are paused early in command processing, we lack the necessary context (command type, expected reply) to generate a proper timeout response, especially for module commands. This would likely require a new module API to communicate this information.
  2. Return an error when paused

    • Pros: Simple to implement.
    • Cons: Unexpected for clients, as they may not anticipate this error.
  3. Postpone CLIENT UNBLOCK of a paused command until the pause expires/is lifted

    • Pros: From the client’s perspective, this is similar to option 1 but with some delay—in certain cases (like WAIT), this may be the most logical behavior.
    • Cons: This introduces a (new?) edge case where one command is deferred by another. We’d need to ensure that commands are unblocked and executed in the correct order, but since blocked commands are already managed in a linked list, this might be feasible.

Overall, option 3 makes most sense to me.

I think that (as I think you also state) the ambiguity was always there. when we pause clients some commands with timeout are not fulfilling the timeout guarantee since it is just too hard to do so. For example we cannot timeout commands which are just sitting in the incoming socket stream as we did not yet parse them.
I think this PR is fine in solving the immediate problem. I would also think that extending CLIENT PAUSE with an extra optional argument (client-id) would be a better choice to extend the API to be more clear and allow unblocking a specific paused client

@zuiderkwast
Copy link
Contributor

Let's merge it so it can be included in

@enjoy-binbin enjoy-binbin requested a review from hpatro June 10, 2025 02:28
@enjoy-binbin enjoy-binbin merged commit 3bc40be into valkey-io:unstable Jun 10, 2025
51 checks passed
@github-project-automation github-project-automation bot moved this to To be backported in Valkey 8.0 Jun 10, 2025
@github-project-automation github-project-automation bot moved this to To be backported in Valkey 8.1 Jun 10, 2025
@github-project-automation github-project-automation bot moved this to To be backported in Valkey 7.2 Jun 10, 2025
@enjoy-binbin enjoy-binbin deleted the fix_block branch June 10, 2025 02:29
@enjoy-binbin enjoy-binbin mentioned this pull request Jun 10, 2025
hpatro pushed a commit to hpatro/valkey that referenced this pull request Jun 10, 2025
…2117)

When a client is blocked by something like `CLIENT PAUSE`, we should not
allow `CLIENT UNBLOCK timeout` to unblock it, since some blocking types
does not has the timeout callback, it will trigger a panic in the core,
people should use `CLIENT UNPAUSE` to unblock it.

Also using `CLIENT UNBLOCK error` is not right, it will return a UNBLOCKED
error to the command, people don't expect a `SET` command to get an error.

So in this commit, in these cases, we will return 0 to `CLIENT UNBLOCK`
to indicate the unblock is fail. The reason is that we assume that if
a command doesn't expect to be timedout, it also doesn't expect to be
unblocked by `CLIENT UNBLOCK`.

The old behavior of the following command will trigger panic in timeout
and get UNBLOCKED error in error. Under the new behavior, client unblock
will get the result of 0.
```
client 1> client pause 100000 write
client 2> set x x

client 1> client unblock 2 timeout
or
client 1> client unblock 2 error
```

Potentially breaking change, previously allowed `CLIENT UNBLOCK error`.
Fixes valkey-io#2111.

Signed-off-by: Binbin <[email protected]>
hpatro pushed a commit that referenced this pull request Jun 11, 2025
When a client is blocked by something like `CLIENT PAUSE`, we should not
allow `CLIENT UNBLOCK timeout` to unblock it, since some blocking types
does not has the timeout callback, it will trigger a panic in the core,
people should use `CLIENT UNPAUSE` to unblock it.

Also using `CLIENT UNBLOCK error` is not right, it will return a UNBLOCKED
error to the command, people don't expect a `SET` command to get an error.

So in this commit, in these cases, we will return 0 to `CLIENT UNBLOCK`
to indicate the unblock is fail. The reason is that we assume that if
a command doesn't expect to be timedout, it also doesn't expect to be
unblocked by `CLIENT UNBLOCK`.

The old behavior of the following command will trigger panic in timeout
and get UNBLOCKED error in error. Under the new behavior, client unblock
will get the result of 0.
```
client 1> client pause 100000 write
client 2> set x x

client 1> client unblock 2 timeout
or
client 1> client unblock 2 error
```

Potentially breaking change, previously allowed `CLIENT UNBLOCK error`.
Fixes #2111.

Signed-off-by: Binbin <[email protected]>
@hpatro hpatro moved this from To be backported to 8.1.2 in Valkey 8.1 Jun 11, 2025
chzhoo pushed a commit to chzhoo/valkey that referenced this pull request Jun 12, 2025
…2117)

When a client is blocked by something like `CLIENT PAUSE`, we should not
allow `CLIENT UNBLOCK timeout` to unblock it, since some blocking types
does not has the timeout callback, it will trigger a panic in the core,
people should use `CLIENT UNPAUSE` to unblock it.

Also using `CLIENT UNBLOCK error` is not right, it will return a UNBLOCKED
error to the command, people don't expect a `SET` command to get an error.

So in this commit, in these cases, we will return 0 to `CLIENT UNBLOCK`
to indicate the unblock is fail. The reason is that we assume that if
a command doesn't expect to be timedout, it also doesn't expect to be
unblocked by `CLIENT UNBLOCK`.

The old behavior of the following command will trigger panic in timeout
and get UNBLOCKED error in error. Under the new behavior, client unblock
will get the result of 0.
```
client 1> client pause 100000 write
client 2> set x x

client 1> client unblock 2 timeout
or
client 1> client unblock 2 error
```

Potentially breaking change, previously allowed `CLIENT UNBLOCK error`.
Fixes valkey-io#2111.

Signed-off-by: Binbin <[email protected]>
Signed-off-by: chzhoo <[email protected]>
vitarb pushed a commit to vitarb/valkey that referenced this pull request Jun 12, 2025
…2117)

When a client is blocked by something like `CLIENT PAUSE`, we should not
allow `CLIENT UNBLOCK timeout` to unblock it, since some blocking types
does not has the timeout callback, it will trigger a panic in the core,
people should use `CLIENT UNPAUSE` to unblock it.

Also using `CLIENT UNBLOCK error` is not right, it will return a UNBLOCKED
error to the command, people don't expect a `SET` command to get an error.

So in this commit, in these cases, we will return 0 to `CLIENT UNBLOCK`
to indicate the unblock is fail. The reason is that we assume that if
a command doesn't expect to be timedout, it also doesn't expect to be
unblocked by `CLIENT UNBLOCK`.

The old behavior of the following command will trigger panic in timeout
and get UNBLOCKED error in error. Under the new behavior, client unblock
will get the result of 0.
```
client 1> client pause 100000 write
client 2> set x x

client 1> client unblock 2 timeout
or
client 1> client unblock 2 error
```

Potentially breaking change, previously allowed `CLIENT UNBLOCK error`.
Fixes valkey-io#2111.

Signed-off-by: Binbin <[email protected]>
(cherry picked from commit 3bc40be)
@vitarb vitarb mentioned this pull request Jun 13, 2025
vitarb pushed a commit to vitarb/valkey that referenced this pull request Jun 13, 2025
…2117)

When a client is blocked by something like `CLIENT PAUSE`, we should not
allow `CLIENT UNBLOCK timeout` to unblock it, since some blocking types
does not has the timeout callback, it will trigger a panic in the core,
people should use `CLIENT UNPAUSE` to unblock it.

Also using `CLIENT UNBLOCK error` is not right, it will return a UNBLOCKED
error to the command, people don't expect a `SET` command to get an error.

So in this commit, in these cases, we will return 0 to `CLIENT UNBLOCK`
to indicate the unblock is fail. The reason is that we assume that if
a command doesn't expect to be timedout, it also doesn't expect to be
unblocked by `CLIENT UNBLOCK`.

The old behavior of the following command will trigger panic in timeout
and get UNBLOCKED error in error. Under the new behavior, client unblock
will get the result of 0.
```
client 1> client pause 100000 write
client 2> set x x

client 1> client unblock 2 timeout
or
client 1> client unblock 2 error
```

Potentially breaking change, previously allowed `CLIENT UNBLOCK error`.
Fixes valkey-io#2111.

Signed-off-by: Binbin <[email protected]>
(cherry picked from commit 3bc40be)
shanwan1 pushed a commit to shanwan1/valkey that referenced this pull request Jun 13, 2025
…2117)

When a client is blocked by something like `CLIENT PAUSE`, we should not
allow `CLIENT UNBLOCK timeout` to unblock it, since some blocking types
does not has the timeout callback, it will trigger a panic in the core,
people should use `CLIENT UNPAUSE` to unblock it.

Also using `CLIENT UNBLOCK error` is not right, it will return a UNBLOCKED
error to the command, people don't expect a `SET` command to get an error.

So in this commit, in these cases, we will return 0 to `CLIENT UNBLOCK`
to indicate the unblock is fail. The reason is that we assume that if
a command doesn't expect to be timedout, it also doesn't expect to be
unblocked by `CLIENT UNBLOCK`.

The old behavior of the following command will trigger panic in timeout
and get UNBLOCKED error in error. Under the new behavior, client unblock
will get the result of 0.
```
client 1> client pause 100000 write
client 2> set x x

client 1> client unblock 2 timeout
or
client 1> client unblock 2 error
```

Potentially breaking change, previously allowed `CLIENT UNBLOCK error`.
Fixes valkey-io#2111.

Signed-off-by: Binbin <[email protected]>
Signed-off-by: shanwan1 <[email protected]>
@ranshid ranshid moved this from To be backported to In Progress in Valkey 7.2 Jun 18, 2025
ranshid pushed a commit to ranshid/valkey that referenced this pull request Jun 18, 2025
…2117)

When a client is blocked by something like `CLIENT PAUSE`, we should not
allow `CLIENT UNBLOCK timeout` to unblock it, since some blocking types
does not has the timeout callback, it will trigger a panic in the core,
people should use `CLIENT UNPAUSE` to unblock it.

Also using `CLIENT UNBLOCK error` is not right, it will return a UNBLOCKED
error to the command, people don't expect a `SET` command to get an error.

So in this commit, in these cases, we will return 0 to `CLIENT UNBLOCK`
to indicate the unblock is fail. The reason is that we assume that if
a command doesn't expect to be timedout, it also doesn't expect to be
unblocked by `CLIENT UNBLOCK`.

The old behavior of the following command will trigger panic in timeout
and get UNBLOCKED error in error. Under the new behavior, client unblock
will get the result of 0.
```
client 1> client pause 100000 write
client 2> set x x

client 1> client unblock 2 timeout
or
client 1> client unblock 2 error
```

Potentially breaking change, previously allowed `CLIENT UNBLOCK error`.
Fixes valkey-io#2111.

Signed-off-by: Binbin <[email protected]>
Signed-off-by: Ran Shidlansik <[email protected]>
ranshid pushed a commit to ranshid/valkey that referenced this pull request Jun 18, 2025
…2117)

When a client is blocked by something like `CLIENT PAUSE`, we should not
allow `CLIENT UNBLOCK timeout` to unblock it, since some blocking types
does not has the timeout callback, it will trigger a panic in the core,
people should use `CLIENT UNPAUSE` to unblock it.

Also using `CLIENT UNBLOCK error` is not right, it will return a UNBLOCKED
error to the command, people don't expect a `SET` command to get an error.

So in this commit, in these cases, we will return 0 to `CLIENT UNBLOCK`
to indicate the unblock is fail. The reason is that we assume that if
a command doesn't expect to be timedout, it also doesn't expect to be
unblocked by `CLIENT UNBLOCK`.

The old behavior of the following command will trigger panic in timeout
and get UNBLOCKED error in error. Under the new behavior, client unblock
will get the result of 0.
```
client 1> client pause 100000 write
client 2> set x x

client 1> client unblock 2 timeout
or
client 1> client unblock 2 error
```

Potentially breaking change, previously allowed `CLIENT UNBLOCK error`.
Fixes valkey-io#2111.

Signed-off-by: Binbin <[email protected]>
Signed-off-by: Ran Shidlansik <[email protected]>
ranshid pushed a commit to ranshid/valkey that referenced this pull request Jun 22, 2025
…2117)

When a client is blocked by something like `CLIENT PAUSE`, we should not
allow `CLIENT UNBLOCK timeout` to unblock it, since some blocking types
does not has the timeout callback, it will trigger a panic in the core,
people should use `CLIENT UNPAUSE` to unblock it.

Also using `CLIENT UNBLOCK error` is not right, it will return a UNBLOCKED
error to the command, people don't expect a `SET` command to get an error.

So in this commit, in these cases, we will return 0 to `CLIENT UNBLOCK`
to indicate the unblock is fail. The reason is that we assume that if
a command doesn't expect to be timedout, it also doesn't expect to be
unblocked by `CLIENT UNBLOCK`.

The old behavior of the following command will trigger panic in timeout
and get UNBLOCKED error in error. Under the new behavior, client unblock
will get the result of 0.
```
client 1> client pause 100000 write
client 2> set x x

client 1> client unblock 2 timeout
or
client 1> client unblock 2 error
```

Potentially breaking change, previously allowed `CLIENT UNBLOCK error`.
Fixes valkey-io#2111.

Signed-off-by: Binbin <[email protected]>
Signed-off-by: Ran Shidlansik <[email protected]>
ranshid pushed a commit that referenced this pull request Jul 7, 2025
When a client is blocked by something like `CLIENT PAUSE`, we should not
allow `CLIENT UNBLOCK timeout` to unblock it, since some blocking types
does not has the timeout callback, it will trigger a panic in the core,
people should use `CLIENT UNPAUSE` to unblock it.

Also using `CLIENT UNBLOCK error` is not right, it will return a UNBLOCKED
error to the command, people don't expect a `SET` command to get an error.

So in this commit, in these cases, we will return 0 to `CLIENT UNBLOCK`
to indicate the unblock is fail. The reason is that we assume that if
a command doesn't expect to be timedout, it also doesn't expect to be
unblocked by `CLIENT UNBLOCK`.

The old behavior of the following command will trigger panic in timeout
and get UNBLOCKED error in error. Under the new behavior, client unblock
will get the result of 0.
```
client 1> client pause 100000 write
client 2> set x x

client 1> client unblock 2 timeout
or
client 1> client unblock 2 error
```

Potentially breaking change, previously allowed `CLIENT UNBLOCK error`.
Fixes #2111.

Signed-off-by: Binbin <[email protected]>
Signed-off-by: Ran Shidlansik <[email protected]>
sundb added a commit to redis/redis that referenced this pull request Jul 24, 2025
This PR is based on valkey-io/valkey#2117

When a client is blocked by something like `CLIENT PAUSE`, we should not
allow `CLIENT UNBLOCK timeout` to unblock it, since some blocking types
does not has the timeout callback, it will trigger a panic in the core,
people should use `CLIENT UNPAUSE` to unblock it.

Also using `CLIENT UNBLOCK error` is not right, it will return a
UNBLOCKED error to the command, people don't expect a `SET` command to
get an error.

So in this commit, in these cases, we will return 0 to `CLIENT UNBLOCK`
to indicate the unblock is fail. The reason is that we assume that if a
command doesn't expect to be timedout, it also doesn't expect to be
unblocked by `CLIENT UNBLOCK`.

The old behavior of the following command will trigger panic in timeout
and get UNBLOCKED error in error. Under the new behavior, client unblock
will get the result of 0.
```
client 1> client pause 100000 write
client 2> set x x

client 1> client unblock 2 timeout
or
client 1> client unblock 2 error
```

---------

Signed-off-by: Binbin <[email protected]>
Co-authored-by: Binbin <[email protected]>
zuiderkwast pushed a commit to vitarb/valkey that referenced this pull request Aug 15, 2025
…2117)

When a client is blocked by something like `CLIENT PAUSE`, we should not
allow `CLIENT UNBLOCK timeout` to unblock it, since some blocking types
does not has the timeout callback, it will trigger a panic in the core,
people should use `CLIENT UNPAUSE` to unblock it.

Also using `CLIENT UNBLOCK error` is not right, it will return a UNBLOCKED
error to the command, people don't expect a `SET` command to get an error.

So in this commit, in these cases, we will return 0 to `CLIENT UNBLOCK`
to indicate the unblock is fail. The reason is that we assume that if
a command doesn't expect to be timedout, it also doesn't expect to be
unblocked by `CLIENT UNBLOCK`.

The old behavior of the following command will trigger panic in timeout
and get UNBLOCKED error in error. Under the new behavior, client unblock
will get the result of 0.
```
client 1> client pause 100000 write
client 2> set x x

client 1> client unblock 2 timeout
or
client 1> client unblock 2 error
```

Potentially breaking change, previously allowed `CLIENT UNBLOCK error`.
Fixes valkey-io#2111.

Signed-off-by: Binbin <[email protected]>
(cherry picked from commit 3bc40be)
zuiderkwast pushed a commit to vitarb/valkey that referenced this pull request Aug 15, 2025
…2117)

When a client is blocked by something like `CLIENT PAUSE`, we should not
allow `CLIENT UNBLOCK timeout` to unblock it, since some blocking types
does not has the timeout callback, it will trigger a panic in the core,
people should use `CLIENT UNPAUSE` to unblock it.

Also using `CLIENT UNBLOCK error` is not right, it will return a UNBLOCKED
error to the command, people don't expect a `SET` command to get an error.

So in this commit, in these cases, we will return 0 to `CLIENT UNBLOCK`
to indicate the unblock is fail. The reason is that we assume that if
a command doesn't expect to be timedout, it also doesn't expect to be
unblocked by `CLIENT UNBLOCK`.

The old behavior of the following command will trigger panic in timeout
and get UNBLOCKED error in error. Under the new behavior, client unblock
will get the result of 0.
```
client 1> client pause 100000 write
client 2> set x x

client 1> client unblock 2 timeout
or
client 1> client unblock 2 error
```

Potentially breaking change, previously allowed `CLIENT UNBLOCK error`.
Fixes valkey-io#2111.

Signed-off-by: Binbin <[email protected]>
(cherry picked from commit 3bc40be)
Signed-off-by: Viktor Söderqvist <[email protected]>
@zuiderkwast zuiderkwast moved this from To be backported to 8.0.5 in Valkey 8.0 Aug 18, 2025
zuiderkwast pushed a commit to vitarb/valkey that referenced this pull request Aug 21, 2025
…2117)

When a client is blocked by something like `CLIENT PAUSE`, we should not
allow `CLIENT UNBLOCK timeout` to unblock it, since some blocking types
does not has the timeout callback, it will trigger a panic in the core,
people should use `CLIENT UNPAUSE` to unblock it.

Also using `CLIENT UNBLOCK error` is not right, it will return a UNBLOCKED
error to the command, people don't expect a `SET` command to get an error.

So in this commit, in these cases, we will return 0 to `CLIENT UNBLOCK`
to indicate the unblock is fail. The reason is that we assume that if
a command doesn't expect to be timedout, it also doesn't expect to be
unblocked by `CLIENT UNBLOCK`.

The old behavior of the following command will trigger panic in timeout
and get UNBLOCKED error in error. Under the new behavior, client unblock
will get the result of 0.
```
client 1> client pause 100000 write
client 2> set x x

client 1> client unblock 2 timeout
or
client 1> client unblock 2 error
```

Potentially breaking change, previously allowed `CLIENT UNBLOCK error`.
Fixes valkey-io#2111.

Signed-off-by: Binbin <[email protected]>
(cherry picked from commit 3bc40be)
Signed-off-by: Viktor Söderqvist <[email protected]>
zuiderkwast pushed a commit that referenced this pull request Aug 22, 2025
When a client is blocked by something like `CLIENT PAUSE`, we should not
allow `CLIENT UNBLOCK timeout` to unblock it, since some blocking types
does not has the timeout callback, it will trigger a panic in the core,
people should use `CLIENT UNPAUSE` to unblock it.

Also using `CLIENT UNBLOCK error` is not right, it will return a UNBLOCKED
error to the command, people don't expect a `SET` command to get an error.

So in this commit, in these cases, we will return 0 to `CLIENT UNBLOCK`
to indicate the unblock is fail. The reason is that we assume that if
a command doesn't expect to be timedout, it also doesn't expect to be
unblocked by `CLIENT UNBLOCK`.

The old behavior of the following command will trigger panic in timeout
and get UNBLOCKED error in error. Under the new behavior, client unblock
will get the result of 0.
```
client 1> client pause 100000 write
client 2> set x x

client 1> client unblock 2 timeout
or
client 1> client unblock 2 error
```

Potentially breaking change, previously allowed `CLIENT UNBLOCK error`.
Fixes #2111.

Signed-off-by: Binbin <[email protected]>
(cherry picked from commit 3bc40be)
Signed-off-by: Viktor Söderqvist <[email protected]>
sarthakaggarwal97 pushed a commit to sarthakaggarwal97/valkey that referenced this pull request Sep 16, 2025
…2117)

When a client is blocked by something like `CLIENT PAUSE`, we should not
allow `CLIENT UNBLOCK timeout` to unblock it, since some blocking types
does not has the timeout callback, it will trigger a panic in the core,
people should use `CLIENT UNPAUSE` to unblock it.

Also using `CLIENT UNBLOCK error` is not right, it will return a UNBLOCKED
error to the command, people don't expect a `SET` command to get an error.

So in this commit, in these cases, we will return 0 to `CLIENT UNBLOCK`
to indicate the unblock is fail. The reason is that we assume that if
a command doesn't expect to be timedout, it also doesn't expect to be
unblocked by `CLIENT UNBLOCK`.

The old behavior of the following command will trigger panic in timeout
and get UNBLOCKED error in error. Under the new behavior, client unblock
will get the result of 0.
```
client 1> client pause 100000 write
client 2> set x x

client 1> client unblock 2 timeout
or
client 1> client unblock 2 error
```

Potentially breaking change, previously allowed `CLIENT UNBLOCK error`.
Fixes valkey-io#2111.

Signed-off-by: Binbin <[email protected]>
(cherry picked from commit 3bc40be)
Signed-off-by: Viktor Söderqvist <[email protected]>
YaacovHazan pushed a commit to YaacovHazan/redis that referenced this pull request Sep 29, 2025
This PR is based on valkey-io/valkey#2117

When a client is blocked by something like `CLIENT PAUSE`, we should not
allow `CLIENT UNBLOCK timeout` to unblock it, since some blocking types
does not has the timeout callback, it will trigger a panic in the core,
people should use `CLIENT UNPAUSE` to unblock it.

Also using `CLIENT UNBLOCK error` is not right, it will return a
UNBLOCKED error to the command, people don't expect a `SET` command to
get an error.

So in this commit, in these cases, we will return 0 to `CLIENT UNBLOCK`
to indicate the unblock is fail. The reason is that we assume that if a
command doesn't expect to be timedout, it also doesn't expect to be
unblocked by `CLIENT UNBLOCK`.

The old behavior of the following command will trigger panic in timeout
and get UNBLOCKED error in error. Under the new behavior, client unblock
will get the result of 0.
```
client 1> client pause 100000 write
client 2> set x x

client 1> client unblock 2 timeout
or
client 1> client unblock 2 error
```

---------

Signed-off-by: Binbin <[email protected]>
Co-authored-by: Binbin <[email protected]>
@rainsupreme rainsupreme moved this from In Progress to 7.2.10 in Valkey 7.2 Sep 29, 2025
YaacovHazan pushed a commit to YaacovHazan/redis that referenced this pull request Sep 30, 2025
This PR is based on valkey-io/valkey#2117

When a client is blocked by something like `CLIENT PAUSE`, we should not
allow `CLIENT UNBLOCK timeout` to unblock it, since some blocking types
does not has the timeout callback, it will trigger a panic in the core,
people should use `CLIENT UNPAUSE` to unblock it.

Also using `CLIENT UNBLOCK error` is not right, it will return a
UNBLOCKED error to the command, people don't expect a `SET` command to
get an error.

So in this commit, in these cases, we will return 0 to `CLIENT UNBLOCK`
to indicate the unblock is fail. The reason is that we assume that if a
command doesn't expect to be timedout, it also doesn't expect to be
unblocked by `CLIENT UNBLOCK`.

The old behavior of the following command will trigger panic in timeout
and get UNBLOCKED error in error. Under the new behavior, client unblock
will get the result of 0.
```
client 1> client pause 100000 write
client 2> set x x

client 1> client unblock 2 timeout
or
client 1> client unblock 2 error
```

---------

Signed-off-by: Binbin <[email protected]>
Co-authored-by: Binbin <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking-change Indicates a possible backwards incompatible change release-notes This issue should get a line item in the release notes

Projects

Status: 7.2.10
Status: 8.0.5
Status: 8.1.2

Development

Successfully merging this pull request may close these issues.

[CRASH] crash when unblocking a client on timeout

6 participants