[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
-
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! :')
-
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.
-
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.
@Nils-Sjoberg Thanks for the suggestion!
I tested with:
OPENSSL_armcap=0Unfortunately, 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
WebEngineProfilewas 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
WebEngineViewwas using a profile stored under/tmp, with a directory name based oncontent.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 namedCacheThread_Blo, with a backtrace ending inmalloc()/operator new()insidelibQt5WebEngineCore.so.
In other words, changing only
persistentStoragePathandcachePathsignificantly 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).
/tmpis atmpfson 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
/tmpitself, but rather how QtWebEngine/Chromium initializes and manages aWebEngineProfileon 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
WebEngineProfileis expected to be used? In particular:- Is storing a
WebEngineProfileunder/tmpconsidered 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
WebEngineProfileand reusing it across allWebEngineViewinstances?
Has anyone seen similar behaviour where changing only
persistentStoragePathorcachePathchanges 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.