Details
-
Bug
-
Resolution: Done
-
P1: Critical
-
5.15.6, 6.4.0
-
None
-
Windows 10
-
-
933eb68a9d (qt/qtbase/dev) 933eb68a9d (qt/tqtc-qtbase/dev) 520a837888 (qt/qtbase/6.4) 520a837888 (qt/tqtc-qtbase/6.4) 520a837888 (qt/tqtc-qtbase/6.4.1) 520a837888 (qt/tqtc-qtbase/tqtc/qtinsight-6.4)
Description
Problem
We have discovered a case where simply the action of selecting a file in the QFileDialog results in a complete freeze of the dialog for over a minute. This happens when using the Windows Native Dialog only, when forcing DontUseNativeDialog there is no freeze.
The freeze happens when you select a very large zip container. In our case the file is 50 gigabytes and contains about 200'000 files.
Similar issues
I read the description to a similar bug report:
https://bugreports.qt.io/browse/QTBUG-72479
In that report the IFileDialog class was blamed, so I tried one of the official examples from Microsoft using the IFileDialog:
https://github.com/microsoft/Windows-classic-samples/tree/main/Samples/Win7Samples/winui/shell/appplatform/commonfiledialog
However, the Microsoft example do not have the same freezing behavior.
Cause
This made me dig a bit into the QT source and I have been able to track down the line of code which is causing the freeze. It is located in: qtbase\src\plugins\platforms\windows\qwindowsdialoghelpers.cpp
In the constructor for QWindowsShellItem:
QWindowsShellItem::QWindowsShellItem(IShellItem *item)
: m_item(item)
, m_attributes(0)
{
if (FAILED(item->GetAttributes(SFGAO_CAPABILITYMASK | SFGAO_DISPLAYATTRMASK | SFGAO_CONTENTSMASK | SFGAO_STORAGECAPMASK, &m_attributes)))
m_attributes = 0;
}
The problem in this case is the checking of the SFGAO_CONTENTSMASK which forces the IShellItem to check if the file have subfolders, which in turn makes Windows start the indexing of the zip-file. In our case, this indexing takes over 70 second and during this time the file dialog is completely frozen.
Further information
I made a small program which profiles the time to acquire the different IShellItem attributes listed here:
https://learn.microsoft.com/en-us/windows/win32/shell/sfgao
The attributes which are expensive to check is: SFGAO_HASSUBFOLDER, SFGAO_CONTENTSMASK and SFGAO_PKEYSFGAOMASK. All these attribute forces windows to start indexing the zip-file, which is an expensive operation when the ZIP file is large. All other attributes can be retrieved within 0.2 ms.
Proposed solution
My proposal is to remove the SFGAO_CONTENTSMASK check from the attribute list in the constructor. The bitmask for this enum is the same as in SFGAO_HASSUBFOLDER, which Microsoft describes in their documentation as:
"The SFGAO_HASSUBFOLDER attribute is only advisory and might be returned by Shell folder implementations even if they do not contain subfolders."
Since the attribute is only advisory it should be safe to skip, or at least defer to a later point if needed.
At the same time the attribute check for SFGAO_DISPLAYATTRMASK should probably be remove as well, since the Microsoft documentation states: Do not use.
Attachments
Issue Links
- duplicates
-
QTBUG-72479 QFileDialog hangs if try to select a big zip file
- Closed