mirror of
https://github.com/eclipse-openvehicle-api/openvehicle-api.git
synced 2026-02-05 15:18:45 +00:00
28
sdv_executables/sdv_trace_mon/CMakeLists.txt
Normal file
28
sdv_executables/sdv_trace_mon/CMakeLists.txt
Normal file
@@ -0,0 +1,28 @@
|
||||
# Define project
|
||||
project (sdv_trace_mon VERSION 1.0 LANGUAGES CXX)
|
||||
|
||||
# Add include directories
|
||||
include_directories(../export)
|
||||
|
||||
# Define the executable
|
||||
add_executable(sdv_trace_mon
|
||||
main.cpp
|
||||
)
|
||||
|
||||
# Link target
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
target_link_libraries(sdv_trace_mon ${CMAKE_THREAD_LIBS_INIT} stdc++fs)
|
||||
if (WIN32)
|
||||
target_link_libraries(sdv_trace_mon Ws2_32 Winmm Rpcrt4.lib)
|
||||
else()
|
||||
target_link_libraries(sdv_trace_mon ${CMAKE_DL_LIBS} rt)
|
||||
endif()
|
||||
else()
|
||||
target_link_libraries(sdv_trace_mon Rpcrt4.lib)
|
||||
endif()
|
||||
|
||||
# Build dependencies
|
||||
add_dependencies(sdv_trace_mon core_services)
|
||||
|
||||
# Appending the executable to the service list
|
||||
set(SDV_Executable_List ${SDV_Executable_List} sdv_trace_mon PARENT_SCOPE)
|
||||
171
sdv_executables/sdv_trace_mon/main.cpp
Normal file
171
sdv_executables/sdv_trace_mon/main.cpp
Normal file
@@ -0,0 +1,171 @@
|
||||
#include <support/sdv_core.h>
|
||||
#include <support/app_control.h>
|
||||
#include "../../global/cmdlnparser/cmdlnparser.cpp"
|
||||
#include "../../global/tracefifo/trace_fifo.cpp"
|
||||
#include "../../global/exec_dir_helper.h"
|
||||
#include "../error_msg.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __unix__
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Add a slag to the string.
|
||||
* @param[in] rssString The string to add a flag to.
|
||||
* @param[in] rssFlag The flag text to add.
|
||||
*/
|
||||
void AddFlagString(std::string& rssString, const std::string& rssFlag)
|
||||
{
|
||||
if (!rssString.empty()) rssString += " | ";
|
||||
rssString += rssFlag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Application shutdown signalled
|
||||
*/
|
||||
bool bShutdownSignalled = false;
|
||||
|
||||
#ifdef _WIN32
|
||||
/**
|
||||
* @brief Console application control handler (CTRL+C, close, shutdown, etc.).
|
||||
* @param[in] dwCtrlType The control type triggered by the system.
|
||||
* @return Returns TRUE when the signal was handled.
|
||||
*/
|
||||
static BOOL WINAPI ControlHandler(DWORD dwCtrlType)
|
||||
{
|
||||
switch (dwCtrlType)
|
||||
{
|
||||
case CTRL_C_EVENT:
|
||||
case CTRL_BREAK_EVENT:
|
||||
case CTRL_CLOSE_EVENT:
|
||||
case CTRL_LOGOFF_EVENT:
|
||||
case CTRL_SHUTDOWN_EVENT:
|
||||
bShutdownSignalled = true;
|
||||
return TRUE;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
#elif defined __unix__
|
||||
/**
|
||||
* @brief Signal handler to catch signal eevents.
|
||||
* @param[in] iSigNum The signal type that was triggered.
|
||||
*/
|
||||
static void SignalHandler(int iSigNum)
|
||||
{
|
||||
if (iSigNum == SIGINT)
|
||||
bShutdownSignalled = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && defined(_UNICODE)
|
||||
extern "C" int wmain(int iArgc, const wchar_t* rgszArgv[])
|
||||
#else
|
||||
extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
#endif
|
||||
{
|
||||
// Workaround for GCC to make certain that POSIX thread library is loaded before the components are loaded.
|
||||
// REASON: If the first call to a thread is done in a dynamic library, the application is already classified as single
|
||||
// threaded and a termination is initiated.
|
||||
// See: https://stackoverflow.com/questions/51209268/using-stdthread-in-a-library-loaded-with-dlopen-leads-to-a-sigsev
|
||||
// NOTE EVE 27.05.2025: in release builds, starting and ending the thread right after each other causes incorrect behavior and
|
||||
// leads in some cases to create a deadlock in the join-function. The solution is to add delays in the thread processing.
|
||||
bool bThreadStarted = false;
|
||||
std::thread thread = std::thread([&]()
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
bThreadStarted = true;
|
||||
});
|
||||
while (!bThreadStarted) {std::this_thread::sleep_for(std::chrono::milliseconds(100));}
|
||||
if (thread.joinable())
|
||||
thread.join();
|
||||
|
||||
// If not set, set the runtime location to the EXE directory.
|
||||
if (sdv::app::CAppControl::GetFrameworkRuntimeDirectory().empty())
|
||||
sdv::app::CAppControl::SetFrameworkRuntimeDirectory(GetExecDirectory());
|
||||
if (sdv::app::CAppControl::GetComponentInstallDirectory().empty())
|
||||
sdv::app::CAppControl::SetComponentInstallDirectory(GetExecDirectory());
|
||||
|
||||
CCommandLine cmdln(static_cast<uint32_t>(CCommandLine::EParseFlags::no_assignment_character));
|
||||
bool bHelp = false;
|
||||
bool bVersion = false;
|
||||
uint32_t uiInstanceID = 1000u;
|
||||
std::string ssArgError;
|
||||
try
|
||||
{
|
||||
auto& rArgDef = cmdln.DefineOption("?", bHelp, "Show help. Use <COMMAND> --help for specific help on the command.");
|
||||
rArgDef.AddSubOptionName("help");
|
||||
cmdln.DefineSubOption("version", bVersion, "Show version information.");
|
||||
cmdln.DefineSubOption("instance", uiInstanceID, "The instance ID of the SDV instance (default ID is 1000).");
|
||||
|
||||
cmdln.Parse(static_cast<size_t>(iArgc), rgszArgv);
|
||||
} catch (const SArgumentParseException& rsExcept)
|
||||
{
|
||||
ssArgError = rsExcept.what();
|
||||
bHelp = true;
|
||||
}
|
||||
|
||||
std::cout << "SDV Server Log Monitor Utility" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2025 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Author: Erik Verhoeven" << std::endl << std::endl;
|
||||
|
||||
if (bVersion)
|
||||
std::cout << "Version: " << (SDVFrameworkBuildVersion / 100) << "." << (SDVFrameworkBuildVersion % 100) << " build " <<
|
||||
SDVFrameworkSubbuildVersion << " interface " << SDVFrameworkInterfaceVersion << std::endl;
|
||||
if (bHelp)
|
||||
{
|
||||
cmdln.PrintHelp(std::cout, "Monitor log messages from a sdv-server.\n");
|
||||
return NO_ERROR;
|
||||
}
|
||||
std::cout << "Monitoring instance #" << uiInstanceID << std::endl;
|
||||
|
||||
CTraceFifoReader reader(uiInstanceID);
|
||||
|
||||
#ifdef _WIN32
|
||||
// Register the console control handler
|
||||
if (!SetConsoleCtrlHandler(&ControlHandler, TRUE))
|
||||
{
|
||||
std::cerr << "ERROR: " << TRACE_MON_REG_HNDLR_ERROR_MSG << std::endl;
|
||||
return TRACE_MON_REG_HNDLR_ERROR;
|
||||
}
|
||||
#elif defined __unix__
|
||||
// Install our signal handler
|
||||
struct sigaction sSigAction{};
|
||||
sSigAction.sa_handler = SignalHandler;
|
||||
sSigAction.sa_flags = SA_RESTART;
|
||||
if (sigaction(SIGINT, &sSigAction, NULL) == -1)
|
||||
{
|
||||
std::cerr << "ERROR: " << TRACE_MON_REG_HNDLR_ERROR_MSG << std::endl;
|
||||
return TRACE_MON_REG_HNDLR_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Open the reader.
|
||||
if (!reader.Open())
|
||||
{
|
||||
std::cerr << "ERROR: " << TRACE_MON_FIFO_OPEN_ERROR_MSG << std::endl;
|
||||
return TRACE_MON_FIFO_OPEN_ERROR;
|
||||
}
|
||||
|
||||
// Trace messages
|
||||
while (!bShutdownSignalled)
|
||||
{
|
||||
std::string ssMsg = reader.WaitForMessage(250);
|
||||
if (!ssMsg.empty())
|
||||
std::cout << ssMsg;
|
||||
else
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
SetConsoleCtrlHandler(&ControlHandler, FALSE);
|
||||
#endif
|
||||
|
||||
reader.Close();
|
||||
std::cout << "Done..." << std::endl;
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
Reference in New Issue
Block a user