mirror of https://github.com/redis/redis.git
Prevent crash when cgroups_ref is null in streamEntryIsReferenced() after reload (#14276)
This bug was introduced by https://github.com/redis/redis/pull/14130 found by @oranagra ### Summary Because `s->cgroup_ref` is created at runtime the first time a consumer group is linked with a message, but it is not released when all references are removed. However, after `debug reload` or restart, if the PEL is empty (meaning no consumer group is referencing any message), `s->cgroup_ref` will not be recreated. As a result, when executing XADD or XTRIM with `ACKED` option and checking whether a message that is being read but has not been ACKed can be deleted, the cgroup_ref being NULL will cause a crash. ### Code Path ``` xaddCommand -> streamTrim -> streamEntryIsReferenced ``` ### Solution Check if `s->cgroup_ref` is NULL in streamEntryIsReferenced().
This commit is contained in:
parent
46a3efa750
commit
b9d9d4000b
|
@ -2705,6 +2705,7 @@ int streamEntryIsReferenced(stream *s, streamID *id) {
|
|||
return 1;
|
||||
|
||||
/* Check if the message is in any consumer group's PEL */
|
||||
if (!s->cgroups_ref) return 0;
|
||||
unsigned char buf[sizeof(streamID)];
|
||||
streamEncodeID(buf, id);
|
||||
return raxFind(s->cgroups_ref, buf, sizeof(streamID), NULL);
|
||||
|
|
|
@ -244,6 +244,33 @@ start_server {
|
|||
assert {[r XLEN mystream] == 1} ;# Successfully trimmed to 1 entries
|
||||
}
|
||||
|
||||
test {XADD with ACKED option doesn't crash after DEBUG RELOAD} {
|
||||
r DEL mystream
|
||||
r XADD mystream 1-0 f v
|
||||
|
||||
# Create a consumer group and read one message
|
||||
r XGROUP CREATE mystream mygroup 0
|
||||
set records [r XREADGROUP GROUP mygroup consumer1 COUNT 1 STREAMS mystream >]
|
||||
assert_equal [lindex [r XPENDING mystream mygroup] 0] 1
|
||||
|
||||
# After reload, the reference relationship between consumer groups and messages
|
||||
# is correctly rebuilt, so the previously read but unacked message still cannot be deleted.
|
||||
r DEBUG RELOAD
|
||||
r XADD mystream MAXLEN = 1 ACKED 2-0 f v
|
||||
assert_equal [r XLEN mystream] 2
|
||||
|
||||
# Acknowledge the read message so the PEL becomes empty
|
||||
r XACK mystream mygroup [lindex [lindex [lindex [lindex $records 0] 1] 0] 0]
|
||||
assert {[lindex [r XPENDING mystream mygroup] 0] == 0}
|
||||
|
||||
# After reload, since PEL is empty, no cgroup references will be recreated.
|
||||
r DEBUG RELOAD
|
||||
|
||||
# ACKED option should work correctly even without cgroup references.
|
||||
r XADD mystream MAXLEN = 1 ACKED 3-0 f v
|
||||
assert_equal [r XLEN mystream] 2
|
||||
} {} {needs:debug}
|
||||
|
||||
test {XADD with MAXLEN option and DELREF option} {
|
||||
r DEL mystream
|
||||
r XADD mystream 1-0 f v
|
||||
|
|
Loading…
Reference in New Issue