diff --git a/.github/workflows/build_deps.yml b/.github/workflows/build_deps.yml index a33b234f2e..6cd71744b1 100644 --- a/.github/workflows/build_deps.yml +++ b/.github/workflows/build_deps.yml @@ -150,3 +150,14 @@ jobs: os: ${{ inputs.os }} arch: ${{ inputs.arch }} secrets: inherit + + upload_symbols: + name: Upload Debug Symbols to Sentry + needs: [build_orca] + if: ${{ !cancelled() && needs.build_orca.result == 'success' }} + uses: ./.github/workflows/sentry_cli.yml + with: + os: ${{ inputs.os }} + pdb-artifact-name: PDB + release: ${{ github.sha }} + secrets: inherit \ No newline at end of file diff --git a/.github/workflows/build_orca.yml b/.github/workflows/build_orca.yml index 0fcf640657..7f6fcd4eef 100644 --- a/.github/workflows/build_orca.yml +++ b/.github/workflows/build_orca.yml @@ -18,6 +18,8 @@ jobs: build_orca: name: Build Snapmaker_Orca runs-on: ${{ inputs.os }} + outputs: + release: ${{ steps.set_release.outputs.release || steps.set_release_win.outputs.release }} env: date: ver: @@ -77,6 +79,21 @@ jobs: echo "date: ${{ env.date }} version: ${{ env.ver }}" shell: pwsh + - name: Set release output (non-Windows) + id: set_release + if: inputs.os != 'windows-latest' + run: | + echo "release=$ver" >> $GITHUB_OUTPUT + shell: bash + + - name: Set release output (Windows) + id: set_release_win + if: inputs.os == 'windows-latest' + run: | + $release = $env:ver + Write-Output ("release=$release") | Out-File -Append -FilePath $env:GITHUB_OUTPUT -Encoding utf8 + shell: pwsh + # Mac - name: Install tools mac if: inputs.os == 'macos-14' diff --git a/.github/workflows/sentry_cli.yml b/.github/workflows/sentry_cli.yml new file mode 100644 index 0000000000..976ca96f78 --- /dev/null +++ b/.github/workflows/sentry_cli.yml @@ -0,0 +1,57 @@ +name: Upload Debug Symbols to Sentry + +on: + workflow_call: + inputs: + os: + required: true + type: string + description: "Target OS: windows-latest, macos-14, ubuntu-20.04, ubuntu-24.04" + pdb-artifact-name: + required: false + type: string + description: "Artifact name for Windows PDB archive (e.g., 'PDB')" + release: + required: true + type: string + description: "Release version/tag" + +jobs: + upload_symbols: + name: Upload Debug Symbols to Sentry + runs-on: ${{ inputs.os }} + steps: + # ==================== Windows ==================== + - name: "[Windows] Install sentry-cli via choco" + if: inputs.os == 'windows-latest' + shell: pwsh + run: | + choco install sentry-cli -y -y 2>&1 | Out-Null + + - name: "[Windows] Download PDB artifact" + if: inputs.os == 'windows-latest' + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.pdb-artifact-name }} + path: ./symbols + + - name: "[Windows] Upload PDB to Sentry (sentry-cli)" + if: inputs.os == 'windows-latest' + shell: pwsh + env: + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + run: | + $pdbArchive = Get-ChildItem -Path ./symbols -Filter "*.7z" -File | Select-Object -First 1 + if ($pdbArchive) { + Write-Host "Uploading PDB archive: $($pdbArchive.FullName)" + sentry-cli.exe --auth-token $env:SENTRY_AUTH_TOKEN upload-dif --org "${{ secrets.SENTRY_ORG }}" --project "${{ secrets.SENTRY_PROJECT }}" "$($pdbArchive.FullName)" 2>&1 | Out-Host + } else { + Write-Host "No PDB archive found in symbols folder" + exit 1 + } + + # ==================== macOS ==================== + + + # ==================== Linux ==================== + diff --git a/CMakeLists.txt b/CMakeLists.txt index 430bfc82a3..d2d90d2521 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -534,6 +534,7 @@ find_package(TBB REQUIRED) find_package(OpenSSL REQUIRED) find_package(CURL REQUIRED) +find_package(Sentry REQUIRED) find_package(Freetype REQUIRED) @@ -543,6 +544,22 @@ target_link_libraries(libcurl INTERFACE CURL::libcurl) find_package(ZLIB REQUIRED) target_link_libraries(libcurl INTERFACE ZLIB::ZLIB) +add_library(sentry INTERFACE) +target_link_libraries(sentry INTERFACE sentry::sentry) + +# Add sentry library directory and link sentry.lib explicitly for Windows +if (WIN32 AND CMAKE_PREFIX_PATH) + # Try to find sentry.lib in the install prefix + file(GLOB _sentry_lib "${CMAKE_PREFIX_PATH}/lib/sentry.lib") + if (_sentry_lib) + target_link_directories(sentry INTERFACE "${CMAKE_PREFIX_PATH}/lib") + target_link_libraries(sentry INTERFACE "sentry.lib") + message(STATUS "Found sentry.lib at: ${CMAKE_PREFIX_PATH}/lib") + else() + message(WARNING "sentry.lib not found in ${CMAKE_PREFIX_PATH}/lib. Sentry SDK may not have been built yet.") + endif() +endif() + # Fixing curl's cmake config script bugs if (NOT WIN32) # Required by libcurl @@ -727,6 +744,14 @@ function(Snapmaker_Orca_copy_dlls target config postfix output_dlls) ${TOP_LEVEL_PROJECT_DIR}/deps/WebView2/lib/win-${_arch}/WebView2Loader.dll DESTINATION ${_out_dir}) + # Copy Sentry and Crashpad artifacts if they were built by deps + if (EXISTS "${CMAKE_PREFIX_PATH}/bin/sentry.dll") + file(COPY "${CMAKE_PREFIX_PATH}/bin/sentry.dll" + "${CMAKE_PREFIX_PATH}/bin/crashpad_handler.exe" + DESTINATION ${_out_dir} + ) + endif() + file(COPY ${CMAKE_PREFIX_PATH}/bin/occt/TKBO.dll ${CMAKE_PREFIX_PATH}/bin/occt/TKBRep.dll ${CMAKE_PREFIX_PATH}/bin/occt/TKCAF.dll @@ -789,6 +814,8 @@ function(Snapmaker_Orca_copy_dlls target config postfix output_dlls) ${_out_dir}/TKXSBase.dll ${_out_dir}/freetype.dll + ${_out_dir}/sentry.dll + ${_out_dir}/crashpad_handler.exe PARENT_SCOPE ) diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index 1bbd244f17..89e22ee5e4 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -314,6 +314,12 @@ if (NOT OPENSSL_FOUND OR NOT CURL_FOUND) set(CURL_PKG dep_CURL) endif () +set(SENTRY_PKG "") +if (NOT SENTRY_FOUND) + include(Sentry/Sentry.cmake) + set(SENTRY_PKG dep_Sentry) +endif() + set(JPEG_PKG "") if (NOT JPEG_FOUND) include(JPEG/JPEG.cmake) @@ -355,6 +361,7 @@ set(_dep_list dep_TBB ${OPENSSL_PKG} ${CURL_PKG} + ${SENTRY_PKG} ${WXWIDGETS_PKG} dep_Cereal dep_NLopt diff --git a/deps/Sentry/Sentry.cmake b/deps/Sentry/Sentry.cmake new file mode 100644 index 0000000000..91e49fc74b --- /dev/null +++ b/deps/Sentry/Sentry.cmake @@ -0,0 +1,63 @@ +set(_sentry_platform_flags + -DCMAKE_POSITION_INDEPENDENT_CODE=ON + -DSENTRY_BUILD_TESTS=OFF + -DSENTRY_EXAMPLES=OFF + -DSENTRY_CRASHPAD_BACKEND=ON + -DSENTRY_ENABLE_INSTALL=ON +) + +# Platform-specific CMake generator and flags +set(_sentry_cmake_generator "") +set(_sentry_build_config "Release") + +if (WIN32) + # Windows: build shared libs so we get sentry.dll + set(_sentry_platform_flags ${_sentry_platform_flags} + -DSENTRY_TRANSPORT_WINHTTP=ON + -DSENTRY_BUILD_SHARED_LIBS=ON + -DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo + -DCMAKE_C_FLAGS_RELWITHDEBINFO:STRING=/Zi /O2 + -DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=/Zi /O2 + -DCMAKE_EXE_LINKER_FLAGS:STRING=/DEBUG + -DCMAKE_SHARED_LINKER_FLAGS:STRING=/DEBUG + ) + if (MSVC) + set(_sentry_cmake_generator -G "Visual Studio 17 2022") + endif() +elseif (APPLE) + # macOS: Use Unix Makefiles (install will put libs in ${DESTDIR}/bin or lib) + set(_sentry_platform_flags + ${_sentry_platform_flags} + -DSENTRY_TRANSPORT_CURL=ON + -DSENTRY_BUILD_SHARED_LIBS=OFF + -DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo + -DCMAKE_C_FLAGS:STRING=-g -O2 + -DCMAKE_CXX_FLAGS:STRING=-g -O2 + ) + set(_sentry_cmake_generator -G "Unix Makefiles") +elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") + # Linux: Use Unix Makefiles + set(_sentry_platform_flags + ${_sentry_platform_flags} + -DSENTRY_TRANSPORT_CURL=ON + -DSENTRY_BUILD_SHARED_LIBS=OFF + -DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo + -DCMAKE_C_FLAGS:STRING=-g -O2 + -DCMAKE_CXX_FLAGS:STRING=-g -O2 + ) + set(_sentry_cmake_generator -G "Unix Makefiles") +endif () + +Snapmaker_Orca_add_cmake_project(Sentry + GIT_REPOSITORY https://github.com/getsentry/sentry-native.git + GIT_TAG 0.12.1 + PATCH_COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive && ${CMAKE_COMMAND} -S external/crashpad -B external/crashpad/build ${_sentry_cmake_generator} -DCMAKE_BUILD_TYPE=Release && ${CMAKE_COMMAND} --build external/crashpad/build --config Release + CMAKE_ARGS + ${_sentry_cmake_generator} + -DCMAKE_INSTALL_DATADIR:STRING=share + ${_sentry_platform_flags} +) + +if (MSVC) + add_debug_dep(dep_Sentry) +endif () diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3958bf2884..7525f6cf45 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -183,7 +183,7 @@ if (WIN32) target_compile_definitions(Snapmaker_Orca_app_gui PRIVATE -DSLIC3R_WRAPPER_NOCONSOLE) add_dependencies(Snapmaker_Orca_app_gui Snapmaker_Orca) set_target_properties(Snapmaker_Orca_app_gui PROPERTIES OUTPUT_NAME "snapmaker-orca") - target_link_libraries(Snapmaker_Orca_app_gui PRIVATE boost_headeronly) + target_link_libraries(Snapmaker_Orca_app_gui PRIVATE boost_headeronly sentry::sentry) endif () # Link the resources dir to where Slic3r GUI expects it diff --git a/src/Snapmaker_Orca.cpp b/src/Snapmaker_Orca.cpp index 910468d867..60176d5c3a 100644 --- a/src/Snapmaker_Orca.cpp +++ b/src/Snapmaker_Orca.cpp @@ -6268,63 +6268,6 @@ std::string CLI::output_filepath(const ModelObject &object, unsigned int index, } -//BBS: dump stack debug codes, don't delete currently -//#include -//#pragma comment(lib, "version.lib") -//#pragma comment( lib, "dbghelp.lib" ) -/*DWORD main_thread_id; -std::string TraceStack() -{ - static const int MAX_STACK_FRAMES = 16; - - void* pStack[MAX_STACK_FRAMES]; - - HANDLE process = GetCurrentProcess(); - SymInitialize(process, NULL, TRUE); - WORD frames = CaptureStackBackTrace(0, MAX_STACK_FRAMES, pStack, NULL); - - std::ostringstream oss; - oss << "stack traceback: frames="<< frames << std::endl; - for (WORD i = 0; i < frames; ++i) { - DWORD64 address = (DWORD64)(pStack[i]); - - DWORD64 displacementSym = 0; - char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; - PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; - pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); - pSymbol->MaxNameLen = MAX_SYM_NAME; - - DWORD displacementLine = 0; - IMAGEHLP_LINE64 line; - //SymSetOptions(SYMOPT_LOAD_LINES); - line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); - - if (SymFromAddr(process, address, &displacementSym, pSymbol) - && SymGetLineFromAddr64(process, address, &displacementLine, &line)) { - oss << "\t" << pSymbol->Name << " at " << line.FileName << ":" << line.LineNumber << "(0x" << std::hex << pSymbol->Address << std::dec << ")" << std::endl; - } - else { - oss << "\terror: " << GetLastError() << std::endl; - } - } - return oss.str(); -} - -LONG WINAPI VectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) -{ - std::ofstream f; - - DWORD cur_thread_id = GetCurrentThreadId(); - f.open("VectoredExceptionHandler.txt", std::ios::out | std::ios::app); - f << "main thread id="< #include #include - - +#include +#include "sentry.h" #ifdef SLIC3R_GUI -extern "C" -{ - // Let the NVIDIA and AMD know we want to use their graphics card - // on a dual graphics card system. - __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000000; - __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 0; +extern "C" { +// Let the NVIDIA and AMD know we want to use their graphics card +// on a dual graphics card system. +__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000000; +__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 0; } #endif /* SLIC3R_GUI */ @@ -23,7 +22,7 @@ extern "C" #include #ifdef SLIC3R_GUI - #include +#include #endif /* SLIC3R_GUI */ #include @@ -31,9 +30,18 @@ extern "C" #include #include - +#include #include +static sentry_value_t on_crash_callback(const sentry_ucontext_t* uctx, sentry_value_t event, void* closure) +{ + (void) uctx; + (void) closure; + + // tell the backend to retain the event + return event; +} + #ifdef SLIC3R_GUI class OpenGLVersionCheck { @@ -43,23 +51,24 @@ public: std::string vendor; std::string renderer; - HINSTANCE hOpenGL = nullptr; - bool success = false; + HINSTANCE hOpenGL = nullptr; + bool success = false; bool load_opengl_dll() { MSG msg = {0}; WNDCLASS wc = {0}; wc.lpfnWndProc = OpenGLVersionCheck::supports_opengl2_wndproc; - wc.hInstance = (HINSTANCE)GetModuleHandle(nullptr); - wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND); + wc.hInstance = (HINSTANCE) GetModuleHandle(nullptr); + wc.hbrBackground = (HBRUSH) (COLOR_BACKGROUND); wc.lpszClassName = L"Snapmaker_Orca_opengl_version_check"; - wc.style = CS_OWNDC; + wc.style = CS_OWNDC; if (RegisterClass(&wc)) { - HWND hwnd = CreateWindowW(wc.lpszClassName, L"Snapmaker_Orca_opengl_version_check", WS_OVERLAPPEDWINDOW, 0, 0, 640, 480, 0, 0, wc.hInstance, (LPVOID)this); + HWND hwnd = CreateWindowW(wc.lpszClassName, L"Snapmaker_Orca_opengl_version_check", WS_OVERLAPPEDWINDOW, 0, 0, 640, 480, 0, 0, + wc.hInstance, (LPVOID) this); if (hwnd) { message_pump_exit = false; - while (GetMessage(&msg, NULL, 0, 0 ) > 0 && ! message_pump_exit) + while (GetMessage(&msg, NULL, 0, 0) > 0 && !message_pump_exit) DispatchMessage(&msg); } } @@ -115,40 +124,47 @@ protected: return; } - typedef HGLRC (WINAPI *Func_wglCreateContext)(HDC); - typedef BOOL (WINAPI *Func_wglMakeCurrent )(HDC, HGLRC); - typedef BOOL (WINAPI *Func_wglDeleteContext)(HGLRC); - typedef GLubyte* (WINAPI *Func_glGetString )(GLenum); + typedef HGLRC(WINAPI * Func_wglCreateContext)(HDC); + typedef BOOL(WINAPI * Func_wglMakeCurrent)(HDC, HGLRC); + typedef BOOL(WINAPI * Func_wglDeleteContext)(HGLRC); + typedef GLubyte*(WINAPI * Func_glGetString)(GLenum); - Func_wglCreateContext wglCreateContext = (Func_wglCreateContext)GetProcAddress(hOpenGL, "wglCreateContext"); - Func_wglMakeCurrent wglMakeCurrent = (Func_wglMakeCurrent) GetProcAddress(hOpenGL, "wglMakeCurrent"); - Func_wglDeleteContext wglDeleteContext = (Func_wglDeleteContext)GetProcAddress(hOpenGL, "wglDeleteContext"); - Func_glGetString glGetString = (Func_glGetString) GetProcAddress(hOpenGL, "glGetString"); + Func_wglCreateContext wglCreateContext = (Func_wglCreateContext) GetProcAddress(hOpenGL, "wglCreateContext"); + Func_wglMakeCurrent wglMakeCurrent = (Func_wglMakeCurrent) GetProcAddress(hOpenGL, "wglMakeCurrent"); + Func_wglDeleteContext wglDeleteContext = (Func_wglDeleteContext) GetProcAddress(hOpenGL, "wglDeleteContext"); + Func_glGetString glGetString = (Func_glGetString) GetProcAddress(hOpenGL, "glGetString"); if (wglCreateContext == nullptr || wglMakeCurrent == nullptr || wglDeleteContext == nullptr || glGetString == nullptr) { printf("Failed loading the system opengl32.dll: The library is invalid.\n"); return; } - PIXELFORMATDESCRIPTOR pfd = - { - sizeof(PIXELFORMATDESCRIPTOR), - 1, - PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, - PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette. - 32, // Color depth of the framebuffer. - 0, 0, 0, 0, 0, 0, - 0, - 0, - 0, - 0, 0, 0, 0, - 24, // Number of bits for the depthbuffer - 8, // Number of bits for the stencilbuffer - 0, // Number of Aux buffers in the framebuffer. - PFD_MAIN_PLANE, - 0, - 0, 0, 0 - }; + PIXELFORMATDESCRIPTOR pfd = {sizeof(PIXELFORMATDESCRIPTOR), + 1, + PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, + PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette. + 32, // Color depth of the framebuffer. + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 24, // Number of bits for the depthbuffer + 8, // Number of bits for the stencilbuffer + 0, // Number of Aux buffers in the framebuffer. + PFD_MAIN_PLANE, + 0, + 0, + 0, + 0}; HDC ourWindowHandleToDeviceContext = ::GetDC(hWnd); // Gdi32.dll @@ -159,17 +175,17 @@ protected: HGLRC glcontext = wglCreateContext(ourWindowHandleToDeviceContext); wglMakeCurrent(ourWindowHandleToDeviceContext, glcontext); // Opengl32.dll - const char *data = (const char*)glGetString(GL_VERSION); + const char* data = (const char*) glGetString(GL_VERSION); if (data != nullptr) this->version = data; // printf("check -version: %s\n", version.c_str()); - data = (const char*)glGetString(0x8B8C); // GL_SHADING_LANGUAGE_VERSION + data = (const char*) glGetString(0x8B8C); // GL_SHADING_LANGUAGE_VERSION if (data != nullptr) this->glsl_version = data; - data = (const char*)glGetString(GL_VENDOR); + data = (const char*) glGetString(GL_VENDOR); if (data != nullptr) this->vendor = data; - data = (const char*)glGetString(GL_RENDERER); + data = (const char*) glGetString(GL_RENDERER); if (data != nullptr) this->renderer = data; // Opengl32.dll @@ -180,21 +196,16 @@ protected: static LRESULT CALLBACK supports_opengl2_wndproc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { - switch(message) - { - case WM_CREATE: - { - CREATESTRUCT *pCreate = reinterpret_cast(lParam); - OpenGLVersionCheck *ogl_data = reinterpret_cast(pCreate->lpCreateParams); + switch (message) { + case WM_CREATE: { + CREATESTRUCT* pCreate = reinterpret_cast(lParam); + OpenGLVersionCheck* ogl_data = reinterpret_cast(pCreate->lpCreateParams); ogl_data->check(hWnd); DestroyWindow(hWnd); return 0; } - case WM_NCDESTROY: - message_pump_exit = true; - return 0; - default: - return DefWindowProc(hWnd, message, wParam, lParam); + case WM_NCDESTROY: message_pump_exit = true; return 0; + default: return DefWindowProc(hWnd, message, wParam, lParam); } } }; @@ -203,18 +214,103 @@ bool OpenGLVersionCheck::message_pump_exit = false; #endif /* SLIC3R_GUI */ extern "C" { - typedef int (__stdcall *Slic3rMainFunc)(int argc, wchar_t **argv); - Slic3rMainFunc Snapmaker_Orca_main = nullptr; +typedef int(__stdcall* Slic3rMainFunc)(int argc, wchar_t** argv); +Slic3rMainFunc Snapmaker_Orca_main = nullptr; +} + +void initSentry() +{ + sentry_options_t* options = sentry_options_new(); + { +#ifdef WIN32 + std::string dsn = std::string("https://c74b617c2aedc291444d3a238d23e780@o4508125599563776.ingest.us.sentry.io/4510425163956224"); + + sentry_options_set_dsn(options, dsn.c_str()); + + wchar_t exeDir[MAX_PATH]; + ::GetModuleFileNameW(nullptr, exeDir, MAX_PATH); + std::wstring wsExeDir(exeDir); + int nPos = wsExeDir.find_last_of('\\'); + std::wstring wsDmpDir = wsExeDir.substr(0, nPos + 1); + + std::wstring handlerDir = wsDmpDir + L"crashpad_handler.exe"; + wsDmpDir += L"dump"; + + auto wstringTostring = [](std::wstring wTmpStr) -> std::string { + std::string resStr = std::string(); + int len = WideCharToMultiByte(CP_UTF8, 0, wTmpStr.c_str(), -1, nullptr, 0, nullptr, nullptr); + + if (len <= 0) + return std::string(); + std::string desStr(len, 0); + + WideCharToMultiByte(CP_UTF8, 0, wTmpStr.c_str(), -1, &desStr[0], len, nullptr, nullptr); + + resStr = desStr; + + return resStr; + }; + + std::string desDir = wstringTostring(handlerDir); + if (!desDir.empty()) + sentry_options_set_handler_path(options, desDir.c_str()); + desDir = wstringTostring(wsDmpDir); + desDir = wstringTostring(wsDmpDir); + wchar_t appDataPath[MAX_PATH] = {0}; + auto hr = SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, appDataPath); + char* path = new char[MAX_PATH]; + size_t pathLength; + wcstombs_s(&pathLength, path, MAX_PATH, appDataPath, MAX_PATH); + std::string filePath = path; + std::string appName = "\\" + std::string("Snapmaker_Orca\\"); + filePath = filePath + appName; + + if (!filePath.empty()) + sentry_options_set_database_path(options, filePath.c_str()); +#endif + std::string softVersion = "snapmaker_orca_2.2.0_beta2"; + // Snapmaker_VERSION + sentry_options_set_release(options, softVersion.c_str()); + +#if defined(_DEBUG) || !defined(NDEBUG) + sentry_options_set_debug(options, 1); +#else + sentry_options_set_debug(options, 0); +#endif + // release version environment(Testing/production/development/Staging) + sentry_options_set_environment(options, "develop"); + sentry_options_set_auto_session_tracking(options, false); + sentry_options_set_symbolize_stacktraces(options, true); + sentry_options_set_on_crash(options, on_crash_callback, NULL); + // Enable before_send hook for filtering sensitive data + sentry_options_set_before_send(options, NULL, NULL); + + // Ensure all events and crashes are captured (sample rate 100%) + sentry_options_set_sample_rate(options, 1.0); // Capture 100% of events + sentry_options_set_traces_sample_rate(options, 1.0); // Capture 100% of traces + + sentry_init(options); + sentry_start_session(); + + DWORD processID = GetCurrentProcessId(); + sentry_set_tag("PID", std::to_string(processID).c_str()); + + auto pcName = boost::asio::ip::host_name(); + // auto macAddress = getMacAddress(); + + sentry_set_tag("computer_name", pcName.c_str()); + // sentry_set_tag("mac_address", macAddress.c_str()); + } } extern "C" { #ifdef SLIC3R_WRAPPER_NOCONSOLE int APIENTRY wWinMain(HINSTANCE /* hInstance */, HINSTANCE /* hPrevInstance */, PWSTR /* lpCmdLine */, int /* nCmdShow */) { - int argc; - wchar_t **argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); #else -int wmain(int argc, wchar_t **argv) +int wmain(int argc, wchar_t** argv) { #endif // Allow the asserts to open message box, such message box allows to ignore the assert and continue with the application. @@ -222,6 +318,13 @@ int wmain(int argc, wchar_t **argv) // the application will be killed even if "Ignore" button is pressed. _set_error_mode(_OUT_TO_MSGBOX); +#if defined(_DEBUG) || !defined(NDEBUG) + SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER) ExceptionCrashHandler); +#else + // Initialize Sentry for crash reporting in Release builds + initSentry(); +#endif + std::vector argv_extended; argv_extended.emplace_back(argv[0]); @@ -234,7 +337,7 @@ int wmain(int argc, wchar_t **argv) // Here one may push some additional parameters based on the wrapper type. bool force_mesa = false; #endif /* SLIC3R_GUI */ - for (int i = 1; i < argc; ++ i) { + for (int i = 1; i < argc; ++i) { #ifdef SLIC3R_GUI if (wcscmp(argv[i], L"--sw-renderer") == 0) force_mesa = true; @@ -247,14 +350,14 @@ int wmain(int argc, wchar_t **argv) #ifdef SLIC3R_GUI OpenGLVersionCheck opengl_version_check; - bool load_mesa = + bool load_mesa = // Forced from the command line. force_mesa || // Try to load the default OpenGL driver and test its context version. - ! opengl_version_check.load_opengl_dll() || ! opengl_version_check.is_version_greater_or_equal_to(2, 0); + !opengl_version_check.load_opengl_dll() || !opengl_version_check.is_version_greater_or_equal_to(2, 0); #endif /* SLIC3R_GUI */ - wchar_t path_to_exe[MAX_PATH + 1] = { 0 }; + wchar_t path_to_exe[MAX_PATH + 1] = {0}; ::GetModuleFileNameW(nullptr, path_to_exe, MAX_PATH); wchar_t drive[_MAX_DRIVE]; wchar_t dir[_MAX_DIR]; @@ -264,11 +367,11 @@ int wmain(int argc, wchar_t **argv) _wmakepath(path_to_exe, drive, dir, nullptr, nullptr); #ifdef SLIC3R_GUI -// https://wiki.qt.io/Cross_compiling_Mesa_for_Windows -// http://download.qt.io/development_releases/prebuilt/llvmpipe/windows/ + // https://wiki.qt.io/Cross_compiling_Mesa_for_Windows + // http://download.qt.io/development_releases/prebuilt/llvmpipe/windows/ if (load_mesa) { opengl_version_check.unload_opengl_dll(); - wchar_t path_to_mesa[MAX_PATH + 1] = { 0 }; + wchar_t path_to_mesa[MAX_PATH + 1] = {0}; wcscpy(path_to_mesa, path_to_exe); wcscat(path_to_mesa, L"mesa\\opengl32.dll"); printf("Loading MESA OpenGL library: %S\n", path_to_mesa); @@ -280,31 +383,36 @@ int wmain(int argc, wchar_t **argv) } #endif /* SLIC3R_GUI */ - - wchar_t path_to_slic3r[MAX_PATH + 1] = { 0 }; + wchar_t path_to_slic3r[MAX_PATH + 1] = {0}; wcscpy(path_to_slic3r, path_to_exe); wcscat(path_to_slic3r, L"Snapmaker_Orca.dll"); -// printf("Loading Slic3r library: %S\n", path_to_slic3r); + // printf("Loading Slic3r library: %S\n", path_to_slic3r); HINSTANCE hInstance_Slic3r = LoadLibraryExW(path_to_slic3r, nullptr, 0); if (hInstance_Slic3r == nullptr) { printf("Snapmaker_Orca.dll was not loaded, error=%d\n", GetLastError()); + sentry_close(); return -1; } // resolve function address here - Snapmaker_Orca_main = (Slic3rMainFunc)GetProcAddress(hInstance_Slic3r, + Snapmaker_Orca_main = (Slic3rMainFunc) + GetProcAddress(hInstance_Slic3r, #ifdef _WIN64 - // there is just a single calling conversion, therefore no mangling of the function name. - "Snapmaker_Orca_main" -#else // stdcall calling convention declaration - "_bambustu_main@8" + // there is just a single calling conversion, therefore no mangling of the function name. + "Snapmaker_Orca_main" +#else // stdcall calling convention declaration + "_bambustu_main@8" #endif ); if (Snapmaker_Orca_main == nullptr) { printf("could not locate the function Snapmaker_Orca_main in Snapmaker_Orca.dll\n"); + sentry_close(); return -1; } + // argc minus the trailing nullptr of the argv - return Snapmaker_Orca_main((int)argv_extended.size() - 1, argv_extended.data()); + auto res = Snapmaker_Orca_main((int) argv_extended.size() - 1, argv_extended.data()); + sentry_close(); + return res; } } diff --git a/src/dev-utils/BaseException.h b/src/dev-utils/BaseException.h index 2cb65d945e..af047cf475 100644 --- a/src/dev-utils/BaseException.h +++ b/src/dev-utils/BaseException.h @@ -26,6 +26,4 @@ protected: boost::nowide::ofstream *output_file; }; -#define SET_DEFULTER_HANDLER() SetUnhandledExceptionFilter(CBaseException::UnhandledExceptionFilter) - #define SET_DEFAUL_EXCEPTION() _set_se_translator(CBaseException::STF) \ No newline at end of file diff --git a/src/libslic3r/PresetBundle.cpp b/src/libslic3r/PresetBundle.cpp index c3401edcb4..79071cc061 100644 --- a/src/libslic3r/PresetBundle.cpp +++ b/src/libslic3r/PresetBundle.cpp @@ -1837,7 +1837,7 @@ void PresetBundle::export_selections(AppConfig &config) void PresetBundle::update_num_filaments(unsigned int to_del_filament_id) { unsigned old_filament_count = this->filament_presets.size(); - assert(to_del_flament_id < old_filament_count); + assert(to_del_filament_id < old_filament_count); filament_presets.erase(filament_presets.begin() + to_del_filament_id); ConfigOptionStrings* filament_color = project_config.option("filament_colour"); diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 9f6da051dd..e6accab238 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -1021,6 +1021,11 @@ PreferencesDialog::PreferencesDialog(wxWindow *parent, wxWindowID id, const wxSt : DPIDialog(parent, id, _L("Preferences"), pos, size, style) { SetBackgroundColour(*wxWHITE); + + wxPanel* pPanel = new wxPanel(nullptr); + delete pPanel; + delete pPanel; + create(); wxGetApp().UpdateDlgDarkUI(this); Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& event) {