Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions modules/listDetector/src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
add_executable(listDetector
main.cpp
configParser.cpp
configReloader.cpp
csvConfigParser.cpp
ipAddressPrefix.cpp
rule.cpp
Expand Down
56 changes: 56 additions & 0 deletions modules/listDetector/src/configReloader.cpp
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();
}
}
Comment on lines +33 to +42
Copy link

Copilot AI Sep 26, 2025

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.

Copilot uses AI. Check for mistakes.
}

void ConfigReloader::restart()
{
execv(argv[0], argv);
}
Comment on lines +45 to +48
Copy link

Copilot AI Sep 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No error handling for execv() failure. If execv() fails, the function returns normally but the process hasn't been replaced, potentially leading to unexpected behavior. Consider adding error handling or at least logging when execv() fails.

Copilot uses AI. Check for mistakes.

void ConfigReloader::startThread(std::string filePath)
{
checkConfigThread = std::thread(&ConfigReloader::checkReloadConfig, this, filePath);
checkConfigThread.detach();
}

} // namespace ListDetector
67 changes: 67 additions & 0 deletions modules/listDetector/src/configReloader.hpp
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
11 changes: 11 additions & 0 deletions modules/listDetector/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/

#include "configReloader.hpp"
#include "csvConfigParser.hpp"
#include "listDetector.hpp"
#include "logger/logger.hpp"
Expand Down Expand Up @@ -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
Copy link

Copilot AI Sep 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line 111 sets argv_copy[argc] to nullptr inside the loop, but this should be done after the loop completes. This will overwrite the null terminator on every iteration except the last.

Suggested change
argv_copy[argc] = nullptr;
strcpy(argv_copy[i], argv[i]);
}
strcpy(argv_copy[i], argv[i]);
}
argv_copy[argc] = nullptr;

Copilot uses AI. Check for mistakes.
Comment on lines +108 to +113
Copy link

Copilot AI Sep 26, 2025

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.

Copilot uses AI. Check for mistakes.

ListDetector::ConfigReloader reloader(argv_copy);
argparse::ArgumentParser program("listdetector");

Nm::loggerInit();
Expand Down Expand Up @@ -189,6 +199,7 @@ int main(int argc, char** argv)
ListDetector::ListDetector listDetector(configParser.get(), mode);
auto listDetectorTelemetryDirectory = telemetryRootDirectory->addDir("listdetector");
listDetector.setTelemetryDirectory(listDetectorTelemetryDirectory);
reloader.startThread(program.get<std::string>("--rules"));

processUnirecRecords(biInterface, listDetector);

Expand Down