Context
Shutdown and cleanup paths need to be correct before production. The current SIGINT handler performs complex work directly in the signal handler, and cleanup paths risk leaking or freeing the wrong data.
Examples to review:
src/server.c: handle_sigint() iterates server.clients but closes list values as if they are fds; list values are client_t *.
src/server.c: hash tables are freed with free() instead of free_hash_table().
src/core/hashtable.c: free_hash_table() frees value_entry_t but should also free value->ptr.
- Event dispatchers need a cooperative shutdown path instead of abrupt
exit() from a signal handler.
Scope
- Replace signal handler work with a signal-safe shutdown flag.
- Add centralized
shutdown_server() / cleanup routine.
- Correct client cleanup, fd closure, event-loop deregistration, socket unlinking, and database cleanup.
- Fix hash table value payload cleanup.
- Ensure shutdown flushes or intentionally discards pending responses according to documented semantics.
- Add tests for cleanup where feasible, plus sanitizer validation.
Acceptance criteria
- Shutdown under SIGINT/SIGTERM does not call non-async-signal-safe routines from the handler.
- Client fds and allocated client structs are released correctly.
- Store and TTL hash tables free all nested allocations.
- Sanitizer/leak checks pass for startup/shutdown and integration tests.
Context
Shutdown and cleanup paths need to be correct before production. The current SIGINT handler performs complex work directly in the signal handler, and cleanup paths risk leaking or freeing the wrong data.
Examples to review:
src/server.c:handle_sigint()iteratesserver.clientsbut closes list values as if they are fds; list values areclient_t *.src/server.c: hash tables are freed withfree()instead offree_hash_table().src/core/hashtable.c:free_hash_table()freesvalue_entry_tbut should also freevalue->ptr.exit()from a signal handler.Scope
shutdown_server()/ cleanup routine.Acceptance criteria