From 7220a9e51d0586fbf973e05d771b15db47669aed Mon Sep 17 00:00:00 2001 From: Kishore Nallan Date: Sun, 17 Sep 2017 13:59:47 +0530 Subject: [PATCH] Cleanly exit server on sigint. Valgrind "definitely lost" and "indirectly lost" are zero now. --- include/http_server.h | 9 ++++++++ src/http_server.cpp | 32 +++++++++++++++++++++----- src/main/typesense_server.cpp | 42 ++++++++++++++++++++++------------- 3 files changed, 62 insertions(+), 21 deletions(-) diff --git a/include/http_server.h b/include/http_server.h index 067d1c95..9f4c5b86 100644 --- a/include/http_server.h +++ b/include/http_server.h @@ -6,6 +6,7 @@ extern "C" { #include "h2o.h" #include "h2o/http1.h" #include "h2o/http2.h" + #include "h2o/multithread.h" } #include @@ -26,8 +27,10 @@ private: h2o_context_t ctx; h2o_accept_ctx_t* accept_ctx; h2o_hostconf_t *hostconf; + h2o_socket_t* listener_socket; h2o_multithread_queue_t* message_queue; h2o_multithread_receiver_t* message_receiver; + bool exit_loop = false; std::vector routes; @@ -77,5 +80,11 @@ public: int run(); + void stop(void (*callback)(void)); + + static void on_stop_server(void *data); + static constexpr const char* AUTH_HEADER = "x-typesense-api-key"; + static constexpr const char* STOP_SERVER_MESSAGE = "STOP_SERVER"; + }; \ No newline at end of file diff --git a/src/http_server.cpp b/src/http_server.cpp index 18ac23ca..9e5b1e83 100644 --- a/src/http_server.cpp +++ b/src/http_server.cpp @@ -61,9 +61,9 @@ int HttpServer::create_listener(void) { } ctx.globalconf->server_name = h2o_strdup(NULL, "", SIZE_MAX); - h2o_socket_t *listener = h2o_evloop_socket_create(ctx.loop, fd, H2O_SOCKET_FLAG_DONT_READ); - listener->data = this; - h2o_socket_read_start(listener, on_accept); + listener_socket = h2o_evloop_socket_create(ctx.loop, fd, H2O_SOCKET_FLAG_DONT_READ); + listener_socket->data = this; + h2o_socket_read_start(listener_socket, on_accept); return 0; } @@ -82,11 +82,27 @@ int HttpServer::run() { return 1; } - while (h2o_evloop_run(ctx.loop, INT32_MAX) == 0); + on(STOP_SERVER_MESSAGE, HttpServer::on_stop_server); + + while(!exit_loop) { + h2o_evloop_run(ctx.loop, INT32_MAX); + } return 0; } +void HttpServer::on_stop_server(void *data) { + auto callback = reinterpret_cast(data); + callback(); +} + +void HttpServer::stop(void (*callback)(void)) { + exit_loop = true; + h2o_socket_read_stop(listener_socket); + h2o_socket_close(listener_socket); + send_message(STOP_SERVER_MESSAGE, (void *)callback); +} + void HttpServer::on_message(h2o_multithread_receiver_t *receiver, h2o_linklist_t *messages) { while (!h2o_linklist_is_empty(messages)) { h2o_generator_t generator = {NULL, NULL}; @@ -309,6 +325,12 @@ void HttpServer::on(const std::string & message, void (*handler)(void*)) { } HttpServer::~HttpServer() { - delete accept_ctx; + h2o_multithread_unregister_receiver(message_queue, message_receiver); + h2o_multithread_destroy_queue(message_queue); delete message_receiver; + + h2o_context_dispose(&ctx); + h2o_evloop_destroy(ctx.loop); + h2o_config_dispose(&config); + delete accept_ctx; } \ No newline at end of file diff --git a/src/main/typesense_server.cpp b/src/main/typesense_server.cpp index 71f47e3a..6ddc4e81 100644 --- a/src/main/typesense_server.cpp +++ b/src/main/typesense_server.cpp @@ -9,8 +9,17 @@ #include "string_utils.h" #include "replicator.h" +HttpServer* server; + +void free_server() { + delete server; +} + void catch_interrupt(int sig) { - std::cout << "Quitting Typesense..." << std::endl; + std::cout << "Stopping Typesense server..." << std::endl; + signal(sig, SIG_IGN); // ignore for now as we want to shut down elegantly + CollectionManager & collectionManager = CollectionManager::get_instance(); + server->stop(&free_server); } int main(int argc, char **argv) { @@ -29,28 +38,28 @@ int main(int argc, char **argv) { CollectionManager & collectionManager = CollectionManager::get_instance(); collectionManager.init(&store, options.get("api-auth-key")); - HttpServer server( + server = new HttpServer( options.get("listen-address"), options.get("listen-port") ); // collection management - server.post("/collections", post_create_collection, true); - server.get("/collections", get_collections, true); - server.del("/collections/:collection", del_drop_collection, true); + server->post("/collections", post_create_collection, true); + server->get("/collections", get_collections, true); + server->del("/collections/:collection", del_drop_collection, true); // document management - server.post("/collections/:collection", post_add_document, true); - server.get("/collections/:collection", get_collection_summary, true); - server.get("/collections/:collection/search", get_search, false); - server.get("/collections/:collection/:id", get_fetch_document, true); - server.del("/collections/:collection/:id", del_remove_document, true); + server->post("/collections/:collection", post_add_document, true); + server->get("/collections/:collection", get_collection_summary, true); + server->get("/collections/:collection/search", get_search, false); + server->get("/collections/:collection/:id", get_fetch_document, true); + server->del("/collections/:collection/:id", del_remove_document, true); // replication - server.get("/replication/updates", get_replication_updates, true, true); + server->get("/replication/updates", get_replication_updates, true, true); - server.on(SEND_RESPONSE_MSG, on_send_response); - server.on(REPLICATION_EVENT_MSG, Replicator::on_replication_event); + server->on(SEND_RESPONSE_MSG, on_send_response); + server->on(REPLICATION_EVENT_MSG, Replicator::on_replication_event); // start a background replication thread if the server is started as a read-only replica if(!options.get("master").empty()) { @@ -63,13 +72,14 @@ int main(int argc, char **argv) { } std::cout << "Typesense server started as a read-only replica... Spawning replication thread..." << std::endl; - std::thread replication_thread([&server, &master_host_port, &store]() { - Replicator::start(&server, master_host_port, store); + std::thread replication_thread([&master_host_port, &store]() { + Replicator::start(::server, master_host_port, store); }); replication_thread.detach(); } - server.run(); + server->run(); + return 0; } \ No newline at end of file