@@ -2342,11 +2342,9 @@ void replicationEmptyDbCallback(void *privdata) {
23422342 * at g_pserver->master, starting from the specified file descriptor. */
23432343void replicationCreateMasterClient (redisMaster *mi, connection *conn, int dbid) {
23442344 serverAssert (mi->master == nullptr );
2345+ replicationDiscardCachedMaster (mi);
2346+ serverAssert (mi->cached_master == nullptr );
23452347 mi->master = createClient (conn, serverTL - g_pserver->rgthreadvar );
2346- if (mi->cached_master != nullptr ) {
2347- freeClientAsync (mi->cached_master );
2348- mi->cached_master = nullptr ;
2349- }
23502348 if (conn)
23512349 {
23522350 serverAssert (connGetPrivateData (mi->master ->conn ) == mi->master );
@@ -4391,11 +4389,9 @@ void replicationCacheMasterUsingMyself(redisMaster *mi) {
43914389 " to synthesize a cached master: I may be able to synchronize with "
43924390 " the new master with just a partial transfer." );
43934391
4394- if (mi->cached_master != nullptr )
4395- {
4396- // This can happen on first load of the RDB, the master we created in config load is stale
4397- freeClient (mi->cached_master );
4398- }
4392+ /* This can happen on first load of the RDB, when the master
4393+ * created during config loading is stale. */
4394+ replicationDiscardCachedMaster (mi);
43994395
44004396 /* This will be used to populate the field g_pserver->master->reploff
44014397 * by replicationCreateMasterClient(). We'll later set the created
@@ -4422,9 +4418,7 @@ void replicationCacheMasterUsingMyself(redisMaster *mi) {
44224418 *
44234419 * Assumes that the passed struct contains valid master info. */
44244420void replicationCacheMasterUsingMaster (redisMaster *mi) {
4425- if (mi->cached_master ) {
4426- freeClient (mi->cached_master );
4427- }
4421+ replicationDiscardCachedMaster (mi);
44284422
44294423 replicationCreateMasterClient (mi, NULL , -1 );
44304424 std::lock_guard<decltype (mi->master ->lock )> lock (mi->master ->lock );
@@ -4440,12 +4434,17 @@ void replicationCacheMasterUsingMaster(redisMaster *mi) {
44404434/* Free a cached master, called when there are no longer the conditions for
44414435 * a partial resync on reconnection. */
44424436void replicationDiscardCachedMaster (redisMaster *mi) {
4443- if (mi->cached_master == NULL ) return ;
4437+ client *cached = mi->cached_master ;
4438+ if (cached == nullptr ) return ;
44444439
44454440 serverLog (LL_NOTICE ," Discarding previously cached master state." );
4446- mi->cached_master ->flags &= ~CLIENT_MASTER ;
4447- freeClientAsync (mi->cached_master );
4448- mi->cached_master = NULL ;
4441+
4442+ /* Transfer ownership before scheduling the client for asynchronous free.
4443+ * No later replication transition may observe the queued client through
4444+ * mi->cached_master. */
4445+ mi->cached_master = nullptr ;
4446+ cached->flags &= ~CLIENT_MASTER ;
4447+ freeClientAsync (cached);
44494448}
44504449
44514450/* Turn the cached master into the current master, using the file descriptor
0 commit comments