Chapter 17: Linux Signals and Graceful Shutdown
This chapter lists common Linux signals and their numbers and describes the boundary between asynchronous delivery and safe cleanup.
1. Why synchronous waiting is safer
Only a small set of functions are async-signal-safe. C++ destruction, locks, logging, allocation, and OpenSSL cleanup are unsafe in an asynchronous signal handler. STTNet blocks termination signals before creating threads and waits for them synchronously in the main thread.
2. Common Linux signal numbers
| Signal | Linux number | Meaning and policy |
|---|---|---|
| SIGHUP | 1 | Terminal hangup / commonly reload; not handled automatically |
| SIGINT | 2 | Ctrl-C; waited by waitForTerminationSignal() |
| SIGQUIT | 3 | Quit and possibly core dump; not a normal shutdown request |
| SIGABRT | 6 | abort(); default fatal behavior remains active |
| SIGKILL | 9 | Immediate termination; cannot be caught or cleaned up |
| SIGSEGV | 11 | Invalid memory access; retain default behavior and core dump |
| SIGPIPE | 13 | Write to closed pipe/socket; ignored by setExceptionHandling() |
| SIGTERM | 15 | Standard termination request; waited synchronously |
| SIGCHLD | 17 | Child state change; relevant to process management |
| SIGSTOP | 19 | Forced stop; cannot be caught |
Number note: These are common values on STTNet's Linux target. Code uses symbolic constants such as
SIGTERM; numeric values remain documentation only.3. Complete shutdown model
using stt::system::ServerSetting;
ServerSetting::setExceptionHandling();
// Block SIGINT (2) and SIGTERM (15) before any framework thread exists.
if(!ServerSetting::blockTerminationSignals())
return 1;
stt::network::HttpServer server;
server.setGracefulShutdownTimeout(5000);
if(!server.startListen(8083))
return 2;
// Wait in normal C++ thread context.
const int signalNumber = ServerSetting::waitForTerminationSignal();
if(signalNumber < 0)
return 3;
return server.close() ? 0 : 4;4. SIGTERM versus SIGKILL
SIGTERM (15) requests an orderly shutdown. SIGKILL (9) immediately terminates the process without destructors, log flushing, or cleanup. A typical supervisor sends SIGTERM and uses SIGKILL only after the shutdown grace period expires.
5. Shutdown flow
setExceptionHandling()andblockTerminationSignals()run in the main thread.- Logger, server, Reactor, and Worker objects are created.
- The listener starts.
waitForTerminationSignal()performs the synchronous wait.server.close()runs after SIGINT or SIGTERM is received.
Server destruction, logging, and locking run in normal thread context rather than an asynchronous signal handler.