Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. [QtWebEngine 5.15.17] Recurring heap corruption crash (std::bad_alloc / corrupted double-linked list) on Raspberry Pi 3 (armhf, Trixie) — works fine on Pi 5 (aarch64) with the same build process
Qt 6.11 is out! See what's new in the release blog

[QtWebEngine 5.15.17] Recurring heap corruption crash (std::bad_alloc / corrupted double-linked list) on Raspberry Pi 3 (armhf, Trixie) — works fine on Pi 5 (aarch64) with the same build process

Scheduled Pinned Locked Moved Unsolved Mobile and Embedded
qtwebengineraspberry pi 3arm7
3 Posts 2 Posters 161 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • T Offline
    T Offline
    The Qt Mayssa
    wrote last edited by The Qt Mayssa
    #1

    I'm running a Qt/QML application (NeoPlayer, digital signage) embedding WebEngineView widgets (QtWebEngine 5.15.17), on two Raspberry Pi OS Trixie (Debian 13) targets running Wayland/labwc:

    • Raspberry Pi 5 (aarch64, kernel 6.12.47+rpt-rpi-2712) → works perfectly, no crashes.
    • Raspberry Pi 3 (armhf/ARMv7, 32-bit) → recurring, reproducible crash, at startup and/or during WebEngine widget transitions.

    Qt is built via cross-compilation in Docker (toolchain arm-linux-gnueabihf for Pi3, aarch64-linux-gnu for Pi5), using a custom script (mkqt) that builds qtbase, qtdeclarative, qtwayland, qtgraphicaleffects, qtmultimedia, qtquickcontrols, qtwebchannel, qtwebview, qtwebengine (Chromium), qtwebsockets, qtxmlpatterns, qtsvg, qtvirtualkeyboard, against a sysroot synced from a real device. Qt is configured with -openssl and VOPENSSL=1.1.1q for the build-time headers, while both devices run OpenSSL 3.x at runtime (3.5.6 on Pi3, 3.5.4 on Pi5 — so comparable on both sides).

    Symptom

    On Pi3 only, the app crashes almost systematically during transitions involving a WebEngine widget, with two observed signatures:

    SIGSEGV + corrupted double-linked list (glibc's heap corruption detector)
    std::bad_alloc followed by Aborted (core dumped)

    Core dump analysis (coredumpctl gdb)

    The corruption is detected by glibc during a posix_memalign call, whose caller is CRYPTO_aligned_alloc (libcrypto.so.3, OpenSSL 3.x):

    #4  malloc_printerr
    #5  unlink_chunk
    #6  malloc_consolidate
    #7  _int_malloc
    #8  _int_memalign
    #9  _mid_memalign
    #10 __posix_memalign
    #11 CRYPTO_aligned_alloc (libcrypto.so.3 + 0x1be564)
    

    Hypotheses already tested and ruled out

    • Cache/log permissions (/xx/cache, /xx/logs): fixed (chown), was not the root cause of the corruption itself.
    • Real OOM: available RAM stayed flat (~763-766 MB out of 920 MB total) before/during the crash → no real memory exhaustion.
    • libarmmem-v7l.so (Raspberry Pi's NEON-optimized 32-bit memcpy override, loaded via /etc/ld.so.preload): disabled for testing → identical crash, ruled out.
    • CPU flag inconsistency (-march=armv8-a -mtune=cortex-a53) between qtbase/qtwebengine compilation units: exhaustively checked in the ninja build logs, every actual source file compile uses the correct flags. Ruled out.
    • OpenSSL version: Pi5 also runs OpenSSL 3.x and works perfectly fine → a simple 1.1.1(build)/3.x(runtime) mismatch alone doesn't explain the difference between the two devices.
    • GPU/EGL-Wayland driver: confirmed via eglinfo that Pi3 does use the hardware driver vc4 (VC4 V3D 2.1, OpenGL ES 2.0 only) on the Wayland path — no software fallback. Pi5 uses v3d (V3D 7.1.7.0, OpenGL ES 3.1). This capability gap is real, but forcing --disable-gpu/full software rendering on the Chromium side doesn't change the crash behavior at all → likely not the direct cause.

    Current working hypothesis

    The one remaining structural difference we haven't yet tested/disproven is that Pi3 is a 32-bit build (armhf/ARMv7), while Pi5 is 64-bit (aarch64). Given that 32-bit ARM Chromium/QtWebEngine builds get increasingly little upstream test/fuzzing coverage (OSS-Fuzz and Google's CI mainly targeting x86-64/ARM64 these days), I'm wondering whether this is a known/documented fragility of QtWebEngine 5.15 on 32-bit armhf targets.

    Questions for the community

    • Has anyone run into this kind of heap corruption (corrupted double-linked list / std::bad_alloc) with QtWebEngine 5.15.x built for 32-bit ARMv7?
    • Are there specific GN/ninja build flags recommended for Chromium on armv7 to avoid this kind of issue?
    • Is the fact that Qt is configured against OpenSSL 1.1.1 (build-time headers) while the runtime system has OpenSSL 3.x a known problem, even though both devices (Pi3 and Pi5) are in the same situation?

    Thanks in advance for any leads! :')

    1 Reply Last reply
    0
    • Nils SjobergN Offline
      Nils SjobergN Offline
      Nils Sjoberg
      wrote last edited by
      #2

      Try running with OPENSSL_armcap=0 (without recompiling) - if the crash goes away, this confirms a CPU misdetection issue in OpenSSL on the Pi3, which can then be permanently fixed with a recompilation in no-asm.

      "What's up, Doc?"

      T 1 Reply Last reply
      0
      • Nils SjobergN Nils Sjoberg

        Try running with OPENSSL_armcap=0 (without recompiling) - if the crash goes away, this confirms a CPU misdetection issue in OpenSSL on the Pi3, which can then be permanently fixed with a recompilation in no-asm.

        T Offline
        T Offline
        The Qt Mayssa
        wrote last edited by The Qt Mayssa
        #3

        @Nils-Sjoberg Thanks for the suggestion!

        I tested with:

        OPENSSL_armcap=0
        

        Unfortunately, it doesn't change the behaviour. The application still crashes on the Raspberry Pi 3, so it doesn't appear to be an OpenSSL CPU capability detection issue.

        However, I have an interesting update that may help narrow down the problem.

        Originally, my WebEngineProfile was configured like this:

        property string tmpDir: session.getPlatform() == "windows" ? "C:/Temp/xx" : "/tmp"
        
        WebEngineProfile {
            offTheRecord: false
            persistentStoragePath: tmpDir + "/xx-webengine-" + content.uuid()
            cachePath: tmpDir + "/xx-webcache-" + content.uuid()
        }
        

        So every WebEngineView was using a profile stored under /tmp, with a directory name based on content.uuid().

        I then changed only the profile/cache location to a persistent directory under the user's home instead of /tmp, for example:

        persistentStoragePath: "/home/xx/.local/share/xx/NeoPlayer/WebEngine/profile"
        cachePath: "/home/xx/.local/share/xx/NeoPlayer/WebEngine/cache"
        

        (or an equivalent persistent location).

        Since this change:

        • the application progresses much further during startup,
        • several crashes no longer occur,
        • the remaining crash is now consistently inside QtWebEngineCore, typically in a thread named CacheThread_Blo, with a backtrace ending in malloc() / operator new() inside libQt5WebEngineCore.so.

        In other words, changing only persistentStoragePath and cachePath significantly changes the failure mode.

        What puzzles me is that the original code works perfectly on a Raspberry Pi 5, while it crashes on the Raspberry Pi 3.

        Some additional comparison between the two systems:

        • Both run Debian 13 (Trixie).
        • /tmp is a tmpfs on both systems.
        • Both use the same application source code.
        • Both are built from the same Qt 5.15.17 build system (with architecture-specific binaries).
        • The Raspberry Pi 5 runs AArch64 (64-bit), while the Raspberry Pi 3 runs ARMv7 (32-bit).

        This makes me wonder whether the issue is not /tmp itself, but rather how QtWebEngine/Chromium initializes and manages a WebEngineProfile on 32-bit ARM. Changing the profile location seems to alter the internal initialization sequence enough that the crash either disappears or occurs much later during startup.

        Am I overlooking something about how WebEngineProfile is expected to be used? In particular:

        • Is storing a WebEngineProfile under /tmp considered bad practice or unsupported?
        • Is creating profile directories dynamically using content.uuid() likely to expose issues or race conditions inside QtWebEngine?
        • Would you instead recommend creating a single long-lived WebEngineProfile and reusing it across all WebEngineView instances?

        Has anyone seen similar behaviour where changing only persistentStoragePath or cachePath changes or eliminates crashes in QtWebEngine?

        If there are other diagnostics that would help identify the root cause, I'd be happy to run them and share the results.

        1 Reply Last reply
        0

        • Login

        • Login or register to search.
        • First post
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • Users
        • Groups
        • Search
        • Get Qt Extensions
        • Unsolved