Package: libqt5core5a Version: 5.15.8+dfsg-11+deb12u3 Severity: normal Tags: patch upstream X-Debbugs-Cc: a...@chyla.org
Dear Maintainer, The Qt-based applications fail to run. All the apps hang without displaying anything on the screen, then terminate.Setting the QT_FONT_DPI environment variable to a sensible default, such as 100,
can be used as a workaround for the issue. As an example, let me take the qtop application: $ qtopErrorHandler::Throw - warning: Setting a QCompleter on non-editable QComboBox is not allowed. file: line: 0 function: ErrorHandler::Throw - warning: Setting a QCompleter on non-editable QComboBox is not allowed. file: line: 0 function: ErrorHandler::Throw - warning: QWidget::setMinimumSize: (/MainWindow) The largest allowed size is (16777215,16777215) file: line: 0 function: ErrorHandler::Throw - warning: QWidget::setMinimumSize: (/MainWindow) The largest allowed size is (16777215,16777215) file: line: 0 function: ErrorHandler::Throw - warning: QWidget::setMinimumSize: (/MainWindow) The largest allowed size is (16777215,16777215) file: line: 0 function: ErrorHandler::Throw - warning: QWidget::setMinimumSize: (/MainWindow) The largest allowed size is (16777215,16777215) file: line: 0 function:
KilledLooking at the ps output while the app is running, both the CPU time and memory
usage are increasing:$ while true ; do LC_ALL=C date "+Current time: %H:%M:%S" ; ps -C qtop Hu ; sleep 1 ; done
Current time: 08:38:44USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
adam 83283 1.7 0.0 46408 2344 pts/13 D+ 08:38 0:00 qtop Current time: 08:38:45USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
adam 83283 2.3 0.1 81480 12152 pts/13 D+ 08:38 0:00 qtop Current time: 08:38:47USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
adam 83283 2.4 0.2 164676 23068 pts/13 Dl+ 08:38 0:00 qtop Current time: 08:38:48USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
adam 83283 4.0 0.4 333088 35260 pts/13 Dl+ 08:38 0:00 qtop [..] Current time: 08:41:50USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
adam 83283 90.8 1.4 736760 118352 pts/13 Rl+ 08:38 2:49 qtop Current time: 08:41:51USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
adam 83283 90.9 1.4 736760 118352 pts/13 Rl+ 08:38 2:50 qtop Current time: 08:41:52USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
adam 83283 90.9 1.4 736760 118352 pts/13 Rl+ 08:38 2:51 qtop Current time: 08:41:53USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
adam 83283 91.0 13.6 5004544 1091248 pts/13 Rl+ 08:38 2:52 qtop Finally, the qtop is terminated by the kernel due to an Out of Memory (OOM): $ dmesg [...][122338.523460] gmain invoked oom-killer: gfp_mask=0x140cca(GFP_HIGHUSER_MOVABLE|__GFP_COMP), order=0, oom_score_adj=0 [122338.523471] CPU: 4 PID: 5110 Comm: gmain Tainted: G OE 6.1.0-33-amd64 #1 Debian 6.1.133-1 [122338.523475] Hardware name: LENOVO 20184/INVALID, BIOS 5ECN96WW(V9.01) 03/14/2013
[122338.523477] Call Trace: [122338.523481] <TASK> [122338.523484] dump_stack_lvl+0x44/0x5c [122338.523492] dump_header+0x4c/0x22b [122338.523498] oom_kill_process.cold+0xb/0x10 [122338.523503] out_of_memory+0x1fd/0x4c0 [...] [122338.523577] RIP: 0033:0x7f04297e921f [122338.523583] Code: Unable to access opcode bytes at 0x7f04297e91f5. [122338.523585] RSP: 002b:00007f04281fea90 EFLAGS: 00010293[122338.523588] RAX: 0000000000000000 RBX: 0000000000000002 RCX: 00007f04297e921f [122338.523590] RDX: 0000000000000f9c RSI: 0000000000000002 RDI: 000055dc4f759490 [122338.523592] RBP: 000055dc4f7f0a80 R08: 0000000000000000 R09: 00007f0429a042c0 [122338.523593] R10: 00007ffd2b881080 R11: 0000000000000293 R12: 000055dc4f759490 [122338.523595] R13: 00007f0429932150 R14: 0000000000000f9c R15: 0000000000000002
[122338.523600] </TASK> [122338.523601] Mem-Info: [122338.523603] active_anon:223303 inactive_anon:1606798 isolated_anon:0 active_file:106 inactive_file:17 isolated_file:0 unevictable:44733 dirty:1 writeback:3 slab_reclaimable:23415 slab_unreclaimable:28840 mapped:735444 shmem:880311 pagetables:15846 sec_pagetables:0 bounce:0 kernel_misc_reclaimable:0 free:26608 free_pcp:124 free_cma:0[122338.523610] Node 0 active_anon:893212kB inactive_anon:6427192kB active_file:424kB inactive_file:68kB unevictable:178932kB isolated(anon):0kB isolated(file):0kB mapped:2941776kB dirty:4kB writeback:12kB shmem:3521244kB shmem_thp: 0kB shmem_pmdmapped: 0kB anon_thp: 1347584kB writeback_tmp:0kB kernel_stack:25616kB pagetables:63384kB sec_pagetables:0kB all_unreclaimable? no [122338.523618] Node 0 DMA free:14336kB boost:0kB min:128kB low:160kB high:192kB reserved_highatomic:0KB active_anon:0kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB writepending:0kB present:15984kB managed:15360kB mlocked:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB
[122338.523625] lowmem_reserve[]: 0 2741 7708 7708 7708[122338.523630] Node 0 DMA32 free:43580kB boost:0kB min:23984kB low:29980kB high:35976kB reserved_highatomic:0KB active_anon:122436kB inactive_anon:2684992kB active_file:0kB inactive_file:0kB unevictable:6680kB writepending:0kB present:3005688kB managed:2894900kB mlocked:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB
[122338.523637] lowmem_reserve[]: 0 0 4967 4967 4967[122338.523642] Node 0 Normal free:48516kB boost:0kB min:43464kB low:54328kB high:65192kB reserved_highatomic:4096KB active_anon:770776kB inactive_anon:3742140kB active_file:744kB inactive_file:68kB unevictable:172252kB writepending:472kB present:5232640kB managed:5086304kB mlocked:192kB bounce:0kB free_pcp:496kB local_pcp:0kB free_cma:0kB
[122338.523649] lowmem_reserve[]: 0 0 0 0 0[122338.523653] Node 0 DMA: 0*4kB 0*8kB 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 1*2048kB (M) 3*4096kB (M) = 14336kB [122338.523669] Node 0 DMA32: 329*4kB (UME) 369*8kB (UME) 292*16kB (UME) 288*32kB (UME) 157*64kB (UME) 68*128kB (UME) 25*256kB (UE) 1*512kB (U) 0*1024kB 0*2048kB 0*4096kB = 43820kB [122338.523690] Node 0 Normal: 1059*4kB (UME) 824*8kB (UME) 631*16kB (UME) 249*32kB (UME) 138*64kB (UME) 57*128kB (UME) 8*256kB (ME) 2*512kB (M) 0*1024kB 0*2048kB 0*4096kB = 48092kB [122338.523711] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[122338.523714] 895623 total pagecache pages [122338.523715] 15054 pages in swap cache [122338.523717] Free swap = 0kB [122338.523718] Total swap = 999420kB [122338.523719] 2063578 pages RAM [122338.523720] 0 pages HighMem/MovableOnly [122338.523721] 64437 pages reserved [122338.523722] 0 pages hwpoisoned [122338.523723] Tasks state (memory values in pages):[122338.523725] [ pid ] uid tgid total_vm rss pgtables_bytes swapents oom_score_adj name
[...][122338.524391] [ 83283] 1000 83283 1251136 730206 6475776 0 200 qtop
[...][122338.524399] oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=/,mems_allowed=0,global_oom,task_memcg=/user.slice/user-1000.slice/user@1000.service/app.slice/app-org.gnome.Terminal.slice/vte-spawn-bd2dd4b4-bc66-4aec-a8d9-673ffe016ce3.scope,task=qtop,pid=83283,uid=1000 [122338.524441] Out of memory: Killed process 83283 (qtop) total-vm:5004544kB, anon-rss:27264kB, file-rss:0kB, shmem-rss:2893560kB, UID:1000 pgtables:6324kB oom_score_adj:200
I have collected the core dump and the stack trace points to the font related
functions:#0 0x00007f275c5f845d in FcCompare (pat=pat@entry=0x55a04f0a7750, fnt=0x7f274beb3840, value=value@entry=0x7ffc770f0d50, result=result@entry=0x7ffc770f0fcc, data=data@entry=0x7ffc770f0d48) at ./src/fcmatch.c:617 #1 0x00007f275c5f886e in FcFontSetMatchInternal (sets=sets@entry=0x7ffc770f0f50, nsets=<optimized out>, p=p@entry=0x55a04f0a7750, result=result@entry=0x7ffc770f0fcc) at ./src/fcmatch.c:896 #2 0x00007f275c5f9917 in IA__FcFontMatch (config=0x55a04ef3cc10, p=0x55a04f0a7750, result=0x7ffc770f0fcc)
at ./src/fcmatch.c:1082#3 0x00007f275c164894 in QFontconfigDatabase::setupFontEngine (this=this@entry=0x7f27540077b0, engine=engine@entry=0x55a04eee6a90, fontDef=...) at fontconfig/qfontconfigdatabase.cpp:980 #4 0x00007f275c1650a5 in QFontconfigDatabase::fontEngine (this=0x7f27540077b0, f=..., usrPtr=<optimized out>)
at fontconfig/qfontconfigdatabase.cpp:716#5 0x00007f2760227421 in loadSingleEngine (foundry=<optimized out>, size=<optimized out>, style=<optimized out>, family=<optimized out>, request=..., script=<optimized out>) at text/qfontdatabase.cpp:990 #6 loadEngine (script=script@entry=2, request=..., family=0x55a04f337b10, style=0x55a04f337be0, size=0x55a04f337c10,
foundry=<optimized out>) at text/qfontdatabase.cpp:1020#7 0x00007f2760227f23 in QFontDatabase::findFont (request=..., script=script@entry=2, preferScriptOverFamily=preferScriptOverFamily@entry=false) at text/qfontdatabase.cpp:2784 #8 0x00007f276020f97c in QFontEngineMulti::loadEngine (this=<optimized out>, at=<optimized out>)
at text/qfontengine.cpp:1843#9 0x00007f276021069f in QFontEngineMulti::ensureEngineAt (this=this@entry=0x55a04ec02f20, at=at@entry=22)
at text/qfontengine.cpp:1822#10 0x00007f2760210da3 in QFontEngineMulti::stringToCMap (this=0x55a04ec02f20, str=<optimized out>, len=<optimized out>, glyphs=<optimized out>, nglyphs=0x7ffc770f163c, flags=...) at text/qfontengine.cpp:1935
[..] After running the qtop with GDB, analyzing the stack trace along with the related code, it turned out that the Qt library failed to get the glyph, resulting in the loading of the next available font. This led to the loading of all available system fonts. That behavior was caused by an invalid pixelSize valuein the qtbase-everywhere-src-5.15.8/src/gui/text/qfontdatabase.cpp, line 950:
(gdb) break qfontdatabase.cpp:936 (gdb) run [..] 945 in text/qfontdatabase.cpp (gdb) p /d pixelSize $2 = 65535 [..] 950 in text/qfontdatabase.cpp (gdb) p /d pixelSize $3 = -298261618The if statement (lines 945-948) changed the initial value to a negative value:
qtbase-everywhere-src-5.15.8/src/gui/text/qfontdatabase.cpp 934 static 935 QFontEngine *loadSingleEngine(int script, 936 const QFontDef &request,937 QtFontFamily *family, QtFontFoundry *foundry,
938 QtFontStyle *style, QtFontSize *size) 939 { 940 Q_UNUSED(foundry); 941 942 Q_ASSERT(size);943 QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
944 int pixelSize = size->pixelSize;945 if (!pixelSize || (style->smoothScalable && pixelSize == SMOOTH_SCALABLE)
946 || pfdb->fontsAlwaysScalable()) { 947 pixelSize = request.pixelSize; 948 } 949 950 QFontDef def = request; 951 def.pixelSize = pixelSize; The request.pixelSize was set in QFontDatabase::load function: qtbase-everywhere-src-5.15.8/src/gui/text/qfontdatabase.cpp 2804 void QFontDatabase::load(const QFontPrivate *d, int script) 2805 { 2806 QFontDef req = d->request; 2807 2808 if (req.pixelSize == -1) {2809 req.pixelSize = std::floor(((req.pointSize * d->dpi) / 72) * 100 + 0.5) / 100;
2810 req.pixelSize = qRound(req.pixelSize); 2811 } 2812 if (req.pointSize < 0) 2813 req.pointSize = req.pixelSize*72.0/d->dpi; Let me focus on d->dpi (line 200, 196, 188): qtbase-everywhere-src-5.15.8/src/gui/text/qfont.cpp 179 Q_GUI_EXPORT int qt_defaultDpiY() 180 { 181 if (QCoreApplication::instance()->testAttribute(Qt::AA_Use96Dpi)) 182 return 96; 183 184 if (!qt_is_gui_used) 185 return 75; 186 187 if (const QScreen *screen = QGuiApplication::primaryScreen()) 188 return qRound(screen->logicalDotsPerInchY()); 189190 //PI has not been initialised, or it is being initialised. Give a default dpi
191 return 100; 192 } 193 194 Q_GUI_EXPORT int qt_defaultDpi() 195 { 196 return qt_defaultDpiY(); 197 } 198 199 QFontPrivate::QFontPrivate() 200 : engineData(nullptr), dpi(qt_defaultDpi()),201 underline(false), overline(false), strikeOut(false), kerning(true),
202 capital(0), letterSpacingIsAbsolute(false), scFont(nullptr) 203 { 204 } It was set to the value returned from screen->logicalDotsPerInchY(): qtbase-everywhere-src-5.15.8/src/gui/kernel/qscreen.cpp 329 qreal QScreen::logicalDotsPerInchY() const 330 { 331 Q_D(const QScreen); 332 if (QHighDpiScaling::isActive()) 333 return QHighDpiScaling::logicalDpi(this).second; 334 return d->logicalDpi.second; 335 } In my case, d->logicalDpi.second was returned. logicalDpi is set in QScreenPrivate::setPlatformScreen function (line 114): qtbase-everywhere-src-5.15.8/src/gui/kernel/qscreen.cpp 73 QScreen::QScreen(QPlatformScreen *screen) 74 : QObject(*new QScreenPrivate(), nullptr) 75 { 76 Q_D(QScreen); 77 d->setPlatformScreen(screen); 78 } qtbase-everywhere-src-5.15.8/src/gui/kernel/qscreen.cpp 107 void QScreenPrivate::setPlatformScreen(QPlatformScreen *screen) 108 { 109 Q_Q(QScreen); 110 platformScreen = screen; 111 platformScreen->d_func()->screen = q; 112 orientation = platformScreen->orientation(); 113114 logicalDpi = QPlatformScreen::overrideDpi(platformScreen->logicalDpi());
115 116 refreshRate = platformScreen->refreshRate(); 117 // safeguard ourselves against buggy platform behavior... 118 if (refreshRate < 1.0) 119 refreshRate = 60.0;The logicalDpi can be overwritten by setting the QT_FONT_DPI environment variable
to a positive value, this can be used to workaround the issue: qtbase-everywhere-src-5.15.8/src/gui/kernel/qplatformscreen.cpp 198 // Helper function for accessing the platform screen logical dpi 199 // which accounts for QT_FONT_DPI.200 QPair<qreal, qreal> QPlatformScreen::overrideDpi(const QPair<qreal, qreal> &in)
201 {202 static const int overrideDpi = qEnvironmentVariableIntValue("QT_FONT_DPI");
203 return overrideDpi > 0 ? QDpi(overrideDpi, overrideDpi) : in; 204 }For this particular case, the platformScreen->logicalDpi() code calls the QXcbScreen::logicalDpi
function: qtbase-everywhere-src-5.15.8/src/plugins/platforms/xcb/qxcbscreen.cpp 720 int QXcbScreen::forcedDpi() const 721 { 722 const int forcedDpi = m_virtualDesktop->forcedDpi(); 723 if (forcedDpi > 0) 724 return forcedDpi; 725 return 0; 726 } 727 728 QDpi QXcbScreen::logicalDpi() const 729 { 730 const int forcedDpi = this->forcedDpi(); 731 if (forcedDpi > 0) 732 return QDpi(forcedDpi, forcedDpi); 733 734 // Fall back to physical virtual desktop DPI, but prevent 735 // using DPI values lower than 96. This ensuers that connecting 736 // to e.g. a TV works somewhat predictabilly. 737 QDpi virtualDesktopPhysicalDPi = m_virtualDesktop->dpi(); 738 return QDpi(std::max(virtualDesktopPhysicalDPi.first, 96.0), 739 std::max(virtualDesktopPhysicalDPi.second, 96.0)); 740 } The code above returns the {96, inf} pair, so need to focus on the virtualDesktopPhysicalDPi values: (gdb) break QXcbScreen::logicalDpi (gdb) runThread 1 "qtop" hit Breakpoint 1.1, QXcbScreen::logicalDpi (this=0x55555595ffe0) at ./src/plugins/platforms/xcb/qxcbscreen.cpp:730 730 ./src/plugins/platforms/xcb/qxcbscreen.cpp: Nie ma takiego pliku ani katalogu.
(gdb) next 731 in ./src/plugins/platforms/xcb/qxcbscreen.cpp (gdb) print forcedDpi $1 = 0 (gdb) nextThread 1 "qtop" hit Breakpoint 1.2, QXcbScreen::logicalDpi (this=<optimized out>) at ./src/plugins/platforms/xcb/qxcbscreen.cpp:737
737 in ./src/plugins/platforms/xcb/qxcbscreen.cpp (gdb) next 738 in ./src/plugins/platforms/xcb/qxcbscreen.cpp (gdb) nextQXcbScreen::logicalDpi (this=0x55555595ffe0) at ../../../../include/QtCore/../../src/corelib/tools/qpair.h:58 58 ../../../../include/QtCore/../../src/corelib/tools/qpair.h: Nie ma takiego pliku ani katalogu.
(gdb) nextQScreenPrivate::setPlatformScreen (this=0x7fffec003f50, screen=screen@entry=0x55555595ffe0) at kernel/qscreen.cpp:116
116 kernel/qscreen.cpp: Nie ma takiego pliku ani katalogu. (gdb) print logicalDpi $4 = {first = 96, second = inf} virtualDesktopPhysicalDPi is calculated in QXcbVirtualDesktop::dpi function: qtbase-everywhere-src-5.15.8/src/plugins/platforms/xcb/qxcbscreen.cpp 135 QDpi QXcbVirtualDesktop::dpi() const 136 { 137 const QSize virtualSize = size(); 138 const QSize virtualSizeMillimeters = physicalSize(); 139140 return QDpi(Q_MM_PER_INCH * virtualSize.width() / virtualSizeMillimeters.width(), 141 Q_MM_PER_INCH * virtualSize.height() / virtualSizeMillimeters.height());
142 } size, physicalSize are as follows: qtbase-everywhere-src-5.15.8/src/plugins/platforms/xcb/qxcbscreen.h75 QSize size() const { return QSize(m_screen->width_in_pixels, m_screen->height_in_pixels); } 76 QSize physicalSize() const { return QSize(m_screen->width_in_millimeters, m_screen->height_in_millimeters); }
Checking with GDB, *_in_pixels looks correct, but *_in_millimeters appears to be incorrect: (gdb) print /d m_screen->width_in_pixels $2 = 4310 (gdb) print /d m_screen->height_in_pixels $3 = 1080 (gdb) print /d m_screen->width_in_millimeters $4 = 0 (gdb) print /d m_screen->height_in_millimeters $5 = 0 These values are used in the nominative within the QXcbVirtualDesktop::dpi function, so in qxcbscreen.cpp:140 there is division by 0. width_in_millimeters, height_in_millimeters are members of the xcb_screen_t structure from the libxcb. These variables are initialized by functions from the mentioned library. I'm uncertain if zeros are the correct values. The X Window System Protocol specification doesn't mention anything about it: "Width-in-millimeters and height-in-millimeters can be used to determine the physical size and the aspect ratio" [1]. Based on this, zeros may be the correct values. On the other hand, the X Resize, Rotate and Reflect Extension specification provides some guidance, in which it states (RRSetScreenSize) 'width-in-millimeters' and 'height-in-millimeters' can be set to reflect the physical size of the screen reported both through this extension and the core protocol. They must be non-zero, or Value error results. [2] This may require further investigation under separate bug report. I believe the root cause of the issue is not in the Qt itself, however, in my opinion Qt should handle the values appropriately. This can be done in QXcbVirtualDesktop::dpi, by returning a default value in case of zeros in the nominative. Suggested patch that resolves the issue:--- a/src/plugins/platforms/xcb/qxcbscreen.cpp 2022-11-11 07:29:17.000000000 +0000 +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp 2025-06-03 20:09:52.619026981 +0000
@@ -137,8 +137,12 @@ const QSize virtualSize = size(); const QSize virtualSizeMillimeters = physicalSize();- return QDpi(Q_MM_PER_INCH * virtualSize.width() / virtualSizeMillimeters.width(), - Q_MM_PER_INCH * virtualSize.height() / virtualSizeMillimeters.height()); + if (virtualSizeMillimeters.width() > 0 && virtualSizeMillimeters.height() > 0) + return QDpi(Q_MM_PER_INCH * virtualSize.width() / virtualSizeMillimeters.width(), + Q_MM_PER_INCH * virtualSize.height() / virtualSizeMillimeters.height());
+ + const int defaultDpi = 100; + return QDpi(defaultDpi, defaultDpi); } QXcbScreen *QXcbVirtualDesktop::screenAt(const QPoint &pos) const Best regards, Adam. [1] https://www.x.org/releases/X11R7.7/doc/xproto/x11protocol.html [2] https://www.x.org/releases/X11R7.7/doc/randrproto/randrproto.txt -- System Information: Debian Release: 12.11 APT prefers stable-updatesAPT policy: (500, 'stable-updates'), (500, 'stable-security'), (500, 'stable-debug'), (500, 'stable')
Architecture: amd64 (x86_64) Kernel: Linux 6.1.0-37-amd64 (SMP w/8 CPU threads; PREEMPT) Kernel taint flags: TAINT_OOT_MODULE, TAINT_UNSIGNED_MODULELocale: LANG=pl_PL.UTF-8, LC_CTYPE=pl_PL.UTF-8 (charmap=UTF-8), LANGUAGE not set
Shell: /bin/sh linked to /usr/bin/dash Init: systemd (via /run/systemd/system) LSM: AppArmor: enabled Versions of packages libqt5core5a depends on: ii libc6 2.36-9+deb12u10 ii libdouble-conversion3 3.2.1-1 ii libgcc-s1 12.2.0-14+deb12u1 ii libglib2.0-0 2.74.6-2+deb12u6 ii libicu72 72.1-3 ii libpcre2-16-0 10.42-1 ii libstdc++6 12.2.0-14+deb12u1 ii libzstd1 1.5.4+dfsg2-5 ii shared-mime-info 2.2-1 ii zlib1g 1:1.2.13.dfsg-1 Versions of packages libqt5core5a recommends: ii qttranslations5-l10n 5.15.8-2 Versions of packages libqt5core5a suggests: ii libthai0 0.1.29-1 -- no debconf information
OpenPGP_signature.asc
Description: OpenPGP digital signature