Infrastructure: Sentry integration#8540
Conversation
|
Hey there! Thanks for helping Mudlet improve. 🌟 Test versionsYou can directly test the changes here:
No need to install anything - just unzip and run. |
📝 WalkthroughWalkthroughThis pull request integrates Sentry crash reporting into Mudlet across multiple build systems and platforms. Changes include adding sentry-native as a Git submodule, updating GitHub workflows to enable recursive submodule initialization and pass Sentry authentication tokens, modifying Windows and Linux build scripts to conditionally compile and configure Sentry support, and creating new source files for Sentry initialization and a Qt-based crash reporter application. Build system modifications span CMake, Qt Pro files, and shell scripts. Additionally, Lua utility functions are refactored to use a custom substitution routine, and debug file upload automation is introduced via CI scripts. ✨ Finishing touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (15)
src/mudlet-lua/lua/GUIUtils.lua (1)
2055-2055: Improve comment to explain the reason for custom implementation.The comment is informal and lacks technical detail about why
rex.gsubwas crashing. Consider documenting:
- The specific issue with
rex.gsub(e.g., crash conditions, bug reference)- Any behavioral differences from the original
- Limitations of the custom implementation (e.g., only uses first capture group)
--- rex.gsub was crashing so here is a homemade +-- Custom implementation of rex.gsub to work around crashes in the native implementation. +-- Note: Only the first capture group is used if the pattern has multiple captures.src/mudlet-lua/lua/DateTime.lua (2)
49-49: Enhance the comment with crash details.The comment briefly states that
rex.gsubwas crashing but lacks important context such as the conditions under which it crashes, affected platforms (Linux/macOS/Windows), or any relation to the Sentry integration. Consider documenting:
- Specific error or crash behavior observed
- Platforms or build configurations where the crash occurs
- Whether this is a known issue with the rex library version in use
50-73: Approve implementation but refactor to eliminate code duplication.The custom
rex_gsub_customimplementation correctly handles the datetime directive substitution use case. The logic is sound: it iterates through matches, assembles output pieces, and properly handles both function and static replacements.However, this exact function also exists in
GUIUtils.lua(lines 2055-2078). Duplicating utility functions across multiple files violates the DRY principle and increases maintenance burden.Consider extracting this function into a shared utility module (e.g.,
StringUtils.luaorRexUtils.lua) that bothDateTime.luaandGUIUtils.luacan require..github/workflows/update-en-us-plural.yml (1)
21-22: Submodule initialization is redundant with checkout configuration.The checkout step on line 19 already specifies
submodules: true, which initializes submodules. The additional recursive initialization step may only be necessary if the sentry-native submodule contains nested submodules that require explicit recursive initialization.Consider whether the sentry-native submodule actually requires recursive initialization. If it doesn't have nested submodules, you could simplify by either:
- Removing this step entirely and relying on the checkout action's
submodules: true, or- Changing the checkout action to
submodules: recursiveand removing this separate step:- uses: actions/checkout@v5 with: ref: development - submodules: true + submodules: recursive - - - name: Init all submodules recursively - run: git submodule update --init --recursivesrc/sentry_dsn.txt (1)
1-1: Document that users should configure their own Sentry DSN.This file contains a Sentry DSN (Data Source Name) in plaintext. While DSNs are designed to be client-facing and don't grant access to view crash reports, this appears to be the Mudlet project's DSN. Users building their own forks or variants should be instructed to:
- Create their own Sentry project
- Replace this DSN with their own
- Set appropriate
SENTRY_AUTH_TOKENfor debug file uploadsConsider adding a comment or documentation (perhaps in a nearby README or build documentation) explaining:
- This DSN is for the official Mudlet project
- Fork maintainers should create their own Sentry project and replace this DSN
- How to disable Sentry entirely by building without
-DWITH_SENTRY=ONExample comment at the top of this file:
+# Official Mudlet Sentry DSN for crash reporting +# If you're building a fork, create your own Sentry project at https://sentry.io +# and replace this DSN with your own, or build without -DWITH_SENTRY=ON https://b207505f6b88191fa4bbcb9b166f61ae@o4510296017338368.ingest.de.sentry.io/4510330003849296.github/workflows/performance-analysis.yml (1)
30-31: Submodule initialization may be redundant with checkout configuration.The checkout step on line 28 already specifies
submodules: true. This additional recursive initialization step is only necessary if nested submodules exist within the sentry-native submodule.See the comment on
.github/workflows/update-en-us-plural.ymllines 21-22 for consolidation options..github/workflows/clangtidy-diff-analysis.yml (1)
39-40: Submodule initialization may be redundant with checkout configuration.The checkout step on line 32 already specifies
submodules: true. See the comment on.github/workflows/update-en-us-plural.ymllines 21-22 for consolidation options..github/workflows/update-translations.yml (1)
24-25: Submodule initialization may be redundant with checkout configuration.The checkout step on line 20 already specifies
submodules: true. See the comment on.github/workflows/update-en-us-plural.ymllines 21-22 for consolidation options..github/workflows/codeql-analysis.yml (1)
49-50: Redundant submodule initialization.The checkout action at line 47 already has
submodules: true, which initializes submodules. The explicitgit submodule update --init --recursivestep is redundant.Consider removing this step:
- - name: Init all submodules recursively - run: git submodule update --init --recursive -Note: If the intent is to initialize submodules recursively (which
submodules: truedoes not do by default in older actions/checkout versions), you can usesubmodules: recursivein the checkout step instead..github/workflows/update-3rdparty.yml (2)
107-108: Redundant submodule initialization.The checkout action at line 104 already has
submodules: true, making this explicit initialization redundant.Consider removing this step or use
submodules: recursivein the checkout action if recursive initialization is specifically needed:- - name: Init all submodules recursively - run: git submodule update --init --recursive -
151-152: Redundant submodule initialization.The checkout action at line 148 already has
submodules: true, making this explicit initialization redundant.Consider removing this step or use
submodules: recursivein the checkout action if recursive initialization is specifically needed:- - name: Init all submodules recursively - run: git submodule update --init --recursive -.github/workflows/build-mudlet.yml (1)
69-70: Redundant submodule initialization.The checkout action at line 66 already has
submodules: true, making this explicit initialization redundant.Consider removing this step or use
submodules: recursivein the checkout action if recursive initialization is specifically needed:- - name: Init all submodules recursively - run: git submodule update --init --recursive -.github/workflows/build-mudlet-win.yml (1)
35-36: Redundant submodule initialization.The checkout action at line 32 already has
submodules: true, making this explicit initialization redundant.Consider removing this step or use
submodules: recursivein the checkout action if recursive initialization is specifically needed:- - name: Init all submodules recursively - run: git submodule update --init --recursive -src/crash_reporter/CMakeLists.txt (1)
7-36: Avoid version duplication and makeEXE_MUDLET_TARGETusage more robust
APP_VERSIONis hard-coded to4.19.1here while the main project already carries the version elsewhere (qmakeVERSIONand top-level CMake). This will drift on the next release and desynchronize Sentry crash reports from the actual app version. Prefer wiring this from the top-level (e.g. via a cache variable,project(VERSION ...), or a generated header) instead of hard-coding it locally.
if(TARGET ${EXE_MUDLET_TARGET})assumesEXE_MUDLET_TARGETis always defined. If this file is ever reused without that variable set, CMake will seeif(TARGET )and error. A safer pattern is:if(DEFINED EXE_MUDLET_TARGET AND TARGET "${EXE_MUDLET_TARGET}") set_target_properties(MudletCrashReporter PROPERTIES RUNTIME_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:${EXE_MUDLET_TARGET}> ) endif()
- If you ever include this crash reporter subdirectory from the same CMake build that defines the
sentry_nativeExternalProject(inWithSentry.cmake), consider adding an explicit dependency so the Sentry libraries are guaranteed to exist before linking, e.g.:add_dependencies(MudletCrashReporter sentry_native)This avoids order-of-build surprises when building everything purely via CMake.
CI/send_debug_files_to_sentry.sh (1)
79-81: Remove unusedSCRIPT_DIRor put it to use
SCRIPT_DIRis computed but never referenced, which ShellCheck also flags (SC2034). Either drop the assignment or use it to e.g. resolve the script-relative path tosend_debug_files_to_sentry.shor other assets. Keeping unused locals around makes maintenance harder and can hide real issues in static-analysis noise.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (26)
.github/workflows/build-mudlet-win.yml(2 hunks).github/workflows/build-mudlet.yml(5 hunks).github/workflows/clangtidy-diff-analysis.yml(1 hunks).github/workflows/codeql-analysis.yml(1 hunks).github/workflows/performance-analysis.yml(1 hunks).github/workflows/update-3rdparty.yml(2 hunks).github/workflows/update-en-us-plural.yml(1 hunks).github/workflows/update-translations.yml(1 hunks).gitignore(1 hunks).gitmodules(1 hunks)3rdparty/sentry-native(1 hunks)CI/build-mudlet-for-windows.sh(1 hunks)CI/package-mudlet-for-windows.sh(1 hunks)CI/send_debug_files_to_sentry.sh(1 hunks)CI/setup-windows-sdk.sh(1 hunks)CMakeLists.txt(1 hunks)src/CMakeLists.txt(2 hunks)src/SentryWrapper.cpp(1 hunks)src/cmake/WithSentry.cmake(1 hunks)src/crash_reporter/CMakeLists.txt(1 hunks)src/crash_reporter/main.cpp(1 hunks)src/main.cpp(2 hunks)src/mudlet-lua/lua/DateTime.lua(2 hunks)src/mudlet-lua/lua/GUIUtils.lua(2 hunks)src/mudlet.pro(2 hunks)src/sentry_dsn.txt(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-14T14:16:57.626Z
Learnt from: vadi2
Repo: Mudlet/Mudlet PR: 8515
File: test/CMakeLists.txt:56-58
Timestamp: 2025-11-14T14:16:57.626Z
Learning: In the Mudlet Windows MSYS2 build environment, the Qt6Keychain package (mingw-w64-x86_64-qtkeychain-qt6) provides the CMake target named `qt6keychain` (lowercase, non-namespaced), not the standard `Qt6Keychain::Qt6Keychain` target. The test/CMakeLists.txt and src/CMakeLists.txt files correctly use `qt6keychain` for both USE_OWN_QTKEYCHAIN=ON and USE_OWN_QTKEYCHAIN=OFF cases.
Applied to files:
.gitmodulessrc/crash_reporter/CMakeLists.txtCI/package-mudlet-for-windows.sh
🧬 Code graph analysis (3)
src/mudlet-lua/lua/DateTime.lua (1)
src/mudlet-lua/lua/GUIUtils.lua (1)
rex_gsub_custom(2056-2079)
src/main.cpp (1)
src/SentryWrapper.cpp (2)
initSentry(41-59)initSentry(41-41)
src/mudlet-lua/lua/GUIUtils.lua (1)
src/mudlet-lua/lua/DateTime.lua (1)
rex_gsub_custom(50-73)
🪛 actionlint (1.7.8)
.github/workflows/build-mudlet.yml
205-205: shellcheck reported issue in this script: SC2086:info:1:27: Double quote to prevent globbing and word splitting
(shellcheck)
205-205: shellcheck reported issue in this script: SC2086:info:3:33: Double quote to prevent globbing and word splitting
(shellcheck)
205-205: shellcheck reported issue in this script: SC2086:info:5:33: Double quote to prevent globbing and word splitting
(shellcheck)
🪛 Shellcheck (0.11.0)
CI/send_debug_files_to_sentry.sh
[warning] 79-79: SCRIPT_DIR appears unused. Verify use (or export if used externally).
(SC2034)
🔇 Additional comments (18)
.gitignore (1)
14-14: Good addition.Adding
src/crash_reporter/build/follows the established pattern for ignoring build directories within the repository and appropriately excludes build artifacts from the new crash reporter component introduced in this PR.src/mudlet-lua/lua/GUIUtils.lua (1)
2084-2084: Verify the customrex_gsub_customproduces correct results with actual ANSI inputs.The custom implementation at lines 2056-2076 correctly handles the single capture group from
ansiPattern(which captures codes like "0;36;40"). However, no test coverage was found foransi2stringoransi2dechofunctions. Since this replaces the nativerex.gsubdue to crashes, manual verification with representative ANSI escape sequences is recommended to ensure correctness before merging.Also applies to: 2098-2098
src/mudlet-lua/lua/DateTime.lua (1)
93-93: Code implementation is correct; verify crash resolution and datetime functionality on all platforms.The
rex_gsub_customworkaround is properly implemented and correctly applied at line 93. The function properly usesrex.find()instead ofrex.gsub(), and no directrex.gsub()calls remain in DateTime.lua. The pattern"(%[A-Za-z])"correctly captures datetime directives, and the replacement function appropriately handles directive lookup viadatetime._directives.To ensure the fix fully addresses the issue:
- Verify the crash no longer occurs on Linux, macOS, and Windows
- Confirm datetime parsing works correctly with various format strings
- Consider adding test cases to prevent regressions
.gitmodules (1)
19-21: Submodule entry is well-formed and follows established patterns.The new sentry-native submodule entry is correctly formatted, consistent with existing submodule definitions, and references the official Sentry repository. The path placement in
3rdparty/aligns with the project's dependency organization.To ensure smooth integration, verify that all CI workflows and developer setup documentation include
git clone --recurse-submodulesor equivalent initialization to fetch this submodule. The PR objectives mention CI integration with submodule initialization—confirm that workflows like.github/workflows/build.ymlinclude the necessarygit submodule update --init --recursivesteps and that the Sentry DSN and auth token environment variables are properly configured downstream in build steps.3rdparty/sentry-native (1)
1-1: Submodule configuration verified as correct.All verification checks passed:
- ✓ .gitmodules: Properly configured with sentry-native pointing to
https://github.com/getsentry/sentry-native.git- ✓ CMake integration:
src/cmake/WithSentry.cmakecorrectly references3rdparty/sentry-nativeand usesExternalProject_Addfor building- ✓ CI submodule initialization: Both
build-mudlet.ymlandbuild-mudlet-win.ymlinitialize submodules viaactions/checkout@v5 with submodules: trueand explicitgit submodule update --init --recursivecommands- ✓ Build system configuration: Properly integrated and will build from the submodule
The submodule pointer update is correctly configured and will function as intended in CI/CD pipelines.
src/main.cpp (2)
60-60: LGTM: Forward declaration properly placed.The forward declaration of
initSentry()is correctly positioned with other forward declarations.
163-165: LGTM: Sentry initialization correctly placed early in main().The Sentry initialization is properly guarded by
#ifdef WITH_SENTRYand called very early inmain(), beforeQApplicationconstruction. This is the correct placement for crash reporting initialization, as it needs to be active before any potential crashes occur.src/CMakeLists.txt (2)
112-112: SentryWrapper.cpp verified successfully.The file exists at
src/SentryWrapper.cppand contains the completeinitSentry()function implementation with proper Sentry initialization logic, conditional compilation guards, and helper utilities for platform-specific paths.
701-705: The review comment is incorrect. The Sentry options are properly declared in the root CMakeLists.txt.The
WITH_SENTRYandSENTRY_SEND_DEBUGoptions are correctly declared atCMakeLists.txt:81-82(not insrc/CMakeLists.txt). This is the proper CMake pattern—options are declared in the rootCMakeLists.txtand inherited by subdirectories. The code atsrc/CMakeLists.txt:701correctly usesWITH_SENTRYas a CMake variable without needing to declare it again.However, a real issue exists: the code at line 702 includes
cmake/WithSentry.cmake, but this file does not exist in the repository.Likely an incorrect or invalid review comment.
CI/setup-windows-sdk.sh (1)
128-132: Based on verification results, I can now provide the rewritten review comment:
Remove duplicate cmake package; verify lld and uasm necessity.
Line 132 adds
mingw-w64-${BUILDCOMPONENT}-cmake, but this package is already listed on line 124, creating a redundant specification.Additionally,
mingw-w64-${BUILDCOMPONENT}-lldandmingw-w64-${BUILDCOMPONENT}-uasmshow no direct usage in the codebase (not found in Sentry build files or CMake configuration). Whilecurlandclangare confirmed necessary for Sentry integration, verify thatlldanduasmare required as transitive dependencies or general MinGW toolchain components before including them.Apply this diff to remove the duplicate:
"mingw-w64-${BUILDCOMPONENT}-curl" \ "mingw-w64-${BUILDCOMPONENT}-uasm" \ "mingw-w64-${BUILDCOMPONENT}-clang" \ - "mingw-w64-${BUILDCOMPONENT}-lld" \ - "mingw-w64-${BUILDCOMPONENT}-cmake"; then + "mingw-w64-${BUILDCOMPONENT}-lld"; then break fiCMakeLists.txt (1)
81-82: LGTM! Clean CMake option declarations.The two new options for Sentry integration are well-named and appropriately defaulted to OFF, allowing opt-in behavior.
CI/build-mudlet-for-windows.sh (1)
148-154: LGTM! Conditional Sentry flag injection is correct.The conditional logic properly appends Sentry-related CMake arguments to CMAKE_ARGS when the environment variables are set.
.github/workflows/build-mudlet.yml (2)
160-160: LGTM! Appropriate dependencies for Sentry integration.The addition of libcurl4-openssl-dev, libssl-dev, openssl, and ca-certificates is necessary for Sentry's HTTP transport functionality.
Also applies to: 174-176
258-259: LGTM! Sentry CMake flags properly configured.The Sentry flags are correctly passed to CMake, and SENTRY_AUTH_TOKEN is properly exposed for authenticated operations during the build.
Also applies to: 262-262
.github/workflows/build-mudlet-win.yml (2)
80-80: LGTM! SENTRY_AUTH_TOKEN properly exposed.The authentication token is correctly passed to the build environment for Sentry operations.
45-55: Quote variable to prevent word splitting.The shell script uses an unquoted variable that should be quoted.
Apply this diff:
run: | echo "WITH_SENTRY=yes" >> $GITHUB_ENV - if [ -n "$SENTRY_SEND_DEBUG_SECRET" ]; then + if [ -n "${SENTRY_SEND_DEBUG_SECRET}" ]; then echo "SENTRY_SEND_DEBUG=1" >> $GITHUB_ENV else echo "SENTRY_SEND_DEBUG=0" >> $GITHUB_ENVLikely an incorrect or invalid review comment.
src/crash_reporter/main.cpp (1)
57-57: SENTRY_DSN is properly defined via CMake configuration.Verification confirms that
SENTRY_DSNis correctly configured as a compile-time flag. The build system reads the DSN fromsrc/sentry_dsn.txtand passes it as-DSENTRY_DSN=...to the compiler viatarget_compile_definitions()insrc/crash_reporter/CMakeLists.txt(line 30) andsrc/cmake/WithSentry.cmake.src/mudlet.pro (1)
616-674: Fix platform-specific code in qmakeWITH_SENTRYblock and avoid baking build-tree paths into binaries
WITH_SENTRYblock lacks Windows-only guards; will fail on Linux/macOSThe qmake
WITH_SENTRY { ... }block (line 616) contains Windows-specific code without platform guards:
- Line 648:
-lwinhttp -ldbghelp -lversionare linked unconditionally- Lines 656, 670, 673: Post-link commands reference
mudlet.exeunconditionally- Line 673:
strip --strip-debug $$APP_DIR_PATH/mudlet.exewill fail ifmudlet.exedoesn't existThe CMake build (
src/cmake/WithSentry.cmake) correctly guards these withif(WIN32),if(APPLE), andif(UNIX)blocks, but the qmake build does not. Wrap Windows-specific code:win32:WITH_SENTRY { # current content }or move cross-platform logic to CMake only and disable qmake+Sentry on non-Windows.
- Compile-time
APP_DIR_PATHfrom build tree breaks post-install relocation
APP_DIR_PATH = $$OUT_PWD/$$BUILD_SUBDIR(line 629) is compiled into the binary viaDEFINES. Once Mudlet is packaged and installed elsewhere, this path no longer exists.SentryWrapper.cpplines 53–54 rely on this hardcoded path to locatecrashpad_handlerandMudletCrashReporterat runtime, so the app will crash if binaries are moved.Replace with
QCoreApplication::applicationDirPath()at runtime instead of hardcoding. This also eliminates duplication between qmake and CMake (which definesAPP_DIR_PATH="${CMAKE_BINARY_DIR}/src"separately).
- DSN and toolchain assumptions differ between qmake and CMake
- qmake line 626 reads
SENTRY_DSN = $$system(cat $$PWD/sentry_dsn.txt)without trimming; ifsentry_dsn.txthas a trailing newline, the macro will include it. CMake correctly usesstring(STRIP ...)to remove whitespace.- Both qmake and CMake force
-DCMAKE_C_COMPILER=clangand-DCMAKE_CXX_COMPILER=clang++unconditionally. On systems with no clang or when the main build uses GCC, this can fail or cause mixed-toolchain linking issues. Let CMake detect or inherit the compiler from the main build.
SentryWrapper.cppinclusion is properly guardedFile correctly uses
#ifdef WITH_SENTRY(lines 21–23, 45–57), so unconditional inclusion inSOURCESis safe.
src/mudlet-lua/lua/GUIUtils.lua
Outdated
| local function rex_gsub_custom(str, pattern, repl) | ||
| local out = {} | ||
| local last_end = 1 | ||
|
|
||
| while true do | ||
| local start_pos, end_pos, cap = rex.find(str, pattern, last_end) | ||
| if not start_pos then | ||
| table.insert(out, str:sub(last_end)) | ||
| break | ||
| end | ||
|
|
||
| table.insert(out, str:sub(last_end, start_pos - 1)) | ||
|
|
||
| if type(repl) == "function" then | ||
| table.insert(out, repl(cap)) | ||
| else | ||
| table.insert(out, repl) | ||
| end | ||
|
|
||
| last_end = end_pos + 1 | ||
| end | ||
|
|
||
| return table.concat(out) | ||
| end |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Extract duplicated rex_gsub_custom to a shared utility module.
This function is identical to the one in DateTime.lua (lines 49-72). Code duplication increases maintenance burden—if a bug is found or enhancement is needed, both copies must be updated.
Consider extracting this to a shared utility module (e.g., LuaGlobal.lua or a new StringUtils.lua) and importing it in both files.
-- In a shared utility module:
function rex_gsub_custom(str, pattern, repl)
local out = {}
local last_end = 1
while true do
local start_pos, end_pos, cap = rex.find(str, pattern, last_end)
if not start_pos then
table.insert(out, str:sub(last_end))
break
end
table.insert(out, str:sub(last_end, start_pos - 1))
if type(repl) == "function" then
table.insert(out, repl(cap))
else
table.insert(out, repl)
end
last_end = end_pos + 1
end
return table.concat(out)
end🤖 Prompt for AI Agents
In src/mudlet-lua/lua/GUIUtils.lua around lines 2056 to 2079, the
rex_gsub_custom implementation is duplicated from DateTime.lua; extract this
function into a shared utility module (e.g., src/mudlet-lua/lua/StringUtils.lua
or LuaGlobal.lua) that returns/exports rex_gsub_custom, replace the local
definition in GUIUtils.lua with a require(...) import and call the imported
function, remove the duplicate from DateTime.lua and update it to require the
same shared module, ensure the new module uses the same function signature,
update any local references if needed, and run the project/tests to confirm no
breakages.
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (4)
src/cmake/WithSentry.cmake (4)
11-12: This issue was previously flagged: Remove hard-coded toolchain and generator.As noted in the previous review, forcing clang/clang++ and Ninja (lines 11-12, 16) breaks builds on systems where these tools are unavailable or when the main project uses a different toolchain (MSVC, GCC). The ExternalProject should inherit the parent's toolchain and generator.
Also applies to: 16-16
66-66: This issue was previously flagged: Remove APP_DIR_PATH compile definition.As noted in the previous review,
APP_DIR_PATH="${CMAKE_BINARY_DIR}/src"(lines 66, 72) bakes a build-time path into the binary that won't exist after installation. The runtime code should useQCoreApplication::applicationDirPath()instead.Also applies to: 72-72
92-92: This issue was previously flagged: Unconditional curl linking will fail on Windows.As noted in the previous review, curl is linked unconditionally (line 92) but
SENTRY_TRANSPORT=curlis only set forUNIX AND NOT APPLE(line 20). On Windows or systems without libcurl, this will cause link failures. Either guard the curl link withUNIX AND NOT APPLEor verify that sentry-native provides it.
138-138: This issue was previously flagged: bash dependency breaks Windows builds.As noted in the previous review, the bash command (line 138) will fail on Windows systems without bash. If this feature is CI-only, document it; otherwise, guard it with
UNIXor provide a portable wrapper.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/cmake/WithSentry.cmake(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: ubuntu / clang
- GitHub Check: ubuntu / gcc / lua tests
- GitHub Check: ubuntu (x86_64)
- GitHub Check: macos (arm64) / c++, lua tests
- GitHub Check: macos (x86_64) / c++, lua tests
- GitHub Check: windows64
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
src/crash_reporter/main.cpp (1)
24-28: Avoid private Sentry headers/transport internals and add proper error handling & cleanup.This function still relies on Sentry’s internal transport details and lacks basic error handling/cleanup:
- Lines 24–28: Including
"sentry_options.h"and"sentry_transport.h"exposes you to internal, unstable APIs. The public integration should only need"sentry.h".- Lines 52–63:
opts->transportand thesentry__transport_*calls are private/internal APIs; they depend on the layout ofsentry_options_tand can break with Sentry upgrades. There’s also:
- No check that the envelope file exists or is readable before calling
sentry_envelope_read_from_file.- No logging on failure.
- No
sentry_options_freeorsentry_envelope_freeon any path (including theif (!opts || !envelope)early return), leaking resources.Refactor this to use only the documented public API and clean up resources, e.g.:
-#include "sentry.h" -#include "sentry_options.h" -extern "C" { - #include "sentry_transport.h" -} +#include "sentry.h" @@ void sendCrashReport(const char *envelopePath) { - sentry_options_t * opts = sentry_options_new(); - sentry_envelope_t * envelope = sentry_envelope_read_from_file(envelopePath); - - if (!opts || !envelope) { - return; - } - sentry_options_set_dsn(opts, SENTRY_DSN); - sentry__transport_startup(opts->transport, opts); - sentry__transport_send_envelope(opts->transport, envelope); - sentry__transport_shutdown(opts->transport, 30 * 1000); + QFileInfo fileInfo(envelopePath); + if (!fileInfo.exists() || !fileInfo.isReadable()) { + qWarning() << "Envelope file does not exist or is not readable:" << envelopePath; + return; + } + + sentry_options_t *opts = sentry_options_new(); + if (!opts) { + qWarning() << "Failed to create Sentry options"; + return; + } + + sentry_envelope_t *envelope = sentry_envelope_read_from_file(envelopePath); + if (!envelope) { + qWarning() << "Failed to read envelope from file:" << envelopePath; + sentry_options_free(opts); + return; + } + + sentry_options_set_dsn(opts, SENTRY_DSN); + + // Use public API: initialize, capture the envelope, then shut down. + if (sentry_init(opts) == 0) { + sentry_capture_envelope(envelope); // Sentry now owns the envelope. + sentry_close(); + } else { + qWarning() << "Failed to initialize Sentry"; + sentry_envelope_free(envelope); + sentry_options_free(opts); + } }Note: Adjust the exact calls if your
sentry-nativeversion differs, but the key points are:
- Drop the private headers and
sentry__transport_*usage.- Use
sentry_init/sentry_capture_envelope/sentry_closeas the public flow.- Ensure every allocation (
opts,envelope) is freed on failure paths.Also applies to: 52-63
🧹 Nitpick comments (3)
src/SentryWrapper.h (1)
1-8: Add header guard / pragma once and fix minor header hygiene (optional).This header is small but should still follow typical header hygiene: add an include guard or
#pragma once, and ensure there is a newline at EOF. If the project expects a GPL copyright header on all public headers (as insrc/crash_reporter/main.cpp), consider adding the standard license block here for consistency.src/mudlet-lua/lua/StringUtils.lua (2)
224-224: Potential infinite loop risk with zero-width matches.While advancing by
end_pos + 1(line 235) generally prevents infinite loops, ifrex.findreturnsstart_pos == end_posfor a zero-width match at the end of the string, the next iteration will start beyond the string length. Consider adding a safeguard to detect whenstart_pos == end_pos == #strto explicitly break.Apply this diff to add a safeguard:
local start_pos, end_pos, cap = rex.find(str, pattern, last_end) - if not start_pos then + if not start_pos or (start_pos == end_pos and end_pos == #str) then table.insert(out, str:sub(last_end)) break end
219-220: Add documentation for the new global function.Since
rex_gsub_customis now part of the public API used across multiple modules, it should have documentation similar to other functions in this file. Include the purpose, parameters, return value, and any known limitations (e.g., multiple captures, return value compatibility).
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (16)
.github/workflows/build-mudlet-win.yml(3 hunks).github/workflows/build-mudlet.yml(5 hunks).github/workflows/clangtidy-diff-analysis.yml(1 hunks).github/workflows/codeql-analysis.yml(1 hunks).github/workflows/performance-analysis.yml(1 hunks).github/workflows/update-3rdparty.yml(2 hunks).github/workflows/update-en-us-plural.yml(1 hunks).github/workflows/update-translations.yml(1 hunks)src/CMakeLists.txt(3 hunks)src/SentryWrapper.cpp(1 hunks)src/SentryWrapper.h(1 hunks)src/crash_reporter/main.cpp(1 hunks)src/main.cpp(2 hunks)src/mudlet-lua/lua/DateTime.lua(2 hunks)src/mudlet-lua/lua/GUIUtils.lua(2 hunks)src/mudlet-lua/lua/StringUtils.lua(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (11)
- .github/workflows/clangtidy-diff-analysis.yml
- src/CMakeLists.txt
- src/mudlet-lua/lua/GUIUtils.lua
- src/SentryWrapper.cpp
- .github/workflows/update-3rdparty.yml
- src/mudlet-lua/lua/DateTime.lua
- .github/workflows/codeql-analysis.yml
- .github/workflows/build-mudlet.yml
- .github/workflows/performance-analysis.yml
- .github/workflows/update-en-us-plural.yml
- src/main.cpp
🧰 Additional context used
🧬 Code graph analysis (1)
src/SentryWrapper.h (1)
src/SentryWrapper.cpp (4)
makeExecutablePath(58-64)makeExecutablePath(58-58)initSentry(39-56)initSentry(39-39)
🪛 GitHub Check: CodeFactor
src/SentryWrapper.h
[notice] 8-8: src/SentryWrapper.h#L8
Could not find a newline character at the end of the file. (whitespace/ending_newline)
[notice] 1-1: src/SentryWrapper.h#L1
No copyright message found. You should have a line: "Copyright [year] ". (legal/copyright)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: windows64
- GitHub Check: ubuntu / gcc / lua tests
- GitHub Check: macos (x86_64) / c++, lua tests
- GitHub Check: macos (arm64) / c++, lua tests
- GitHub Check: ubuntu (x86_64)
- GitHub Check: ubuntu / clang
🔇 Additional comments (4)
src/mudlet-lua/lua/StringUtils.lua (1)
218-238: Let me search for more context about the rex.gsub crash:No critical issues found. The implementation is correct for actual usage patterns.
The script output reveals that the original review comment's concerns about API incompatibility do not reflect actual usage:
Multiple captures: All patterns in the codebase have exactly ONE capture group:
- DateTime.lua uses
(%[A-Za-z])with one capture- GUIUtils.lua uses
\\e\\[([0-9:;]*?)mwith one capture- The function correctly handles this case
Return value incompatibility: No callers expect a count return value; all assign the result to a single variable
Root cause: GUIUtils.lua confirms "rex.gsub was crashing", indicating a legitimate issue with the rex library itself. Implementing a workaround is appropriate for library crashes.
The custom implementation is fit for purpose in this codebase, though it remains less general than
rex.gsub(e.g., only handles single captures). For the current usage patterns, this is not a concern..github/workflows/update-translations.yml (1)
17-22: Submodule initialization strategy is consistent across workflows.The change from
submodules: truetosubmodules: recursivealigns with the PR's broader approach to initializing the newsentry-nativegit submodule across all CI workflows..github/workflows/build-mudlet-win.yml (2)
42-52: Sentry enablement step is well-designed and follows PR guidance.The conditional logic for
SENTRY_SEND_DEBUGcorrectly gates debug symbol uploads behind secret presence, aligning with the PR objective: "set secrets.SENTRY_SEND_DEBUG=1 to allow CI to upload debug symbol files."
70-78: Verify downstream build script handles Sentry environment variables correctly.The
SENTRY_AUTH_TOKEN,WITH_SENTRY, andSENTRY_SEND_DEBUGenvironment variables are now passed to the build step. EnsureCI/build-mudlet-for-windows.shcorrectly:
- Receives and passes these variables to CMake
- Handles the case where
SENTRY_AUTH_TOKENmay be empty (if the secret is not set)- Properly configures debug symbol upload when
SENTRY_SEND_DEBUG=1
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
src/SentryWrapper.cpp (1)
39-42: Cache path doc vs actualQStandardPathslayoutThe comment (Lines 39–42) documents cache paths like
~/.cache/mudlet/sentry, butQStandardPaths::CacheLocationis already app‑specific. Appending"/mudlet/sentry"on Line 49 can easily yield something like~/.cache/mudlet/mudlet/sentry(or~/.cache/Mudlet/mudlet/sentry), which diverges from what’s documented.To align behavior with the comment, either:
- Base this on
GenericCacheLocationand append"mudlet/sentry", or- Append only
"/sentry"toCacheLocationand update the comment accordingly.Also applies to: 49-49
🧹 Nitpick comments (4)
src/SentryWrapper.h (2)
23-26: Avoid pulling Sentry/Qt internals into this public headerThe header doesn’t use
qScopeGuardor any Sentry types; only the implementation inSentryWrapper.cppneeds them. Including<QtCore/qscopeguard.h>and"sentry.h"here increases coupling and rebuild surface for every includer. Consider moving these includes intoSentryWrapper.cppand keeping the header limited to<string>and forward declarations.
34-34: Add trailing newline to satisfy lintersCodeFactor is flagging the missing newline at end of file. Adding a final newline after Line 34 will silence the warning and follow the usual POSIX text‑file convention.
src/SentryWrapper.cpp (2)
44-62: Wiresentry_close()to application shutdown rather than never calling it
initSentry()now initializes Sentry and leaves it running for the process lifetime, which is much better than the previous immediatesentry_close(). However, there is currently no shutdown at all, so queued events may not be flushed on clean exit and SDK resources are never released.Consider:
- Ensuring
initSentry()is only called once (e.g., with a staticbool initializedguard), and- Registering a single
sentry_close()at application shutdown (e.g., via a staticqScopeGuard,std::atexit, or aQCoreApplication::aboutToQuithandler).This keeps crash reporting active while still following sentry‑native’s recommended init/close lifecycle.
91-91: Add trailing newline to satisfy lintersSimilar to the header, CodeFactor is reporting a missing newline at end of file. Adding a final newline after Line 91 will clear the warning.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
.github/workflows/performance-analysis.yml(1 hunks)src/SentryWrapper.cpp(1 hunks)src/SentryWrapper.h(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/SentryWrapper.h (1)
src/SentryWrapper.cpp (6)
initSentry(44-62)initSentry(44-44)makeExecutablePath(64-71)makeExecutablePath(64-64)getExeDir(73-91)getExeDir(73-73)
🪛 GitHub Check: CodeFactor
src/SentryWrapper.cpp
[notice] 91-91: src/SentryWrapper.cpp#L91
Could not find a newline character at the end of the file. (whitespace/ending_newline)
[failure] 86-86: src/SentryWrapper.cpp#L86
Possible race condition (CWE-362, CWE-20) (flawfinder7-readlink)
src/SentryWrapper.h
[notice] 34-34: src/SentryWrapper.h#L34
Could not find a newline character at the end of the file. (whitespace/ending_newline)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: windows64
- GitHub Check: macos (arm64) / c++, lua tests
- GitHub Check: ubuntu / clang
- GitHub Check: ubuntu / gcc / lua tests
- GitHub Check: macos (x86_64) / c++, lua tests
- GitHub Check: ubuntu (x86_64)
🔇 Additional comments (2)
.github/workflows/performance-analysis.yml (1)
24-28: The build is compatible with recursive submodule initialization.Verification confirms:
- WITH_SENTRY defaults to OFF
- crash_reporter (which requires sentry-native) is only added to the build when WITH_SENTRY=ON, and this is already guarded in src/CMakeLists.txt
- Since the performance-analysis workflow does not set WITH_SENTRY, the build will succeed without attempting to use the sentry-native submodule
- The submodule will be fetched recursively but remain unused—slightly inefficient but not a correctness issue
The change to
submodules: recursiveis safe.src/SentryWrapper.cpp (1)
64-71:makeExecutablePathhelper looks goodThe platform split here (adding
.exeonly on Windows) is straightforward and appropriate; no issues spotted with this helper.
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
src/SentryWrapper.cpp (1)
54-54: Remove redundant "mudlet" subdirectory nesting in cache path.
QStandardPaths::CacheLocationis application-specific and already includes the app name in the path. Mudlet setssetApplicationName("Mudlet")andsetOrganizationName("Mudlet"), so CacheLocation on Linux resolves to~/.cache/mudlet. Appending/mudlet/sentrycreates redundant nesting:~/.cache/mudlet/mudlet/sentry.Other cache usages in the codebase—
dlgProfilePreferences.cpp:3496andTMedia.cpp:904—use CacheLocation directly without adding/mudlet. Align with this pattern:- QString path = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/mudlet/sentry"; + QString path = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/sentry";
🧹 Nitpick comments (3)
src/SentryWrapper.h (1)
23-26: Remove unusedqscopeguard.hinclude.The
#include <QtCore/qscopeguard.h>is no longer needed. The original implementation usedqScopeGuardto callsentry_close(), but that code was removed per previous review feedback. Sinceqscopeguard.hserves no purpose now, remove it to reduce unnecessary dependencies.Apply this diff:
#ifdef WITH_SENTRY - #include <QtCore/qscopeguard.h> #include "sentry.h" #endifsrc/SentryWrapper.cpp (2)
53-53: Consider using Qt'sapplicationDirPath()for simplicity and consistency.The current
getExeDir()implementation works correctly across platforms, but the codebase already usesQCoreApplication::applicationDirPath()extensively elsewhere. Using Qt's API here would:
- Reduce platform-specific code
- Improve maintainability
- Align with established patterns in the codebase
Apply this diff:
- std::string runtimeAppDir = getExeDir(); + std::string runtimeAppDir = QCoreApplication::applicationDirPath().toStdString();If you adopt this, you could also simplify or remove the
getExeDir()function if it's not needed elsewhere. Note thatinitSentry()must be called after theQCoreApplicationinstance is created inmain().Also applies to: 62-63
78-114: Consider caching the executable directory for better performance.The function is thread-safe, but it recomputes the executable path on every call. Since this path doesn't change during process lifetime, you could cache it:
std::string getExeDir() { - static std::mutex mtx; - std::lock_guard<std::mutex> lock(mtx); + static std::once_flag flag; + static std::string cachedDir; + + std::call_once(flag, []() { #if defined(_WIN32) || defined(_WIN64) char path[MAX_PATH]; GetModuleFileNameA(NULL, path, MAX_PATH); std::string exePath(path); size_t pos = exePath.find_last_of("\\/"); - std::string dir = exePath.substr(0, pos); - std::replace(dir.begin(), dir.end(), '\\', '/'); - - return dir; + cachedDir = exePath.substr(0, pos); + std::replace(cachedDir.begin(), cachedDir.end(), '\\', '/'); #elif defined(__APPLE__) char path[PATH_MAX]; uint32_t size = sizeof(path); if (_NSGetExecutablePath(path, &size) != 0) { - return "."; + cachedDir = "."; + return; } std::string exePath(path); size_t pos = exePath.find_last_of("/"); if (pos == std::string::npos) { - return exePath; + cachedDir = exePath; + return; } - return exePath.substr(0, pos); + cachedDir = exePath.substr(0, pos); #else char result[PATH_MAX]; ssize_t count = readlink("/proc/self/exe", result, PATH_MAX); if (count <= 0) { - return std::string("."); + cachedDir = "."; + return; } std::string exePath(result, count); size_t pos = exePath.find_last_of("/"); - return exePath.substr(0, pos); + cachedDir = exePath.substr(0, pos); #endif + }); + + return cachedDir; }Note: The static analysis warning about a race condition at line 106 (
readlink("/proc/self/exe")) is a false positive—reading/proc/self/exeis safe and has no time-of-check-to-time-of-use issue.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/SentryWrapper.cpp(1 hunks)src/SentryWrapper.h(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/SentryWrapper.h (1)
src/SentryWrapper.cpp (6)
initSentry(49-67)initSentry(49-49)makeExecutablePath(69-76)makeExecutablePath(69-69)getExeDir(78-114)getExeDir(78-78)
🪛 GitHub Check: CodeFactor
src/SentryWrapper.cpp
[failure] 86-86: src/SentryWrapper.cpp#L86
Possible race condition (CWE-362, CWE-20) (flawfinder7-readlink)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: windows64
- GitHub Check: macos (x86_64) / c++, lua tests
- GitHub Check: macos (arm64) / c++, lua tests
- GitHub Check: ubuntu / gcc / lua tests
- GitHub Check: ubuntu (x86_64)
- GitHub Check: ubuntu / clang
🔇 Additional comments (1)
src/SentryWrapper.cpp (1)
69-76: LGTM!The platform-specific executable path construction is correct and straightforward.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/SentryWrapper.cpp (1)
78-82: Consider whether the mutex is necessaryThe mutex protects
getExeDir()for thread safety, but the executable path is constant throughout the process lifetime and the platform APIs used are thread-safe for reads. Even if multiple threads call simultaneously, they'd compute the same result and return by value (no shared mutable state).The mutex adds overhead (minimal, but measureable if called frequently), though it provides defensive safety. If
getExeDir()is only called once at startup viainitSentry(), the mutex is harmless but not strictly necessary.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/SentryWrapper.cpp(1 hunks)src/TBuffer.cpp(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: windows64
- GitHub Check: macos (arm64) / c++, lua tests
- GitHub Check: macos (x86_64) / c++, lua tests
- GitHub Check: ubuntu / clang
- GitHub Check: ubuntu / gcc / lua tests
- GitHub Check: ubuntu (x86_64)
🔇 Additional comments (1)
src/SentryWrapper.cpp (1)
54-65: Remove invalid dangling pointer concern at line 60; verify string handling at lines 62-63 and error handling at line 65The web search confirmed that the Sentry C SDK's sentry_options_set_database_path copies the string into the options (not merely storing your pointer), making line 60 safe. However, two other concerns warrant manual verification:
Lines 62-63: Verify string copying for handler and reporter paths
The Sentry documentation does not explicitly confirm whether
sentry_options_set_handler_pathandsentry_options_set_external_crash_reporter_pathcopy strings or store pointers. To be safe, consider storing the temporarystd::stringresults before passing them:const std::string handlerPath = makeExecutablePath(runtimeAppDir, "crashpad_handler"); const std::string reporterPath = makeExecutablePath(runtimeAppDir, "MudletCrashReporter"); sentry_options_set_handler_path(options, handlerPath.c_str()); sentry_options_set_external_crash_reporter_path(options, reporterPath.c_str());Line 65: Consider error handling for sentry_init()
While the official Sentry examples show
sentry_init(options)called without error checking, the function's return value semantics are undocumented. You may optionally check for errors:if (sentry_init(options) != 0) { // Handle initialization failure }
|
@NicolasKeita feel free to stop when you feel coderabbit comments are enough, your call |
|
@vadi2 I’ve just finished reviewing all of the CodeRabbit comments. The PR should now be in good shape. I had actually missed one thing initially, so codeRabbit was helpful :) |
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (1)
src/mudlet.pro (1)
658-659: Add error handling for crash_reporter build.The cmake commands to configure and build crash_reporter lack error checking. If these commands fail, the build continues silently, potentially leading to runtime issues.
Add error checking similar to the pattern used elsewhere in qmake:
- system(cmake -S $$PWD/crash_reporter/ -B $$PWD/crash_reporter/build/ -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=$$APP_DIR_PATH/) - system(cmake --build $$PWD/crash_reporter/build/) + !system(cmake -S $$PWD/crash_reporter/ -B $$PWD/crash_reporter/build/ -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=$$APP_DIR_PATH/) { + error("Failed to configure crash_reporter with CMake") + } + !system(cmake --build $$PWD/crash_reporter/build/) { + error("Failed to build crash_reporter") + }Apply the same pattern to the sentry-native build commands at lines 637-639.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/mudlet.pro(2 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: NicolasKeita
Repo: Mudlet/Mudlet PR: 8540
File: CI/package-mudlet-for-windows.sh:111-113
Timestamp: 2025-11-18T19:24:57.339Z
Learning: In CI/package-mudlet-for-windows.sh for the Mudlet project, when WITH_SENTRY is enabled, the Sentry binaries (crashpad_handler.exe and crashpad_wer.dll) are mandatory and the script should fail with an error if they are missing, rather than continuing with a warning.
📚 Learning: 2025-11-18T19:24:57.339Z
Learnt from: NicolasKeita
Repo: Mudlet/Mudlet PR: 8540
File: CI/package-mudlet-for-windows.sh:111-113
Timestamp: 2025-11-18T19:24:57.339Z
Learning: In CI/package-mudlet-for-windows.sh for the Mudlet project, when WITH_SENTRY is enabled, the Sentry binaries (crashpad_handler.exe and crashpad_wer.dll) are mandatory and the script should fail with an error if they are missing, rather than continuing with a warning.
Applied to files:
src/mudlet.pro
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: windows64
- GitHub Check: ubuntu (x86_64)
- GitHub Check: ubuntu / gcc / lua tests
- GitHub Check: macos (x86_64) / c++, lua tests
- GitHub Check: ubuntu / clang
- GitHub Check: macos (arm64) / c++, lua tests
| !exists($$SENTRY_PATH/install) { | ||
| message("Sentry install missing, building sentry-native from sources") | ||
|
|
||
| system(cmake -S $$SENTRY_PATH -B $$SENTRY_PATH/build -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DSENTRY_BACKEND=crashpad -D SENTRY_BUILD_SHARED_LIBS=OFF --log-level=ERROR) | ||
| system(cmake --build $$SENTRY_PATH/build --parallel) | ||
| system(cmake --install $$SENTRY_PATH/build --prefix $$SENTRY_PATH/install) | ||
| } |
There was a problem hiding this comment.
Major: Missing git submodule initialization for sentry-native.
The code checks if $$SENTRY_PATH/install exists and attempts to build sentry-native if missing, but there's no check or initialization of the git submodule itself (unlike other dependencies).
Other dependencies in this file (edbee-lib, lcf, qtkeychain) properly check for submodule presence and initialize them if needed (see lines 520-569). According to the PR objectives, sentry-native is added as a git submodule.
Add submodule initialization before the install check, following the pattern used for other dependencies:
SENTRY_PATH = $$PWD/../3rdparty/sentry-native
+
+ win32 {
+ !exists("$${PWD}/../3rdparty/sentry-native/CMakeLists.txt") {
+ message("git submodule for required sentry-native source code missing, executing 'git submodule update --init' to get it...")
+ system("cd $${PWD}\.. & git submodule update --init 3rdparty/sentry-native")
+ }
+ } else {
+ !exists("$${PWD}/../3rdparty/sentry-native/CMakeLists.txt") {
+ message("git submodule for required sentry-native source code missing, executing 'git submodule update --init' to get it...")
+ system("cd $${PWD}/.. ; git submodule update --init 3rdparty/sentry-native")
+ }
+ }
!exists($$SENTRY_PATH/install) {
message("Sentry install missing, building sentry-native from sources")📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| !exists($$SENTRY_PATH/install) { | |
| message("Sentry install missing, building sentry-native from sources") | |
| system(cmake -S $$SENTRY_PATH -B $$SENTRY_PATH/build -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DSENTRY_BACKEND=crashpad -D SENTRY_BUILD_SHARED_LIBS=OFF --log-level=ERROR) | |
| system(cmake --build $$SENTRY_PATH/build --parallel) | |
| system(cmake --install $$SENTRY_PATH/build --prefix $$SENTRY_PATH/install) | |
| } | |
| SENTRY_PATH = $$PWD/../3rdparty/sentry-native | |
| win32 { | |
| !exists("$${PWD}/../3rdparty/sentry-native/CMakeLists.txt") { | |
| message("git submodule for required sentry-native source code missing, executing 'git submodule update --init' to get it...") | |
| system("cd $${PWD}\.. & git submodule update --init 3rdparty/sentry-native") | |
| } | |
| } else { | |
| !exists("$${PWD}/../3rdparty/sentry-native/CMakeLists.txt") { | |
| message("git submodule for required sentry-native source code missing, executing 'git submodule update --init' to get it...") | |
| system("cd $${PWD}/.. ; git submodule update --init 3rdparty/sentry-native") | |
| } | |
| } | |
| !exists($$SENTRY_PATH/install) { | |
| message("Sentry install missing, building sentry-native from sources") | |
| system(cmake -S $$SENTRY_PATH -B $$SENTRY_PATH/build -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DSENTRY_BACKEND=crashpad -D SENTRY_BUILD_SHARED_LIBS=OFF --log-level=ERROR) | |
| system(cmake --build $$SENTRY_PATH/build --parallel) | |
| system(cmake --install $$SENTRY_PATH/build --prefix $$SENTRY_PATH/install) | |
| } |
🤖 Prompt for AI Agents
In src/mudlet.pro around lines 634 to 640, the sentry-native submodule is never
initialized before attempting to build/install; add a submodule initialization
step (following the pattern used for edbee-lib/lcf/qtkeychain) that checks for
the submodule (e.g., test for $$SENTRY_PATH/.git or existence) and runs git
submodule update --init --recursive for $$SENTRY_PATH when missing, then proceed
with the existing install/build check and commands.
There was a problem hiding this comment.
This is still unresolved. (But like the prior issue I am looking at it right now as I try to get development branch code buildable in my development environment - currently Windows but am thinking about other OSes as well).
| !exists($$SENTRY_PATH/install) { | ||
| message("Sentry install missing, building sentry-native from sources") | ||
|
|
||
| system(cmake -S $$SENTRY_PATH -B $$SENTRY_PATH/build -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DSENTRY_BACKEND=crashpad -D SENTRY_BUILD_SHARED_LIBS=OFF --log-level=ERROR) |
There was a problem hiding this comment.
Major: CMake configuration errors.
This line has two issues:
-
Syntax error: There's a space in
-D SENTRY_BUILD_SHARED_LIBS=OFFwhich should be-DSENTRY_BUILD_SHARED_LIBS=OFF. -
Incorrect compiler override: Hardcoding
-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++conflicts with the MinGW/MSYS2 environment indicated by the rest of this file (seeMINGW_BASE_DIRusage at lines 415-452). This will fail when the specified compilers are not available or incompatible.
Apply this fix:
- system(cmake -S $$SENTRY_PATH -B $$SENTRY_PATH/build -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DSENTRY_BACKEND=crashpad -D SENTRY_BUILD_SHARED_LIBS=OFF --log-level=ERROR)
+ system(cmake -S $$SENTRY_PATH -B $$SENTRY_PATH/build -DSENTRY_BACKEND=crashpad -DSENTRY_BUILD_SHARED_LIBS=OFF --log-level=ERROR)Let CMake use the system's default compiler chain (which qmake is already using for the main build) rather than forcing a specific one. If you need to override the compiler, it should match the platform and the compiler used by the parent qmake build.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| system(cmake -S $$SENTRY_PATH -B $$SENTRY_PATH/build -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DSENTRY_BACKEND=crashpad -D SENTRY_BUILD_SHARED_LIBS=OFF --log-level=ERROR) | |
| system(cmake -S $$SENTRY_PATH -B $$SENTRY_PATH/build -DSENTRY_BACKEND=crashpad -DSENTRY_BUILD_SHARED_LIBS=OFF --log-level=ERROR) |
🤖 Prompt for AI Agents
In src/mudlet.pro around line 637, the cmake invocation has two problems: a
misplaced space in the -D flag and an inappropriate hardcoded compiler override;
change `-D SENTRY_BUILD_SHARED_LIBS=OFF` to `-DSENTRY_BUILD_SHARED_LIBS=OFF` and
remove the `-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++` flags so
CMake will default to the system/compiler already selected by the parent qmake
build (or if an override is required, use the same compiler variables/config
from the MINGW/Msys2 qmake environment so compilers match the rest of the
build).
There was a problem hiding this comment.
This trivial error is still in place and needs to be applied should anyone try to use QMake. Yes I know it is deprecated but in some situations it is still usable/useful (particularly given how hard CMake makes it to examine files not being directly used in the compilation and linkage stages of the build process)...
|
|
||
|
|
||
| QMAKE_POST_LINK += $$quote($$QMAKE_MOVE $$OUT_PWD/mudlet.pdb $$APP_DIR_PATH/) ; | ||
| QMAKE_POST_LINK += $$quote(cp -f $$SENTRY_PATH/install/bin/* $$APP_DIR_PATH/) ; |
There was a problem hiding this comment.
Major: Non-portable copy command.
Line 656 uses cp -f, which is a Unix command and won't work on Windows cmd.exe (though it might work in MSYS2 bash). Line 655 correctly uses $$QMAKE_MOVE for portability.
Use qmake's cross-platform copy variable:
- QMAKE_POST_LINK += $$quote(cp -f $$SENTRY_PATH/install/bin/* $$APP_DIR_PATH/) ;
+ QMAKE_POST_LINK += $$quote($$QMAKE_COPY $$SENTRY_PATH/install/bin/* $$APP_DIR_PATH/) ;Note: You may need to iterate over files individually if wildcard expansion doesn't work with $$QMAKE_COPY, as qmake's copy might not support wildcards on all platforms.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| QMAKE_POST_LINK += $$quote(cp -f $$SENTRY_PATH/install/bin/* $$APP_DIR_PATH/) ; | |
| QMAKE_POST_LINK += $$quote($$QMAKE_COPY $$SENTRY_PATH/install/bin/* $$APP_DIR_PATH/) ; |
🤖 Prompt for AI Agents
In src/mudlet.pro around line 656, the post-link command uses the Unix-only `cp
-f` which is not portable to Windows; replace it with qmake's cross-platform
copy mechanism (`$$QMAKE_COPY`) and, if wildcards are not supported on the
target platform, expand the install/bin files and call `$$QMAKE_COPY` on each
file individually (e.g., iterate the list of files and run the qmake copy for
each) so the operation works across platforms and preserves the intended
behavior.
There was a problem hiding this comment.
QMAKE_MOVE now present or the QMAKE_COPY imagined here are both AI fantasies - there is not such function in QMake. 😡
|
A few notes for the original post. When compiling with sentry enabled,
|
vadi2
left a comment
There was a problem hiding this comment.
Confirmed works well on Linux. Could you resolve the merge conflicts? The windows build has expired since, and I'd like to test it there.
ec69375 to
fca3bbc
Compare
|
Looks solid, thanks. |
|
/refresh links |
|
How can I get the crash handler to trigger on Windows? Screencast.from.2025-11-28.06-33-55.mp4I previously got it working macOS and Linux in this PR, but Windows was the hard part. |
|
Clang-tidy should work with latest development merged in |
Improve crash reporter dialog UX
|
Fair call on the size. Lets try uploading them on release and PTB builds only, and as a once-off on this PR (so the stack unwinding can be tested) |
This is RONG - Windows builds use the MSYS2+Mingw64 toolchain and |
|
I agree that by default, GCC under MinGW generates executables containing DWARF debug information, not CodeView. DWARF symbols can be split into a separate Additionally, Sentry specifically requires debug information in CodeView format on Windows in order to correctly process stack traces. For this reason, I enabled the GCC option -gcodeview (which I have read somewhere is still a little bit experimental) :
With this option enabled, the final mudlet.exe contains the CodeView symbols itself, and uploading the executable is enough for Sentry to resolve stack traces with accuracy. Sentry accepts this approach, so we do not need two separate files (binary + external debug file) for windows. After uploading to Sentry, the executable is stripped to reduce its size. About the .pdb file:Using For this reason, the .pdb file is simply removed after the build and not used. My original post was confusing when mentioning an external .pdb file. I apologize for that and have updated it. On another note, I think Sentry could benefit from supporting DWARF symbols ( |
Let's see if getsentry/sentry#104738 gets any traction... |
I understand that Basically, these (version 1.0) files: clash with these (version 1.1.1) files: 🤷 |
|
I wasn’t able to reproduce the exact same issue on my side, but I did encounter similar In my experience, these issues are usually resolved by starting from a completely clean state, for example: DetailsFor details, this is how sentry-native is currently compiled via CMake:These correspond to the two manual commands: Post-build, on my setup, Hopefully starting from a clean state helps avoid these conflicts, and in the meanwhile I fixed/updated the mudlet.pro in a PR to keep backward compatibility. |
Initially I thought that |



Brief overview of PR changes/additions
You can view the demonstration video here.
SENTRY_SEND_DEBUGWITH_SENTRYAll PR code is wrapped with
IF (WITH_SENTRY)blocks, making it easy to enable or disable the Sentry integration.The
SENTRY_SEND_DEBUGoption is used to automatically upload debug files to Sentry.io. These files are required by Sentry to display the exact line of a crash.Sentry requires both the executable and its corresponding debug symbols. Debug symbol files can be large (up to 350 MB for Mudlet), which is why this option
SENTRY_SEND_DEBUGexists—to avoid uploading the full debug files on every CI push.+(all debug symbols are embedded directly in the Mudlet binary).pdbfile.debugfile.dSYMfolderIdeally, the executable is "stripped" of all debug symbols to reduce its size, while the debug symbol files contain all the necessary debugging information. Both the stripped executable and the debug files are sent to Sentry, which is sufficient for accurate crash reporting.
Added a secondary program: A small window prompts the user for consent to send the crash report. This program is located at
src/crash_reporter/main.cpp.Copied a mandatory Sentry-provided executable (crash_handler) required for proper functioning, which must be placed alongside the Mudlet executable.
Generated a mandatory cache directory at runtime for storing Sentry crash reports.
Added a git submodule : sentry-native
Added two CI secret variables
${{ secrets.SENTRY_DSN }}sets the default DSN at compile time (developers can override it via an environment variable namedSENTRY_DSN).${{secrets.SENTRY_AUTH_TOKEN}}is used to send debug files. (dev can also override it via a environment variableSENTRY_AUTH_TOKENHow to Test
mudlet) and obtain the project's DSN then add it to the console environment: export SENTRY_DSN="..."export MUDLET_CRASH_TEST=1(thanks to this variable, Mudlet will crash whenever you open a profile. Let's use Sentry to see exactly where I inserted the crash.)But without the debug files, it doesn't show exactly where the crash is.
export=SENTRY_AUTH_TOKEN="..."-DSENTRY_SEND_DEBUG=1CI/send_debug_files_to_sentry.shMotivation for adding to Mudlet
/claim #7126,
fixes #7126.
Other info (issues closed, discussion etc)
I pushed a working snippet for qmake (mudlet.pro) aswell,
Although QMake is expected to be removed out soon, I added this snippet to ensure compatibility for the time being.