Cleanly exit server on sigint.

Valgrind "definitely lost" and "indirectly lost" are zero now.
This commit is contained in:
Kishore Nallan 2017-09-17 13:59:47 +05:30
parent 6a2f2fa26f
commit 7220a9e51d
3 changed files with 62 additions and 21 deletions

View File

@ -6,6 +6,7 @@ extern "C" {
#include "h2o.h"
#include "h2o/http1.h"
#include "h2o/http2.h"
#include "h2o/multithread.h"
}
#include <map>
@ -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<route_path> 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";
};

View File

@ -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<void (*)(void)>(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;
}

View File

@ -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<std::string>("api-auth-key"));
HttpServer server(
server = new HttpServer(
options.get<std::string>("listen-address"),
options.get<uint32_t>("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<std::string>("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;
}