| 294 | } |
| 295 | |
| 296 | void Server::stop() { |
| 297 | if (!mRunning) return; |
| 298 | |
| 299 | // Unregister from async system |
| 300 | if (mAsyncRunner) { |
| 301 | task::Executor::instance().unregister_runner(mAsyncRunner.get()); |
| 302 | mAsyncRunner.reset(); |
| 303 | } |
| 304 | |
| 305 | // Close all client connections |
| 306 | for (auto& client : mClientSockets) { |
| 307 | if (client.fd != -1) { |
| 308 | close(client.fd); |
| 309 | } |
| 310 | } |
| 311 | mClientSockets.clear(); |
| 312 | |
| 313 | // Close listen socket |
| 314 | if (mListenSocket != -1) { |
| 315 | close(mListenSocket); |
| 316 | mListenSocket = -1; |
| 317 | } |
| 318 | |
| 319 | // Free route handlers to prevent leaks when server lives in a shared library |
| 320 | // (LSAN runs before shared library static destructors) |
| 321 | mRoutes.clear(); |
| 322 | |
| 323 | mRunning = false; |
| 324 | } |
| 325 | |
| 326 | void Server::route(const string& method, const string& path, RouteHandler handler) { |
| 327 | mRoutes.push_back({method, path, handler}); |
nothing calls this directly
no test coverage detected