CodeVetter · Repo Unpack · Behavior traces
redis/redis
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.
- 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`.
- 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.
- 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.
- 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.
- 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.
- 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()`.
- 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()`.
- 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.
- 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.
- 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`.
- 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.
- 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`).
- 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()`.
- 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`.
- 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.
- 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.