-
Notifications
You must be signed in to change notification settings - Fork 7
ListDetector - module automatically reloads #62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| /** | ||
| * @file | ||
| * @author Alex Petras <alex.petras@cesnet.cz> | ||
| * @brief Implementation of the ConfigReloader base class for checking for updates in the | ||
| * configuration and handling the reloading process | ||
| * | ||
| * SPDX-License-Identifier: BSD-3-Clause | ||
| */ | ||
|
|
||
| #include "configReloader.hpp" | ||
|
|
||
| #include <sys/stat.h> | ||
| #include <unistd.h> | ||
|
|
||
| namespace ListDetector { | ||
|
|
||
| ConfigReloader::ConfigReloader(char** m_argv) | ||
| : argv(m_argv) | ||
| { | ||
| } | ||
|
|
||
| std::time_t ConfigReloader::getLastModified(const std::string& filePath) | ||
| { | ||
| struct stat file_stat; | ||
| if (stat(filePath.c_str(), &file_stat) == 0) { | ||
| return file_stat.st_mtime; | ||
| } | ||
| return -1; | ||
| } | ||
|
|
||
| void ConfigReloader::checkReloadConfig(std::string filePath) | ||
| { | ||
| auto previousTimestamp = getLastModified(filePath); | ||
| while (true) { | ||
| sleep(CHECK_INTERVAL); | ||
| auto currentTimestamp = getLastModified(filePath); | ||
| if (currentTimestamp != previousTimestamp && currentTimestamp != -1) { | ||
| previousTimestamp = currentTimestamp; | ||
|
|
||
| this->restart(); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void ConfigReloader::restart() | ||
| { | ||
| execv(argv[0], argv); | ||
| } | ||
|
Comment on lines
+45
to
+48
|
||
|
|
||
| void ConfigReloader::startThread(std::string filePath) | ||
| { | ||
| checkConfigThread = std::thread(&ConfigReloader::checkReloadConfig, this, filePath); | ||
| checkConfigThread.detach(); | ||
| } | ||
|
|
||
| } // namespace ListDetector | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| /** | ||
| * @file | ||
| * @author Alex Petras <alex.petras@cesnet.cz> | ||
| * @brief Declaration of the ConfigReloader base class for checking for updates in the configuration | ||
| * and handling the reloading process | ||
| * | ||
| * SPDX-License-Identifier: BSD-3-Clause | ||
| */ | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <ctime> | ||
| #include <string> | ||
| #include <thread> | ||
| #include <unistd.h> | ||
|
|
||
| namespace ListDetector { | ||
|
|
||
| /** | ||
| * @brief Base class for dealing with reloading the config. | ||
| * | ||
| * The `ConfigReloader` class provides functionality for checking for updates in the configuration | ||
| * and handling the reloading process. | ||
| */ | ||
| class ConfigReloader { | ||
| public: | ||
| ConfigReloader(char** m_argv); | ||
|
|
||
| /** | ||
| * Start a thread that checks for updates in the configuration file. | ||
| * | ||
| * @param filePath Path to the configuration file to monitor. | ||
| */ | ||
| void startThread(std::string filePath); | ||
|
|
||
| /** | ||
| * Get the last modified timestamp of a file. | ||
| * | ||
| * @param filePath Path to the configuration file. | ||
| * | ||
| * @return The last modified timestamp of the file, or -1 if an error occurred. | ||
| */ | ||
| static std::time_t getLastModified(const std::string& filePath); | ||
|
|
||
| /** | ||
| * Check for changes in the configuration file and reload if the configuration file has changed. | ||
| * | ||
| * @param filePath Path to the configuration file to monitor. | ||
| */ | ||
| void checkReloadConfig(std::string filePath); | ||
|
|
||
| /** | ||
| * Restart the current process with the same arguments effectively reloading the configuration. | ||
| */ | ||
| void restart(); | ||
|
|
||
| /** | ||
| * @brief Interval in seconds to check for file changes. | ||
| */ | ||
| static const unsigned int CHECK_INTERVAL = 5; | ||
|
|
||
| private: | ||
| char** argv; | ||
| std::thread checkConfigThread; | ||
| }; | ||
|
|
||
| } // namespace ListDetector |
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -12,6 +12,7 @@ | |||||||||||||
| * SPDX-License-Identifier: BSD-3-Clause | ||||||||||||||
| */ | ||||||||||||||
|
|
||||||||||||||
| #include "configReloader.hpp" | ||||||||||||||
| #include "csvConfigParser.hpp" | ||||||||||||||
| #include "listDetector.hpp" | ||||||||||||||
| #include "logger/logger.hpp" | ||||||||||||||
|
|
@@ -103,6 +104,15 @@ static void processUnirecRecords( | |||||||||||||
|
|
||||||||||||||
| int main(int argc, char** argv) | ||||||||||||||
| { | ||||||||||||||
| // make a copy of argv | ||||||||||||||
| char** argv_copy = new char*[argc + 1]; | ||||||||||||||
| for (int i = 0; i < argc; ++i) { | ||||||||||||||
| argv_copy[i] = new char[strlen(argv[i]) + 1]; | ||||||||||||||
| argv_copy[argc] = nullptr; | ||||||||||||||
| strcpy(argv_copy[i], argv[i]); | ||||||||||||||
| } | ||||||||||||||
|
Comment on lines
+111
to
+113
|
||||||||||||||
| argv_copy[argc] = nullptr; | |
| strcpy(argv_copy[i], argv[i]); | |
| } | |
| strcpy(argv_copy[i], argv[i]); | |
| } | |
| argv_copy[argc] = nullptr; |
Copilot
AI
Sep 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Memory allocated with 'new' is never freed, causing a memory leak. Consider using smart pointers or RAII containers like std::vectorstd::string instead of manual memory management.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The infinite loop will continue running even after restart() is called. Since restart() calls execv() which replaces the current process, the code after restart() should be unreachable, but if execv() fails, the loop will continue indefinitely without any error handling.