diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 5749d4f6..e0017230 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -28,6 +28,7 @@ if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug") add_link_options(-O3) endif () +add_subdirectory(utils) add_subdirectory(libjvm_wrapper) add_subdirectory(backend) add_subdirectory(gui) diff --git a/launcher/backend/CMakeLists.txt b/launcher/backend/CMakeLists.txt index 878b84a8..96d81d2d 100644 --- a/launcher/backend/CMakeLists.txt +++ b/launcher/backend/CMakeLists.txt @@ -6,4 +6,4 @@ add_library(backend target_include_directories(backend PRIVATE include) target_include_directories(backend PUBLIC include_public) -target_link_libraries(backend PUBLIC libjvm_wrapper) +target_link_libraries(backend PUBLIC libjvm_wrapper utils) diff --git a/launcher/backend/src/DhfsInstance.cpp b/launcher/backend/src/DhfsInstance.cpp index 394db4a6..25be22da 100644 --- a/launcher/backend/src/DhfsInstance.cpp +++ b/launcher/backend/src/DhfsInstance.cpp @@ -35,7 +35,7 @@ void DhfsInstance::start() { args.options = options.data(); args.ignoreUnrecognized = false; - LibjvmWrapper::instance().JNI_CreateJavaVM(&_jvm, (void**) &_env, &args); + LibjvmWrapper::instance().WJNI_CreateJavaVM(&_jvm, (void**) &_env, &args); } void DhfsInstance::stop() { diff --git a/launcher/gui/CMakeLists.txt b/launcher/gui/CMakeLists.txt index 3cb68c77..ea15a326 100644 --- a/launcher/gui/CMakeLists.txt +++ b/launcher/gui/CMakeLists.txt @@ -11,4 +11,4 @@ add_executable(launcher ) target_link_libraries(launcher ${wxWidgets_LIBRARIES}) -target_link_libraries(launcher backend) \ No newline at end of file +target_link_libraries(launcher backend utils) \ No newline at end of file diff --git a/launcher/gui/src/LauncherApp.cpp b/launcher/gui/src/LauncherApp.cpp index 68ab7a09..636e3a04 100644 --- a/launcher/gui/src/LauncherApp.cpp +++ b/launcher/gui/src/LauncherApp.cpp @@ -31,3 +31,12 @@ bool LauncherApp::OnInit() { return true; } + +bool LauncherApp::OnExceptionInMainLoop() { + try { + std::rethrow_exception(std::current_exception()); + } catch (const std::exception& e) { + wxMessageBox(e.what(), "Error", wxOK | wxICON_ERROR | wxCENTRE, GetTopWindow()); + } + return true; +} diff --git a/launcher/gui/src/LauncherApp.h b/launcher/gui/src/LauncherApp.h index 1600383c..830702a7 100644 --- a/launcher/gui/src/LauncherApp.h +++ b/launcher/gui/src/LauncherApp.h @@ -9,7 +9,9 @@ // containing a statusbar with the text "Hello World" class LauncherApp : public wxApp { public: - virtual bool OnInit(); + virtual bool OnInit() override; + + virtual bool OnExceptionInMainLoop() override; }; DECLARE_APP(LauncherApp) diff --git a/launcher/libjvm_wrapper/CMakeLists.txt b/launcher/libjvm_wrapper/CMakeLists.txt index 6c90549c..9540653c 100644 --- a/launcher/libjvm_wrapper/CMakeLists.txt +++ b/launcher/libjvm_wrapper/CMakeLists.txt @@ -7,4 +7,6 @@ target_include_directories(libjvm_wrapper PRIVATE include) target_include_directories(libjvm_wrapper PUBLIC include_public) find_package(JNI REQUIRED) -target_include_directories(libjvm_wrapper PUBLIC ${JNI_INCLUDE_DIRS}) \ No newline at end of file +target_include_directories(libjvm_wrapper PUBLIC ${JNI_INCLUDE_DIRS}) + +target_link_libraries(libjvm_wrapper PUBLIC utils) \ No newline at end of file diff --git a/launcher/libjvm_wrapper/include_public/LibjvmWrapper.hpp b/launcher/libjvm_wrapper/include_public/LibjvmWrapper.hpp index 727f915a..fe008280 100644 --- a/launcher/libjvm_wrapper/include_public/LibjvmWrapper.hpp +++ b/launcher/libjvm_wrapper/include_public/LibjvmWrapper.hpp @@ -4,14 +4,14 @@ #ifndef LIBJVMWRAPPER_HPP #define LIBJVMWRAPPER_HPP -#include +#include class LibjvmWrapper { public: static LibjvmWrapper& instance(); - decltype(JNI_CreateJavaVM)* JNI_CreateJavaVM; + decltype(JNI_CreateJavaVM)* WJNI_CreateJavaVM; private: LibjvmWrapper(); diff --git a/launcher/libjvm_wrapper/src/LibjvmWrapper.cpp b/launcher/libjvm_wrapper/src/LibjvmWrapper.cpp index 00fe6778..72e02e41 100644 --- a/launcher/libjvm_wrapper/src/LibjvmWrapper.cpp +++ b/launcher/libjvm_wrapper/src/LibjvmWrapper.cpp @@ -6,6 +6,8 @@ #include #include +#include "Exception.h" + static constexpr auto LIBJVM_PATH = "/Library/Java/JavaVirtualMachines/zulu-21.jdk/Contents/Home/lib/server/libjvm.dylib"; @@ -16,8 +18,12 @@ LibjvmWrapper& LibjvmWrapper::instance() { LibjvmWrapper::LibjvmWrapper() { _lib_handle = dlopen(LIBJVM_PATH, RTLD_NOW | RTLD_GLOBAL); - JNI_CreateJavaVM = reinterpret_cast( + if (_lib_handle == nullptr) + throw Exception(dlerror()); + WJNI_CreateJavaVM = reinterpret_cast( dlsym(_lib_handle, "JNI_CreateJavaVM")); + if (WJNI_CreateJavaVM == nullptr) + throw Exception(dlerror()); } LibjvmWrapper::~LibjvmWrapper() { diff --git a/launcher/utils/CMakeLists.txt b/launcher/utils/CMakeLists.txt new file mode 100644 index 00000000..a4adbd05 --- /dev/null +++ b/launcher/utils/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(utils + src/Exception.cpp + include_public/Exception.h +) + +target_include_directories(utils PRIVATE include) +target_include_directories(utils PUBLIC include_public) \ No newline at end of file diff --git a/launcher/utils/include_public/Exception.h b/launcher/utils/include_public/Exception.h new file mode 100644 index 00000000..4bd4a68a --- /dev/null +++ b/launcher/utils/include_public/Exception.h @@ -0,0 +1,30 @@ +// +// Created by Stepan Usatiuk on 01.05.2023. +// + +#ifndef SEMBACKUP_EXCEPTION_H +#define SEMBACKUP_EXCEPTION_H + +#include +#include +#include +#include + +/// Custom exception class that uses execinfo to append a stacktrace to the exception message +class Exception : public std::runtime_error { +public: + Exception(const std::string& text); + Exception(const char* text); + +private: + /// Static function to get the current stacktrace + static std::string getStacktrace(); +}; + +class ErrnoException : public Exception { +public: + ErrnoException(const std::string& text) : Exception(text + " " + std::strerror(errno)) {} + ErrnoException(const char* text) : Exception(std::string(text) + " " + std::strerror(errno)) {} +}; + +#endif // SEMBACKUP_EXCEPTION_H diff --git a/launcher/utils/src/Exception.cpp b/launcher/utils/src/Exception.cpp new file mode 100644 index 00000000..63f2f96e --- /dev/null +++ b/launcher/utils/src/Exception.cpp @@ -0,0 +1,37 @@ +// +// Created by Stepan Usatiuk on 01.05.2023. +// + +#include "Exception.h" + +#include +#include + +#include + +Exception::Exception(const std::string& text) : runtime_error(text + "\n" + getStacktrace()) { +} + +Exception::Exception(const char* text) : runtime_error(std::string(text) + "\n" + getStacktrace()) { +} + +// Based on: https://www.gnu.org/software/libc/manual/html_node/Backtraces.html +std::string Exception::getStacktrace() { + std::vector functions(50); + char** strings; + int n; + + n = backtrace(functions.data(), 50); + strings = backtrace_symbols(functions.data(), n); + + std::stringstream out; + + if (strings != nullptr) { + out << "Stacktrace:" << std::endl; + for (int i = 0; i < n; i++) + out << strings[i] << std::endl; + } + + free(strings); + return out.str(); +}