From 0602df3b4b56eed0b3760f309480564bab4dec40 Mon Sep 17 00:00:00 2001 From: Mathieu Cayeux Date: Fri, 9 Feb 2024 19:45:51 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=80=20Added=20proper=20server=20stoppi?= =?UTF-8?q?ng?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cmd/console.cpp | 36 ++++++++++++++++++++++++++++++------ src/cmd/console.h | 8 ++++++++ src/server.cpp | 9 ++++++++- src/server.h | 3 ++- src/utils/network.cpp | 7 +++++++ 5 files changed, 55 insertions(+), 8 deletions(-) diff --git a/src/cmd/console.cpp b/src/cmd/console.cpp index 91085d01..871b7ef4 100644 --- a/src/cmd/console.cpp +++ b/src/cmd/console.cpp @@ -8,12 +8,14 @@ #if defined(__linux__) #include #include +#include #elif defined(_WIN32) #include +#include #endif ConsoleManager *ConsoleManager::instance; -ConsoleManager::ConsoleManager() : currentInput("") +ConsoleManager::ConsoleManager() : currentInput(""), isRunning(false) { if (instance) throw std::runtime_error("Console handler should not be constructed twice"); @@ -95,13 +97,35 @@ void ConsoleManager::loop() } } +#include + void ConsoleManager::start() { - std::thread([this]() - { while(true) { - this->loop(); - } }) - .detach(); + std::thread t = std::thread([this]() + { + this->isRunning = true; + while (isRunning) + { + this->loop(); + } }); + threadHandle = t.native_handle(); + t.detach(); + + CommandsManager::inst().addCommand( + "stop", [](const ISender::SenderType, ISender &, const std::vector &) + { Server::inst()->stop(); }, + "", "Stops the server"); +} + +void ConsoleManager::stop() +{ + isRunning = false; + +#if defined(__linux__) + pthread_cancel(threadHandle); +#elif defined(_WIN32) + TerminateThread(threadHandle, 1); +#endif } void ConsoleManager::onPostPrint(logger::PostPrintEvent event) diff --git a/src/cmd/console.h b/src/cmd/console.h index 99ec0e95..2a3087ca 100644 --- a/src/cmd/console.h +++ b/src/cmd/console.h @@ -13,6 +13,7 @@ #define MINESERVER_CONSOLE_H #include +#include #include /** @@ -26,6 +27,8 @@ class ConsoleManager std::string currentInput; EventHandler::subId subscribeId; + std::thread::native_handle_type threadHandle; + std::atomic isRunning; void loop(); @@ -46,6 +49,11 @@ class ConsoleManager * */ void start(); + /** + * @brief Stops listening for commands + * + */ + void stop(); /** * @brief Post print hook * diff --git a/src/server.cpp b/src/server.cpp index a8ee0e78..25dcc688 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -14,6 +14,7 @@ #include #include #include +#include Server *Server::INSTANCE; Server::Server() : sock(), @@ -21,7 +22,8 @@ Server::Server() : sock(), pluginsManager(), eventsManager(), commandsManager(), - consoleManager() + consoleManager(), + isRunning(false) { if (INSTANCE) return; @@ -87,11 +89,13 @@ void Server::start() logger::info("Server started on %s:%d !", addr.c_str(), port); while (isRunning) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // So that we don't overload the CPU ClientSocket cs = sock.accept(); if (!cs.isValid()) continue; + // Join thread afterwards std::thread([&cs, this]() { Client client(cs); @@ -113,4 +117,7 @@ void Server::stop() } sock.close(); + + consoleManager.stop(); + logger::debug("Stopped server !"); } diff --git a/src/server.h b/src/server.h index 9770f265..815a9eff 100644 --- a/src/server.h +++ b/src/server.h @@ -19,6 +19,7 @@ #include #include #include +#include #include /** @@ -38,7 +39,7 @@ class Server CommandsManager commandsManager; ConsoleManager consoleManager; ServerSocket sock; - bool isRunning{}; + std::atomic isRunning; /** * @brief Internal Checks diff --git a/src/utils/network.cpp b/src/utils/network.cpp index de9e82c4..6db97d04 100644 --- a/src/utils/network.cpp +++ b/src/utils/network.cpp @@ -20,6 +20,7 @@ #include #endif // _WIN32 #if defined(__linux__) +#include #include #include #include @@ -56,6 +57,12 @@ bool ServerSocket::bind(const char *address, int port) serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); } serv_addr.sin_port = htons(port); +#if defined(__linux__) + fcntl(sock, F_SETFL, O_NONBLOCK); +#elif defined(_WIN32) + u_long mode = 1; // 1 to enable non-blocking socket + ioctlsocket(sock, FIONBIO, &mode); +#endif int status_code = ::bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); return status_code >= 0; }