diff --git a/src/cluster.c b/src/cluster.c index f77b068b64..e9b1a8b5eb 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -295,15 +295,18 @@ void restoreCommand(client *c) { /* Create the key and set the TTL if any */ kvobj *kv = dbAddInternal(c->db, key, &obj, NULL, &keymeta); + /* Save type: kv may be reallocated by module callbacks during notifyKeyspaceEvent below. */ + int kvtype = kv->type; + /* If minExpiredField was set, then the object is hash with expiration * on fields and need to register it in global HFE DS */ - if (kv->type == OBJ_HASH) { + if (kvtype == OBJ_HASH) { uint64_t minExpiredField = hashTypeGetMinExpire(kv, 1); if (minExpiredField != EB_EXPIRE_TIME_INVALID) estoreAdd(c->db->subexpires, getKeySlot(key->ptr), kv, minExpiredField); } - if (kv->type == OBJ_STREAM) { + if (kvtype == OBJ_STREAM) { stream *s = kv->ptr; if (s->idmp_producers != NULL) { if (dictAdd(c->db->stream_idmp_keys, key, NULL) == DICT_OK) @@ -328,7 +331,7 @@ void restoreCommand(client *c) { * destination key existed. */ if (deleted) { notifyKeyspaceEvent(NOTIFY_OVERWRITTEN, "overwritten", key, c->db->id); - if (oldtype != kv->type) { + if (oldtype != kvtype) { notifyKeyspaceEvent(NOTIFY_TYPE_CHANGED, "type_changed", key, c->db->id); } } diff --git a/src/notify.c b/src/notify.c index 84cd85551a..00dd4a0909 100644 --- a/src/notify.c +++ b/src/notify.c @@ -84,7 +84,10 @@ sds keyspaceEventsFlagsToString(int flags) { * 'type' is the notification class we define in `server.h`. * 'event' is a C string representing the event name. * 'key' is a Redis object representing the key name. - * 'dbid' is the database ID where the key lives. */ + * 'dbid' is the database ID where the key lives. + * + * NOTE: This function may invoke module notification callbacks, which may + * cause the key's kvobj to be reallocated. */ void notifyKeyspaceEvent(int type, const char *event, robj *key, int dbid) { sds chan; robj *chanobj, *eventobj;