Unsolved Qt5 hanging/crashing problems when window is not active (on MacOS)
-
@aeszym Like @jlgregg said I immediately thought of the app going into AppNap. I found that disabling options for app nap were no use for my issue. I needed to keep my code running in the background with code. The following worked for me...
[[NSProcessInfo processInfo] beginActivityWithOptions:NSActivityBackground reason:@"cos my app gets bruk in the background"];
-
Here's a quick look at Activity Monitor's sample process output while the app is hanging. Please note that I have not seen consistent sample output; that is, there seems be multiple places in Qt/QCore that are hanging.
Call graph: 2787 Thread_4621518 DispatchQueue_1: com.apple.main-thread (serial) + 2787 start (in libdyld.dylib) + 1 [0x7fff729d7cc9] + 2787 main (in HubTool) + 216 [0x104116c68] + 2787 QCoreApplication::exec() (in QtCore) + 130 [0x1056e1452] + 2787 QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) (in QtCore) + 431 [0x1056dc50f] + 2787 ??? (in libqcocoa.dylib) load address 0x104a5e000 + 0x33ccb [0x104a91ccb] + 2787 -[NSApplication run] (in AppKit) + 658 [0x7fff35ba358e] + 2787 -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] (in AppKit) + 3848 [0x7fff35bb2240] + 2787 objc_autoreleasePoolPop (in libobjc.A.dylib) + 175 [0x7fff71824dba] + 2787 AutoreleasePoolPage::releaseUntil(objc_object**) (in libobjc.A.dylib) + 134 [0x7fff71840054] + 2781 -[NSBitmapGraphicsContext dealloc] (in AppKit) + 59 [0x7fff35d40a8e] + ! 2781 -[NSCGSContext dealloc] (in AppKit) + 25 [0x7fff35d40aae] + ! 2780 -[NSCGSContext _invalidate] (in AppKit) + 44 [0x7fff35d40aff] + ! : 2778 _CFRelease (in CoreFoundation) + 189 [0x7fff38a0e568] + ! : | 2777 context_reclaim (in CoreGraphics) + 37 [0x7fff38d7482d] + ! : | + 2776 _CFRelease (in CoreFoundation) + 189 [0x7fff38a0e568] + ! : | + ! 2776 CGContextDelegateFinalize (in CoreGraphics) + 59 [0x7fff38d748c0] + ! : | + ! 2773 ripc_Finalize (in CoreGraphics) + 237 [0x7fff38d74a41] + ! : | + ! : 2773 RIPRemoveContextFromContextList (in CoreGraphics) + 40 [0x7fff38d7504e] + ! : | + ! : 2773 x_list_remove (in CoreGraphics) + 32,56,... [0x7fff38d74dec,0x7fff38d74e04,...] + ! : | + ! 1 free (in libsystem_malloc.dylib) + 0 [0x7fff72b8e9b1] + ! : | + ! 1 ripc_Finalize (in CoreGraphics) + 106 [0x7fff38d749be] + ! : | + ! : 1 free_tiny (in libsystem_malloc.dylib) + 459 [0x7fff72b92d8b] + ! : | + ! : 1 tiny_free_no_lock (in libsystem_malloc.dylib) + 1018 [0x7fff72b93279] + ! : | + ! : 1 tiny_free_list_remove_ptr (in libsystem_malloc.dylib) + 519 [0x7fff72b93fd6] + ! : | + ! 1 ripc_Finalize (in CoreGraphics) + 115 [0x7fff38d749c7] + ! : | + ! 1 _CFRelease (in CoreFoundation) + 460 [0x7fff38a0e677] + ! : | + ! 1 color_transform_retain_count (in CoreGraphics) + 93 [0x7fff38d60751] + ! : | + ! 1 color_transform_finalize (in CoreGraphics) + 87 [0x7fff38d74c73] + ! : | + ! 1 CGColorTransformBaseCacheRelease (in CoreGraphics) + 115 [0x7fff38d74d2b] + ! : | + ! 1 matches_space (in CoreGraphics) + 62 [0x7fff38d5a59c]
-
As for the AppNap topic, I have tried calling beginActivityWithOptions with NSActivityBackground, NSActivityUserInitiated, and NSActivityUserInitiated | NSActivityLatencyCritical at the start of the program and also around the various signals for updating the GUI thread with no effect on the hang. Any and all of these prevent actual AppNap, but as I noted, the program is not being napped when this hang occurs. The attached source (above) includes appNap.mm which sets NSActivityUserInitiated but calls to the "napper" object are commented out. You are welcome to experiment with those calls.
-
What value should the refresh rate have in normal execution ?
-
Short answer: the default is 20ms delay between calls to StemWorker::pollStemForChanges() which signals the GUI thread with updates. There are 100s of signals that get fired from this call at a rate of ~1 per millisecond. That is, almost every GUI element gets updated with signals from this function. So, the average update rate is around 10-15Hz, but there are spikes of calls which signal into GUI elements.
Longer answer: This GUI is a tool to interface with USB hardware. Most customers want "as fast as possible" refresh rates. There are multiple interactions with the USB hardware. Each interaction takes 1-2ms and result in the firing of 1-8 signals from the StemWorker thread to the GUI (HubTool) thread. In total, the hardware interactions take ~50ms total (this is for the function StemWorker::pollStemForChanges() to complete). The default setting is for the StemWorker::pollStemForChanges() to be triggered 20ms after the previous completion (see pollingTimer and HubTool::handlePollingFinished()). This delay is configurable by the user in the GUI as the "Polling Delay".
Reading into your question a bit, do you think it be better to "smooth out" the GUI update rate? That is, make it so the signals hit the GUI thread at a more consistent (and slower) rate? Since I'm not directly forcing an update() call in GUI thread, shouldn't Qt queue these updates and effectively smooth the update rate for me?
-
My question came because I did not notice a big drop so I did not know what I should be watching for.
As for the update, repainting will also depend on the hardware you use. You can't get faster than what your graphics card/screen combo allows. And you also have to think that the human eye still works at around 24fps so trying to update your numbers at high speed will not really make them more visible. Triggering meaningful updates will always be better, you'll perform well on a wider range of hardware.
-
The drop in refresh rate isn't the big concern, but it is a helpful indicator that something is getting "gummed up". The big concern is the hang on re-activating the app. After launching and backgrounding the application, wait for 10-15 minutes. I notice that the refresh rate slowly drops over this time. Then bring the application back to the foreground. You will get a beachball hang for several seconds. The length of the hang seems correlated to the amount of time in the app was in the background (not active).
I completely understand and agree with the reasonable limit on GUI update rate. The longer answer above mentions that there is hardware in the loop for this application. As such, the fastest average update rate to the GUI is about 20Hz (1/50ms). Most systems are closer to 10-15Hz average update rate to the GUI. The hang that occurs after the app is backgrounded/foregrounded does not seem to be impacted by this update rate; it only seems to depend on the amount of time the app is inactive.
Another thing to note is that I've purposely stripped down this application to aide in debugging this hang. While the update rate to the GUI shouldn't need to be faster than 10-15Hz, one use case for this app is as a simple data logger. As such, some users want to log data "as fast as possible". To do this, the signals coming from StemWorker::pollStemForChanges() are also connected to some plots via qCustomPlot objects. I originally suspected qCustomPlot the source of the hang, which is how I started to move towards the stripped down version of the app posted here. You can run the full version (even without the associated hardware) which is available in compiled binaries here with source here.
(and thanks for your input on this so far)
-
I am also facing this type of issue.
core dump is also there.
https://forum.qt.io/topic/120710/qml-c-crash-when-dialog-window-is-getting-opened-on-pressing-button-in-qt-application -
Was there ever any update on this? We see the same behavior in our application.
-
@btse Since there was no link to a bug report posted somewhere I would guess no one at TQtC knows about this. So provide a minimal, compilable example and create a bug report.