# Behavior traces — redis/redis

> Canonical page: https://codevetter.com/unpack/redis/behavior-traces

# Behavior traces — redis/redis

Scanned commit c3215f019a4c11c35d438f241114e94730fe39e5 (2026-09-22). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

Three flows dominate. Startup: `main()` → config → subsystem init → `initServer()` → `InitServerLast()` → `loadDataFromDisk()` → AOF reconciliation → `aeMain()`. Command execution: socket readable → `readQueryFromClient()` → `processInputBuffer()` → `processCommandAndResetClient()` → `processCommand()` → `call()` → handler → `alsoPropagate()` → `propagatePendingCommands()` → `propagateNow()`. Replica bootstrap: `replicaofCommand()` → `replicationSetMaster()` → `connectWithMaster()` → `syncWithMaster()` handshake → `slaveTryPartialResynchronization()` → full sync via `readSyncBulkPayload()`, with the master side running `syncCommand()` → `startBgsaveForReplication()` → `rdbSaveToSlavesSockets()`.
- STARTUP step 1 — `main()` seeds entropy from `time(NULL)^getpid()^tv.tv_usec` into `srand`/`srandom`/`init_genrand64`, calls `crc64_init()`, captures `umask(server.umask = umask(0777))` early to avoid a thread race, and seeds the dict hash with 16 bytes from `getRandomBytes()` — this is what makes hash-flooding attacks impractical. — [src/server.c#L8313-8330](https://github.com/redis/redis/blob/c3215f019a4c11c35d438f241114e94730fe39e5/src/server.c#L8313-L8330)
- STARTUP step 2 — argv parsing in `main()` conceptually appends every `--opt value` pair onto the config file text as newline-separated directives, with documented precedence 'File, stdin, explicit options -- last config is the one that matters', plus special-cases for bare `--save` and `--sentinel`. — [src/server.c#L8390-8460](https://github.com/redis/redis/blob/c3215f019a4c11c35d438f241114e94730fe39e5/src/server.c#L8390-L8460)
- STARTUP step 3 — `initServer()` installs `SIG_IGN` for SIGHUP/SIGPIPE, runs `setupSignalHandlers()`, `ThreadsManager_init()`, `makeThreadKillable()`, then `hashTemplatesInit()`, `createSharedObjects()`, `adjustOpenFilesLimit()` and `monotonicInit(monotonicLogCallback)` before creating the event loop. — [src/server.c#L3024-3110](https://github.com/redis/redis/blob/c3215f019a4c11c35d438f241114e94730fe39e5/src/server.c#L3024-L3110)
- STARTUP step 4 — `initServer()` decides memory accounting once and irreversibly: `server.memory_tracking_enabled = server.key_memory_histograms || clusterSlotStatsEnabled(CLUSTER_SLOT_STATS_MEM)`, documented as disable-able at runtime but never re-enable-able to avoid a full slot re-scan. — [src/server.c#L3084-3090](https://github.com/redis/redis/blob/c3215f019a4c11c35d438f241114e94730fe39e5/src/server.c#L3084-L3090)
- STARTUP step 5 — `InitServerLast()` starts the background subsystems last: `bioInit()`, `initThreadedIO()`, `set_jemalloc_bg_thread()`, and records `server.initial_memory_usage = zmalloc_used_memory()` as the baseline for memory reporting. — [src/server.c#L3365-3370](https://github.com/redis/redis/blob/c3215f019a4c11c35d438f241114e94730fe39e5/src/server.c#L3365-L3370)
- STARTUP step 6 — the load sequence in `main()` is `aofLoadManifestFromDisk()` → `loadDataFromDisk()` → `aofSetupAfterPreloadFile()` → `aofOpenIfNeededOnServerStart()` → `aofDelHistoryFiles()` → `applyAppendOnlyConfig()`, the last of which exists specifically to apply an `appendonly` config change that arrived while loading. — [src/server.c#L8560-8572](https://github.com/redis/redis/blob/c3215f019a4c11c35d438f241114e94730fe39e5/src/server.c#L8560-L8572)
- STARTUP step 7 — in cluster mode `main()` hard-asserts `verifyClusterConfigWithData() == C_OK` after load, then logs 'Ready to accept connections' per non-NULL `server.listeners[j]`, notifies systemd with `READY=1` when `supervised_mode == SUPERVISED_SYSTEMD`, and finally calls `warnAboutInsecureConfig()`. — [src/server.c#L8573-8593](https://github.com/redis/redis/blob/c3215f019a4c11c35d438f241114e94730fe39e5/src/server.c#L8573-L8593)
- COMMAND step 1 — `processCommand()` first postpones the client via `blockPostponeClient(c)` if a module is in a blocked yield that excludes `BUSY_MODULE_YIELD_CLIENTS`, then runs `commandCheckExistence()` and `commandCheckArity()`, rejecting via `rejectCommandSds()`. — [src/server.c#L4680-4730](https://github.com/redis/redis/blob/c3215f019a4c11c35d438f241114e94730fe39e5/src/server.c#L4680-L4730)
- COMMAND step 2 — commands literally named `host:` or `post` are intercepted before any other handling and routed to `securityWarningCommand(c)` returning `C_ERR`, a cross-protocol-scripting (HTTP-to-Redis) defence. — [src/server.c#L4706-4712](https://github.com/redis/redis/blob/c3215f019a4c11c35d438f241114e94730fe39e5/src/server.c#L4706-L4712)
- COMMAND step 3 — commands carrying `CMD_INTERNAL` are made to look nonexistent (`cmd = NULL`) unless the client has `CLIENT_INTERNAL` or `mustObeyClient(c)` is true, so masters and AOF replay are implicitly trusted while ordinary clients cannot even discover them. — [src/server.c#L4714-4720](https://github.com/redis/redis/blob/c3215f019a4c11c35d438f241114e94730fe39e5/src/server.c#L4714-L4720)
- COMMAND step 4 — `CMD_PROTECTED` commands are gated by `allowProtectedAction(server.enable_debug_cmd, c)` for `debugCommand` and `server.enable_module_cmd` for `moduleCommand`, with an error naming `enable-debug-command`/`enable-module-command`. — [src/server.c#L4732-4748](https://github.com/redis/redis/blob/c3215f019a4c11c35d438f241114e94730fe39e5/src/server.c#L4732-L4748)
- COMMAND step 5 — `call()` sets `CLIENT_EXECUTING_COMMAND` to suppress mid-reply client-side-caching pushes, calls `enterExecutionUnit(1, call_timer)`, and skips slowlog/stat updates entirely when `isAOFLoadingContext()` is true. — [src/server.c#L4155-4215](https://github.com/redis/redis/blob/c3215f019a4c11c35d438f241114e94730fe39e5/src/server.c#L4155-L4215)
- COMMAND step 6 — `call()` avoids a `gettimeofday` per command when a hardware monotonic clock is available: it only calls `updateCachedTime(0)` after 10µs of monotonic drift or 25 accumulated calls (`server.accum_call_count_since_ustime > 25`). — [src/server.c#L4185-4208](https://github.com/redis/redis/blob/c3215f019a4c11c35d438f241114e94730fe39e5/src/server.c#L4185-L4208)
- REPLICATION (replica side) — `replicaofCommand()` → `replicationSetMaster(ip, port)` → `connectWithMaster()` installs `syncWithMaster()` as the connection handler, which performs the PING/AUTH/REPLCONF handshake then calls `slaveTryPartialResynchronization(conn, read_reply)`; on `+FULLRESYNC` the handler becomes `readSyncBulkPayload()`. — [src/replication.c#L4490](https://github.com/redis/redis/blob/c3215f019a4c11c35d438f241114e94730fe39e5/src/replication.c#L4490) [src/replication.c#L3621](https://github.com/redis/redis/blob/c3215f019a4c11c35d438f241114e94730fe39e5/src/replication.c#L3621) [src/replication.c#L3538](https://github.com/redis/redis/blob/c3215f019a4c11c35d438f241114e94730fe39e5/src/replication.c#L3538) [src/replication.c#L3143-2952](https://github.com/redis/redis/blob/c3215f019a4c11c35d438f241114e94730fe39e5/src/replication.c#L3143-L2952)
- REPLICATION (master side) — `syncCommand()` handles PSYNC/SYNC and, when no partial resync is possible, calls `startBgsaveForReplication(mincapa, req)` which selects between `rdbSaveBackground()` (disk-backed) and `rdbSaveToSlavesSockets()` (diskless) based on `repl-diskless-sync`. — [src/replication.c#L1208](https://github.com/redis/redis/blob/c3215f019a4c11c35d438f241114e94730fe39e5/src/replication.c#L1208) [src/replication.c#L1123](https://github.com/redis/redis/blob/c3215f019a4c11c35d438f241114e94730fe39e5/src/replication.c#L1123) [src/rdb.c#L2226](https://github.com/redis/redis/blob/c3215f019a4c11c35d438f241114e94730fe39e5/src/rdb.c#L2226) [src/rdb.c#L5298](https://github.com/redis/redis/blob/c3215f019a4c11c35d438f241114e94730fe39e5/src/rdb.c#L5298)
- ATOMIC SLOT MIGRATION — the documented eight-step flow is: destination runs `CLUSTER MIGRATION IMPORT`, source forks and ships a slot snapshot as RESTORE commands over an RDB channel, streams incremental writes over a main channel, pauses writes at catch-up, destination drains and takes ownership, config propagates over the cluster bus, then the source trims migrated keys via `asmTriggerBackgroundTrim()` on a BIO thread. — [src/cluster_asm.c#L18-45](https://github.com/redis/redis/blob/c3215f019a4c11c35d438f241114e94730fe39e5/src/cluster_asm.c#L18-L45) [src/cluster_asm.c#L3144](https://github.com/redis/redis/blob/c3215f019a4c11c35d438f241114e94730fe39e5/src/cluster_asm.c#L3144) [src/cluster_asm.c#L60-100](https://github.com/redis/redis/blob/c3215f019a4c11c35d438f241114e94730fe39e5/src/cluster_asm.c#L60-L100)
- NESTED EVENT LOOP — when `ProcessingEventsWhileBlocked` is set, `beforeSleep()` takes a short-circuit path running only `connTypeProcessPendingData`, `clientCompressionProcessPendingData`, `flushAppendOnlyFile(0)`, `handleClientsWithPendingWrites`, `freeClientsInAsyncFreeQueue`, `processClientsOfAllIOThreads` and `sendPendingClientsToIOThreads`, counting them into `server.events_processed_while_blocked` and returning early. — [src/server.c#L1966-1990](https://github.com/redis/redis/blob/c3215f019a4c11c35d438f241114e94730fe39e5/src/server.c#L1966-L1990)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
