Task: Implement session cancellation
This page documents a task in the Session lifecycle follow-up story. It captures the goal, current status, acceptance, and any notes or results.
Goal
Cancel all active sessions when the server stops, so it can shut down cleanly under SIGINT or programmatic shutdown. Critical for container orchestration and service restarts.
Status
| Field | Value |
|---|---|
| State | DONE |
| Parent story | Session lifecycle follow-up |
| Now | Completed 2025-12-04. |
| Waiting on | None. |
| Next | None. |
| Last touched | 2025-12-04 |
Acceptance
- Server can stop cleanly with multiple active sessions running.
- All session I/O operations cancelled when
server::stop()is called. - No indefinite hangs during shutdown.
- Sessions log their cancellation for observability.
Plan
(Plan was distilled into the parent story's * Decisions and cleared when the task closed.)
Notes
- Total time spent in v0: ~2:42.
- Important pivot: original plan used Boost.Asio's hierarchical cancellation_signal model — but
cancellation_signalcontains exactly ONE slot that holds ONE handler at a time, so multiple sessions callingslot.assign()overwrite each other. Tests showed only 1/3 sessions cancelled; the Deepseek-suggested idiomatic example segfaulted. - Final solution: explicit session management. Server maintains
std::list<std::shared_ptr<session>>protected by a mutex; sessions added/removed on create/complete;server::stop()explicitly callssession::stop()on each active session;session::stop()closes the connection, causing pending I/O to fail. - Gemini code review pass also caught a race in
main.cpp(redundant signal handler) and an unclean connection-state path inclient.cppon read failure.
Result
Server shuts down cleanly with multiple sessions; all 3/3 sessions properly cancelled in tests; race + clean-state issues fixed via Gemini review.