From c10ede3ada3d1b34ad4b3032a374aa34525ac35c Mon Sep 17 00:00:00 2001 From: LoRd_MuldeR Date: Fri, 21 Nov 2014 19:42:39 +0100 Subject: [PATCH] Implemented fatal_exit() and exception handler macros. --- MUtilities_VS2013.vcxproj | 2 + MUtilities_VS2013.vcxproj.filters | 15 ++++- include/MUtils/Exception.h | 57 ++++++++++++++++++ include/MUtils/OSSupport.h | 3 + src/CriticalSection_Win32.h | 98 +++++++++++++++++++++++++++++++ src/Global.cpp | 4 +- src/OSSupport_Win32.cpp | 47 +++++++++++++++ src/UpdateChecker.cpp | 23 ++------ 8 files changed, 226 insertions(+), 23 deletions(-) create mode 100644 include/MUtils/Exception.h create mode 100644 src/CriticalSection_Win32.h diff --git a/MUtilities_VS2013.vcxproj b/MUtilities_VS2013.vcxproj index f8c4cf3..9ea9e71 100644 --- a/MUtilities_VS2013.vcxproj +++ b/MUtilities_VS2013.vcxproj @@ -20,9 +20,11 @@ + + {55405FE1-149F-434C-9D72-4B64348D2A08} diff --git a/MUtilities_VS2013.vcxproj.filters b/MUtilities_VS2013.vcxproj.filters index b077129..3cb1279 100644 --- a/MUtilities_VS2013.vcxproj.filters +++ b/MUtilities_VS2013.vcxproj.filters @@ -13,6 +13,9 @@ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + {d47fbdba-5e24-460a-bba8-824ea0fe874c} + @@ -26,14 +29,20 @@ - + Header Files + + Public Headers + - Header Files + Public Headers - Header Files + Public Headers + + + Public Headers \ No newline at end of file diff --git a/include/MUtils/Exception.h b/include/MUtils/Exception.h new file mode 100644 index 0000000..ede846c --- /dev/null +++ b/include/MUtils/Exception.h @@ -0,0 +1,57 @@ +/////////////////////////////////////////////////////////////////////////////// +// MuldeR's Utilities for Qt +// Copyright (C) 2004-2014 LoRd_MuldeR +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// http://www.gnu.org/licenses/lgpl-2.1.txt +////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include + +#define MUTILS_PRINT_ERROR(FORMAT, ...) do \ +{ \ + fflush(stdout); \ + fprintf(stderr, (FORMAT), __VA_ARGS__); \ + fflush(stderr); \ +} \ +while(0) + +#define MUTILS_EXCEPTION_HANDLER(COMMAND) do \ +{ \ + try \ + { \ + do { COMMAND; } while(0); \ + } \ + catch(const std::exception &error) \ + { \ + MUTILS_PRINT_ERROR("\nGURU MEDITATION !!!\n\nException error:\n%s\n", error.what()); \ + MUtils::OS::fatal_exit("Unhandeled C++ exception error, application will exit!"); \ + } \ + catch(...) \ + { \ + MUTILS_PRINT_ERROR("\nGURU MEDITATION !!!\n\nUnknown exception error!\n"); \ + MUtils::OS::fatal_exit("Unhandeled C++ exception error, application will exit!"); \ + } \ +} \ +while(0) + +#define MUTILS_THROW(MESSAGE) do \ +{ \ + throw std::runtime_error((MESSAGE)); \ +} \ +while(0) diff --git a/include/MUtils/OSSupport.h b/include/MUtils/OSSupport.h index b5bcaee..66e03cf 100644 --- a/include/MUtils/OSSupport.h +++ b/include/MUtils/OSSupport.h @@ -41,6 +41,9 @@ namespace MUtils //Get known Folder const QString &known_folder(known_folder_t folder_id); + + //Error handling + void fatal_exit(const char* const errorMessage); } } diff --git a/src/CriticalSection_Win32.h b/src/CriticalSection_Win32.h new file mode 100644 index 0000000..e6f7b84 --- /dev/null +++ b/src/CriticalSection_Win32.h @@ -0,0 +1,98 @@ +/////////////////////////////////////////////////////////////////////////////// +// MuldeR's Utilities for Qt +// Copyright (C) 2004-2014 LoRd_MuldeR +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// http://www.gnu.org/licenses/lgpl-2.1.txt +////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +//Win32 API +#define WIN32_LEAN_AND_MEAN 1 +#include + +/////////////////////////////////////////////////////////////////////////////// +// CRITICAL SECTION +/////////////////////////////////////////////////////////////////////////////// + +/* + * wrapper for native Win32 critical sections + */ +class CriticalSection +{ +public: + inline CriticalSection(void) + { + InitializeCriticalSection(&m_win32criticalSection); + } + + inline ~CriticalSection(void) + { + DeleteCriticalSection(&m_win32criticalSection); + } + + inline void enter(void) + { + EnterCriticalSection(&m_win32criticalSection); + } + + inline bool tryEnter(void) + { + return TryEnterCriticalSection(&m_win32criticalSection); + } + + inline void leave(void) + { + LeaveCriticalSection(&m_win32criticalSection); + } + +protected: + CRITICAL_SECTION m_win32criticalSection; +}; + +/* + * RAII-style critical section locker + */ +class CSLocker +{ +public: + inline CSLocker(CriticalSection &criticalSection) + : + m_locked(false), + m_criticalSection(criticalSection) + { + m_criticalSection.enter(); + m_locked = true; + } + + inline ~CSLocker(void) + { + forceUnlock(); + } + + inline void forceUnlock(void) + { + if(m_locked) + { + m_criticalSection.leave(); + m_locked = false; + } + } +protected: + volatile bool m_locked; + CriticalSection &m_criticalSection; +}; diff --git a/src/Global.cpp b/src/Global.cpp index 8f53d4c..4b3b6f6 100644 --- a/src/Global.cpp +++ b/src/Global.cpp @@ -102,8 +102,8 @@ QString MUtils::rand_str(const bool &bLong) /////////////////////////////////////////////////////////////////////////////// static QReadWriteLock g_temp_folder_lock; -static QFile *g_temp_folder_file; -static QString *g_temp_folder_path = NULL; +static QFile* g_temp_folder_file = NULL; +static QString* g_temp_folder_path = NULL; #define INIT_TEMP_FOLDER_RAND(OUT_PTR, FILE_PTR, BASE_DIR) do \ { \ diff --git a/src/OSSupport_Win32.cpp b/src/OSSupport_Win32.cpp index ee9e2ba..26bb5d6 100644 --- a/src/OSSupport_Win32.cpp +++ b/src/OSSupport_Win32.cpp @@ -24,6 +24,7 @@ //Internal #include #include +#include "CriticalSection_Win32.h" //Win32 API #define WIN32_LEAN_AND_MEAN 1 @@ -36,6 +37,9 @@ #include #include +//Main thread ID +static const DWORD g_main_thread_id = GetCurrentThreadId(); + /////////////////////////////////////////////////////////////////////////////// // KNWON FOLDERS /////////////////////////////////////////////////////////////////////////////// @@ -155,3 +159,46 @@ const QString &MUtils::OS::known_folder(known_folder_t folder_id) } /////////////////////////////////////////////////////////////////////////////// +// FATAL EXIT +/////////////////////////////////////////////////////////////////////////////// + +static CriticalSection g_fatal_exit_lock; +static volatile bool g_fatal_exit_flag = true; + +static DWORD WINAPI fatal_exit_helper(LPVOID lpParameter) +{ + MessageBoxA(NULL, ((LPCSTR) lpParameter), "LameXP - Guru Meditation", MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_TOPMOST | MB_SETFOREGROUND); + return 0; +} + +void MUtils::OS::fatal_exit(const char* const errorMessage) +{ + g_fatal_exit_lock.enter(); + + if(!g_fatal_exit_flag) + { + return; /*prevent recursive invocation*/ + } + + g_fatal_exit_flag = false; + + if(g_main_thread_id != GetCurrentThreadId()) + { + if(HANDLE hThreadMain = OpenThread(THREAD_SUSPEND_RESUME, FALSE, g_main_thread_id)) + { + SuspendThread(hThreadMain); /*stop main thread*/ + } + } + + if(HANDLE hThread = CreateThread(NULL, 0, fatal_exit_helper, (LPVOID) errorMessage, 0, NULL)) + { + WaitForSingleObject(hThread, INFINITE); + } + + for(;;) + { + TerminateProcess(GetCurrentProcess(), 666); + } +} + +/////////////////////////////////////////////////////////////////////////////// diff --git a/src/UpdateChecker.cpp b/src/UpdateChecker.cpp index 5725207..490f9e8 100644 --- a/src/UpdateChecker.cpp +++ b/src/UpdateChecker.cpp @@ -19,8 +19,10 @@ // http://www.gnu.org/licenses/lgpl-2.1.txt ////////////////////////////////////////////////////////////////////////////////// -#include #include +#include +#include +#include #include #include @@ -213,7 +215,7 @@ UpdateChecker::UpdateChecker(const QString &binWGet, const QString &binGnuPG, co if(m_binaryWGet.isEmpty() || m_binaryGnuPG.isEmpty() || m_binaryKeys.isEmpty()) { - THROW("Tools not initialized correctly!"); + MUTILS_THROW("Tools not initialized correctly!"); } } @@ -229,22 +231,7 @@ UpdateChecker::~UpdateChecker(void) void UpdateChecker::run(void) { qDebug("Update checker thread started!"); - - try - { - m_testMode ? testKnownHosts() : checkForUpdates(); - } - catch(const std::exception &error) - { - PRINT_ERROR("\nGURU MEDITATION !!!\n\nException error:\n%s\n", error.what()); - lamexp_fatal_exit("Unhandeled C++ exception error, application will exit!"); - } - catch(...) - { - PRINT_ERROR("\nGURU MEDITATION !!!\n\nUnknown exception error!\n"); - lamexp_fatal_exit("Unhandeled C++ exception error, application will exit!"); - } - + MUTILS_EXCEPTION_HANDLER(m_testMode ? testKnownHosts() : checkForUpdates()); qDebug("Update checker thread completed."); }