From 94c0d149dd9e05224b6f9fef3161e39c8c40bfc5 Mon Sep 17 00:00:00 2001 From: Transporter Date: Thu, 1 Aug 2024 08:54:45 +0200 Subject: [PATCH] Automatic deletion of residual files after crashes --- src/cpp/CMakeLists.txt | 4 ++ src/cpp/utils/Win32Dll.cpp | 92 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 src/cpp/utils/Win32Dll.cpp diff --git a/src/cpp/CMakeLists.txt b/src/cpp/CMakeLists.txt index 89cb6cfbb29..617e2765c9d 100644 --- a/src/cpp/CMakeLists.txt +++ b/src/cpp/CMakeLists.txt @@ -382,6 +382,10 @@ if(ANDROID) endif() endif() +if(WIN32 AND BUILD_SHARED_LIBS) + list(APPEND ${PROJECT_NAME}_source_files utils/Win32Dll.cpp) +endif() + # Option to enable strict real-time. In this case, several API functions have a real-time behaviour. # * Publisher::write() - Uses ReliabilityQosPolicy.max_blocking_time # * Subscriber::takeNextData() - Uses ReliabilityQosPolicy.max_blocking_time diff --git a/src/cpp/utils/Win32Dll.cpp b/src/cpp/utils/Win32Dll.cpp new file mode 100644 index 00000000000..1626d0d4515 --- /dev/null +++ b/src/cpp/utils/Win32Dll.cpp @@ -0,0 +1,92 @@ +/** + * @file Win32Dll.cpp + * @brief Deletes all residual files left over after crashes when loading and unloading the DLL. + */ +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include +#ifdef _MSC_VER +#define strncasecmp(x,y,z) _strnicmp(x,y,z) +#else +#include +#endif + +static bool win32_test_file_open(const std::string& fileName_in) +{ + HANDLE hFile = CreateFileA(fileName_in.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) + return true; // File is open + else + { + // File not open + CloseHandle(hFile); + return false; + } +} + +static bool win32_test_dir_exists(const std::string& dirName_in) +{ + DWORD ftyp = GetFileAttributesA(dirName_in.c_str()); + if (ftyp == INVALID_FILE_ATTRIBUTES) + return false; // Something is wrong with the path! + if (ftyp & FILE_ATTRIBUTE_DIRECTORY) + return true; // This is a directory! + return false; // This is not a directory! +} + +static bool win32_test_file_exists(const std::string& fileName_in) +{ + DWORD attributes = GetFileAttributesA(fileName_in.c_str()); + return (attributes != INVALID_FILE_ATTRIBUTES && !(attributes & FILE_ATTRIBUTE_DIRECTORY)); +} + +static bool str_endsWith(std::string& text, std::string test) +{ + if (test.empty() || text.empty()) return false; + if (test.length() > text.length()) return false; + size_t offset = text.length() - test.length(); + return strncasecmp(text.c_str() + offset, test.c_str(), test.length()) == 0; +} + +static void cleanup_eprosima() +{ + std::string interprocessdata("C:\\ProgramData\\eprosima\\fastrtps_interprocess"); + if (!win32_test_dir_exists(interprocessdata)) return; + std::string search = interprocessdata + "\\*"; + WIN32_FIND_DATAA data; + HANDLE hFind = FindFirstFileA(search.c_str(), &data); + if (hFind == INVALID_HANDLE_VALUE) return; + do + { + if (!(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + std::string filename(data.cFileName); + if (str_endsWith(filename, "_el") || str_endsWith(filename, "_mutex")) continue; + std::string file = interprocessdata + "\\" + filename; + if (win32_test_file_open(file)) continue; + std::string path = file + "_el"; + if (win32_test_file_exists(path)) DeleteFileA(path.c_str()); + path = file + "_mutex"; + if (win32_test_file_exists(path)) DeleteFileA(path.c_str()); + DeleteFileA(file.c_str()); + } + } while (FindNextFileA(hFind, &data)); + FindClose(hFind); +} + +BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) +{ + switch (ul_reason_for_call) + { + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + break; + case DLL_PROCESS_ATTACH: + case DLL_PROCESS_DETACH: + cleanup_eprosima(); + break; + } + return TRUE; +} +#endif