From 2b97e2f4ff9d7455ca3eb426a84b553d1718758a Mon Sep 17 00:00:00 2001 From: BenDroid Date: Tue, 17 Oct 2017 22:31:22 +0200 Subject: [PATCH] Fixed bugs in CCClient, added missing delete/desttructors for restart --- src/App.cpp | 69 +++++++++++++++++++-------------------- src/App.h | 8 +++-- src/Console.cpp | 6 +++- src/Console.h | 1 + src/Mem.h | 5 ++- src/Mem_unix.cpp | 14 ++++---- src/Mem_win.cpp | 14 ++++---- src/Summary.cpp | 4 +-- src/cc/CCClient.cpp | 45 +++++++++++++------------ src/cc/ClientStatus.cpp | 8 ++--- src/cc/ClientStatus.h | 38 ++++++++++++++++++--- src/cc/ControlCommand.cpp | 17 +++++++--- src/cc/ControlCommand.h | 34 ++++++++++++++++--- src/cc/Service.cpp | 21 ++++++------ src/log/Log.h | 2 +- src/net/Network.cpp | 8 ++++- src/xmrig.cpp | 10 ++++-- 17 files changed, 194 insertions(+), 110 deletions(-) diff --git a/src/App.cpp b/src/App.cpp index 8e2ef644..284135cf 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -36,10 +36,8 @@ #include "log/Log.h" #include "Mem.h" #include "net/Network.h" -#include "Options.h" #include "Platform.h" #include "Summary.h" -#include "version.h" #include "workers/Workers.h" #include "cc/CCClient.h" @@ -57,6 +55,7 @@ App *App::m_self = nullptr; App::App(int argc, char **argv) : + m_restart(false), m_console(nullptr), m_httpd(nullptr), m_network(nullptr), @@ -99,7 +98,12 @@ App::App(int argc, char **argv) : App::~App() { - uv_tty_reset_mode(); + Log::release(); + Options::release(); + Mem::release(); + Platform::release(); + + delete m_network; # ifndef XMRIG_NO_HTTPD delete m_httpd; @@ -110,10 +114,19 @@ App::~App() # endif delete m_console; + +# ifndef XMRIG_NO_API + Api::release(); +# endif + + uv_signal_stop(&m_signal); + uv_tty_reset_mode(); + + m_self = nullptr; } -int App::exec() +int App::start() { if (!m_options) { return 0; @@ -130,7 +143,7 @@ int App::exec() return 1; } - Mem::allocate(m_options->algo(), m_options->threads(), m_options->doubleHash(), m_options->hugePages()); + Mem::allocate(m_options); Summary::print(); # ifndef XMRIG_NO_API @@ -153,13 +166,7 @@ int App::exec() const int r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); uv_loop_close(uv_default_loop()); - delete m_network; - - Options::release(); - Mem::release(); - Platform::release(); - - return r; + return m_restart ? ERESTART : r; } @@ -171,6 +178,11 @@ void App::onConsoleCommand(char command) Workers::printHashrate(true); break; + case 'i': + case 'I': + restart(); + break; + case 'p': case 'P': LOG_INFO(m_options->colors() ? "\x1B[01;33mpaused\x1B[0m, press \x1B[01;35mr\x1B[0m to resume" : "paused, press 'r' to resume"); @@ -185,9 +197,10 @@ void App::onConsoleCommand(char command) } break; + case 'q': + case 'Q': case 3: - LOG_WARN("Ctrl+C received, exiting"); - close(); + stop(false); break; default: @@ -196,33 +209,19 @@ void App::onConsoleCommand(char command) } -void App::close() +void App::stop(bool restart) { + m_restart = restart; + m_network->stop(); Workers::stop(); uv_stop(uv_default_loop()); } -void App::reloadConfig() +void App::restart() { - // reload config WIP - /* - m_self->m_options->parseConfig(m_self->m_options->configFile()); - - Platform::release(); - Platform::init(m_self->m_options->userAgent()); - Platform::setProcessPriority(m_self->m_options->priority()); - - m_self->m_network->stop(); - Workers::stop(); // free resources here - - Mem::release(); - Mem::allocate(m_self->m_options->algo(), m_self->m_options->threads(), m_self->m_options->doubleHash(), m_self->m_options->hugePages()); - Summary::print(); - - Workers::start(m_self->m_options->affinity(), m_self->m_options->priority()); - */ + m_self->stop(true); } void App::onSignal(uv_signal_t *handle, int signum) @@ -245,7 +244,5 @@ void App::onSignal(uv_signal_t *handle, int signum) break; } - uv_signal_stop(handle); - m_self->close(); + m_self->stop(false); } - diff --git a/src/App.h b/src/App.h index c08f5fcf..b17b7afe 100644 --- a/src/App.h +++ b/src/App.h @@ -43,21 +43,23 @@ public: App(int argc, char **argv); ~App(); - int exec(); + int start(); - static void reloadConfig(); + static void restart(); protected: void onConsoleCommand(char command) override; private: void background(); - void close(); + void stop(bool restart); static void onSignal(uv_signal_t *handle, int signum); static App *m_self; + bool m_restart; + Console *m_console; Httpd *m_httpd; Network *m_network; diff --git a/src/Console.cpp b/src/Console.cpp index 3d95ada4..09094330 100644 --- a/src/Console.cpp +++ b/src/Console.cpp @@ -40,6 +40,11 @@ Console::Console(IConsoleListener *listener) uv_read_start(reinterpret_cast(&m_tty), Console::onAllocBuffer, Console::onRead); } +Console::~Console() +{ + uv_read_stop(reinterpret_cast(&m_tty)); + uv_tty_reset_mode(); +} void Console::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) { @@ -48,7 +53,6 @@ void Console::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t buf->base = console->m_buf; } - void Console::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) { if (nread < 0) { diff --git a/src/Console.h b/src/Console.h index bde95d7d..fd34b3e9 100644 --- a/src/Console.h +++ b/src/Console.h @@ -35,6 +35,7 @@ class Console { public: Console(IConsoleListener *listener); + ~Console(); private: static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf); diff --git a/src/Mem.h b/src/Mem.h index 58dba848..dcd3a970 100644 --- a/src/Mem.h +++ b/src/Mem.h @@ -28,9 +28,8 @@ #include #include - #include "align.h" - +#include "Options.h" struct cryptonight_ctx; @@ -44,7 +43,7 @@ public: Lock = 4 }; - static bool allocate(int algo, int threads, bool doubleHash, bool enabled); + static bool allocate(const Options* options); static cryptonight_ctx *create(int threadId); static void *calloc(size_t num, size_t size); static void release(); diff --git a/src/Mem_unix.cpp b/src/Mem_unix.cpp index 7c41fd16..061d50c1 100644 --- a/src/Mem_unix.cpp +++ b/src/Mem_unix.cpp @@ -33,16 +33,16 @@ #include "Options.h" -bool Mem::allocate(int algo, int threads, bool doubleHash, bool enabled) +bool Mem::allocate(const Options* options) { - m_algo = algo; - m_threads = threads; - m_doubleHash = doubleHash; + m_algo = options->algo(); + m_threads = options->threads(); + m_doubleHash = options->doubleHash(); - const int ratio = (doubleHash && algo != Options::ALGO_CRYPTONIGHT_LITE) ? 2 : 1; - const size_t size = MEMORY * (threads * ratio + 1); + const int ratio = (m_doubleHash && m_algo != Options::ALGO_CRYPTONIGHT_LITE) ? 2 : 1; + const size_t size = MEMORY * (m_threads * ratio + 1); - if (!enabled) { + if (!options->hugePages()) { m_memory = static_cast(_mm_malloc(size, 16)); return true; } diff --git a/src/Mem_win.cpp b/src/Mem_win.cpp index a4f92cfe..9348c0dd 100644 --- a/src/Mem_win.cpp +++ b/src/Mem_win.cpp @@ -144,16 +144,16 @@ static BOOL TrySetLockPagesPrivilege() { } -bool Mem::allocate(int algo, int threads, bool doubleHash, bool enabled) +bool Mem::allocate(const Options* options) { - m_algo = algo; - m_threads = threads; - m_doubleHash = doubleHash; + m_algo = options->algo(); + m_threads = options->threads(); + m_doubleHash = options->doubleHash(); - const int ratio = (doubleHash && algo != Options::ALGO_CRYPTONIGHT_LITE) ? 2 : 1; - const size_t size = MEMORY * (threads * ratio + 1); + const int ratio = (m_doubleHash && m_algo != Options::ALGO_CRYPTONIGHT_LITE) ? 2 : 1; + const size_t size = MEMORY * (m_threads * ratio + 1); - if (!enabled) { + if (!options->hugePages()) { m_memory = static_cast(_mm_malloc(size, 16)); return true; } diff --git a/src/Summary.cpp b/src/Summary.cpp index 39ce5abf..d3affd03 100644 --- a/src/Summary.cpp +++ b/src/Summary.cpp @@ -152,10 +152,10 @@ static void print_cc() static void print_commands() { if (Options::i()->colors()) { - Log::i()->text("\x1B[01;32m * \x1B[01;37mCOMMANDS: \x1B[01;35mh\x1B[01;37mashrate, \x1B[01;35mp\x1B[01;37mause, \x1B[01;35mr\x1B[01;37mesume"); + Log::i()->text("\x1B[01;32m * \x1B[01;37mCOMMANDS: \x1B[01;35mh\x1B[01;37mashrate, \x1B[01;35mi\x1B[01;37mnvalidate, \x1B[01;35mp\x1B[01;37mause, \x1B[01;35mr\x1B[01;37mesume, \x1B[01;35mq\x1B[01;37muit"); } else { - Log::i()->text(" * COMMANDS: 'h' hashrate, 'p' pause, 'r' resume"); + Log::i()->text(" * COMMANDS: 'h' hashrate, 'i' invalidate, 'p' pause, 'r' resume, 'q' quit"); } } diff --git a/src/cc/CCClient.cpp b/src/cc/CCClient.cpp index 0407a66f..5938bca0 100644 --- a/src/cc/CCClient.cpp +++ b/src/cc/CCClient.cpp @@ -88,7 +88,7 @@ void CCClient::updateNetworkState(const NetworkState &network) { uv_mutex_lock(&m_mutex); - m_self->m_clientStatus.setCurrentStatus(Workers::isEnabled() ? "mining" : "paused"); + m_self->m_clientStatus.setCurrentStatus(Workers::isEnabled() ? ClientStatus::RUNNING : ClientStatus::PAUSED); m_self->m_clientStatus.setCurrentPool(network.pool); m_self->m_clientStatus.setSharesGood(network.accepted); m_self->m_clientStatus.setSharesTotal(network.accepted + network.rejected); @@ -100,50 +100,55 @@ void CCClient::updateNetworkState(const NetworkState &network) void CCClient::publishClientStatusReport() { - std::string requestUrl = m_self->m_serverURL + "/client/setClientStatus?clientId=" + m_self->m_clientStatus.getClientId(); + std::string requestUrl = m_self->m_serverURL + + "/client/setClientStatus?clientId=" + + m_self->m_clientStatus.getClientId(); + std::string requestBuffer = m_self->m_clientStatus.toJsonString(); std::string responseBuffer; CURLcode res = performCurl(requestUrl, requestBuffer, "POST", responseBuffer); if (res != CURLE_OK) { - LOG_ERR("CCClient error: %s", curl_easy_strerror(res)); + LOG_ERR("[CC-Client] error: \"%s\" -> %s", + curl_easy_strerror(res), requestUrl.c_str()); } else { ControlCommand controlCommand; if (controlCommand.parseFromJsonString(responseBuffer)) { if (controlCommand.getCommand() == ControlCommand::START) { if (!Workers::isEnabled()) { - LOG_INFO("Command: START received -> Resuming"); + LOG_INFO("[CC-Client] Command: START received -> resume"); Workers::setEnabled(true); } } else if (controlCommand.getCommand() == ControlCommand::STOP) { - if (!Workers::isEnabled()) { - LOG_INFO("Command: STOP received -> Pausing"); - Workers::setEnabled(true); + if (Workers::isEnabled()) { + LOG_INFO("[CC-Client] Command: STOP received -> pause"); + Workers::setEnabled(false); } } else if (controlCommand.getCommand() == ControlCommand::UPDATE_CONFIG) { - LOG_INFO("Command: UPDATE_CONFIG received -> Updating config"); updateConfig(); - } else if (controlCommand.getCommand() == ControlCommand::RELOAD) { - LOG_INFO("Command: RELOAD received -> Reload"); - App::reloadConfig(); - } else { - LOG_ERR("Command: GET_CONFIG received -> NOT IMPLEMENTED YET!"); + } else if (controlCommand.getCommand() == ControlCommand::RESTART) { + App::restart(); + } else if (controlCommand.getCommand() == ControlCommand::QUIT) { + // TODO } } else { - LOG_ERR("Unknown Command received from CC Server."); + LOG_ERR("[CC-Client] unknown command received from CC Server."); } } } void CCClient::updateConfig() { - std::string requestUrl = m_self->m_serverURL + "/client/getConfig?clientId=" + m_self->m_clientStatus.getClientId(); + std::string requestUrl = m_self->m_serverURL + + "/client/getConfig?clientId=" + + m_self->m_clientStatus.getClientId(); + std::string requestBuffer; std::string responseBuffer; CURLcode res = performCurl(requestUrl, requestBuffer, "GET", responseBuffer); if (res != CURLE_OK) { - LOG_ERR("CCClient error: %s", curl_easy_strerror(res)); + LOG_ERR("[CC-Client] error: \"%s\" -> %s", curl_easy_strerror(res), requestUrl.c_str()); } else { rapidjson::Document document; if (!document.Parse(responseBuffer.c_str()).HasParseError()) { @@ -157,13 +162,13 @@ void CCClient::updateConfig() clientConfigFile << buffer.GetString(); clientConfigFile.close(); - LOG_INFO("Config update done. Reload."); - App::reloadConfig(); + LOG_INFO("[CC-Client] config updated. restart."); + App::restart(); } else { - LOG_ERR("Not able to store client config to file %s.", m_self->m_options->configFile()); + LOG_ERR("[CC-Client] not able to store client config to file %s.", m_self->m_options->configFile()); } } else{ - LOG_ERR("Not able to store client config. The received client config is broken!"); + LOG_ERR("[CC-Client] not able to store client config. received client config is broken!"); } } } diff --git a/src/cc/ClientStatus.cpp b/src/cc/ClientStatus.cpp index bb3b9f8a..06a8673a 100644 --- a/src/cc/ClientStatus.cpp +++ b/src/cc/ClientStatus.cpp @@ -63,12 +63,12 @@ void ClientStatus::setCurrentPool(const std::string& currentPool) m_currentPool = currentPool; } -const std::string ClientStatus::getCurrentStatus() const +ClientStatus::Status ClientStatus::getCurrentStatus() const { return m_currentStatus; } -void ClientStatus::setCurrentStatus(const std::string& currentStatus) +void ClientStatus::setCurrentStatus(Status currentStatus) { m_currentStatus = currentStatus; } @@ -175,7 +175,7 @@ bool ClientStatus::parseFromJson(const rapidjson::Document& document) } if (clientStatus.HasMember("current_status")) { - m_currentStatus = clientStatus["current_status"].GetString(); + m_currentStatus = toStatus(clientStatus["current_status"].GetString()); } if (clientStatus.HasMember("hashrate_short")) { @@ -227,7 +227,7 @@ rapidjson::Value ClientStatus::toJson(rapidjson::MemoryPoolAllocator(status)]; + } + + inline Status toStatus (const char *status) + { + const int n = sizeof(status_str) / sizeof(status_str[0]); + for (int i = 0; i < n; ++i) + { + if (strcmp(status_str[i], status) == 0) + return (Status) i; + } + return Status::RUNNING; + } + const std::string getClientId() const; void setClientId(const std::string& clientId); const std::string getCurrentPool() const; void setCurrentPool(const std::string& currentPool); - const std::string getCurrentStatus() const; - void setCurrentStatus(const std::string& currentStatus); + Status getCurrentStatus() const; + void setCurrentStatus(Status currentStatus); double getHashrateShort() const; void setHashrateShort(double hashrateShort); @@ -76,9 +99,16 @@ public: private: + const char* status_str[3] = { + "RUNNING", + "PAUSED", + "CONFIG_UPDATED" + }; + + Status m_currentStatus; + std::string m_clientId; std::string m_currentPool; - std::string m_currentStatus; double m_hashrateShort; double m_hashrateMedium; diff --git a/src/cc/ControlCommand.cpp b/src/cc/ControlCommand.cpp index 38e790f9..b76c4b97 100644 --- a/src/cc/ControlCommand.cpp +++ b/src/cc/ControlCommand.cpp @@ -34,7 +34,7 @@ ControlCommand::ControlCommand() } -ControlCommand::ControlCommand(ControlCommand::Command command) +ControlCommand::ControlCommand(Command command) : m_command(command) { @@ -59,7 +59,7 @@ bool ControlCommand::parseFromJson(const rapidjson::Document& document) if (document.HasMember("control_command")) { rapidjson::Value::ConstObject controlCommand = document["control_command"].GetObject(); if (controlCommand.HasMember("command")) { - m_command = static_cast(controlCommand["command"].GetUint()); + m_command = toCommand(controlCommand["command"].GetString()); result = true; } else { @@ -76,12 +76,12 @@ rapidjson::Value ControlCommand::toJson(rapidjson::MemoryPoolAllocator(command)]; + } + + inline Command toCommand (const char *command) + { + const int n = sizeof(command_str) / sizeof(command_str[0]); + for (int i = 0; i < n; ++i) + { + if (strcmp(command_str[i], command) == 0) + return (Command) i; + } + return Command::START; + } + rapidjson::Value toJson(rapidjson::MemoryPoolAllocator& allocator); bool parseFromJsonString(const std::string& json); bool parseFromJson(const rapidjson::Document& document); @@ -51,7 +67,17 @@ public: Command getCommand() const; void setCommand(Command command); + bool isOneTimeCommand() const; + private: + const char* command_str[5] = { + "START", + "STOP", + "UPDATE_CONFIG", + "RESTART", + "QUIT" + }; + Command m_command; }; diff --git a/src/cc/Service.cpp b/src/cc/Service.cpp index 8db4cf11..2b3bd923 100644 --- a/src/cc/Service.cpp +++ b/src/cc/Service.cpp @@ -60,7 +60,7 @@ unsigned Service::handleGET(const Options* options, const std::string& url, cons { uv_mutex_lock(&m_mutex); - unsigned resultCode = MHD_HTTP_BAD_REQUEST; + unsigned resultCode = MHD_HTTP_NOT_FOUND; LOG_INFO("GET(url='%s', clientId='%s')", url.c_str(), clientId.c_str()); @@ -72,12 +72,6 @@ unsigned Service::handleGET(const Options* options, const std::string& url, cons if (!clientId.empty()) { if (url.rfind("/client/getConfig", 0) == 0 || url.rfind("/admin/getClientConfig", 0) == 0) { resultCode = getClientConfig(options, clientId, resp); - if (url.rfind("/client/getConfig", 0) == 0) { - std::map::iterator iter = m_clientCommand.find(clientId); - if (iter != m_clientCommand.end()) { - m_clientCommand.erase(iter); - } - } } else if (url.rfind("/admin/getClientCommand", 0) == 0) { resultCode = getClientCommand(clientId, resp); } @@ -96,7 +90,7 @@ unsigned Service::handlePOST(const Options* options, const std::string& url, con { uv_mutex_lock(&m_mutex); - unsigned resultCode = MHD_HTTP_BAD_REQUEST; + unsigned resultCode = MHD_HTTP_NOT_FOUND; LOG_INFO("POST(url='%s', clientId='%s', data='%s')", url.c_str(), clientId.c_str(), data.c_str()); @@ -212,6 +206,8 @@ unsigned Service::getClientStatusList(std::string& resp) unsigned Service::setClientStatus(const std::string& clientId, const std::string& data, std::string& resp) { + int resultCode = MHD_HTTP_BAD_REQUEST; + rapidjson::Document document; if (!document.Parse(data.c_str()).HasParseError()) { LOG_INFO("Status from client: %s", clientId.c_str()); @@ -220,12 +216,17 @@ unsigned Service::setClientStatus(const std::string& clientId, const std::string clientStatus.parseFromJson(document); m_clientStatus[clientId] = clientStatus; + + resultCode = getClientCommand(clientId, resp); + + if (m_clientCommand[clientId].isOneTimeCommand()) { + m_clientCommand.erase(clientId); + } } else { LOG_ERR("Parse Error Occured: %d", document.GetParseError()); - return MHD_HTTP_BAD_REQUEST; } - return getClientCommand(clientId, resp); + return resultCode; } unsigned Service::getClientCommand(const std::string& clientId, std::string& resp) diff --git a/src/log/Log.h b/src/log/Log.h index fd944d80..6b1568ef 100644 --- a/src/log/Log.h +++ b/src/log/Log.h @@ -57,7 +57,7 @@ public: static inline Log* i() { return m_self; } static inline void add(ILogBackend *backend) { i()->m_backends.push_back(backend); } static inline void init() { if (!m_self) { m_self = new Log();} } - static inline void release() { delete m_self; } + static inline void release() { delete m_self; m_self = nullptr; } void message(Level level, const char* fmt, ...); void text(const char* fmt, ...); diff --git a/src/net/Network.cpp b/src/net/Network.cpp index 60fc91a2..dcee50b2 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -55,7 +55,6 @@ Network::Network(const Options *options) : Workers::setListener(this); const std::vector &pools = options->pools(); - if (pools.size() > 1) { m_strategy = new FailoverStrategy(pools, Platform::userAgent(), this); } @@ -76,6 +75,13 @@ Network::Network(const Options *options) : Network::~Network() { + uv_timer_stop(&m_timer); + + if (m_donate) { + delete m_donate; + } + + delete m_strategy; } diff --git a/src/xmrig.cpp b/src/xmrig.cpp index 48362ada..619f21a7 100644 --- a/src/xmrig.cpp +++ b/src/xmrig.cpp @@ -25,7 +25,13 @@ int main(int argc, char **argv) { - App app(argc, argv); + for (;;) { + App* app = new App(argc, argv); + int res = app->start(); + delete app; - return app.exec(); + if (res != ERESTART) { + break; + } + } }