Random application crash on Apple Silicon M1 (Qt 6.2.3)
-
void RadioControl::eventFromDab(RadioControlEvent * pEvent)
{
switch (pEvent->type) // <=== sanitizer complains that this is the data racethis one is, you're passing a pointer to an object around, that lives on an other thread. The QueuedConnecion will only copy the pointer not the underlying data.
@J-Hilk said in Random application crash on Apple Silicon M1 (Qt 6.2.3):
void RadioControl::eventFromDab(RadioControlEvent * pEvent)
{
switch (pEvent->type) // <=== sanitizer complains that this is the data racethis one is, you're passing a pointer to an object around, that lives on an other thread. The QueuedConnecion will only copy the pointer not the underlying data.
Yes, that is actually my point. I do not want to do copy of the data (in this case it is small, but it can be significantly bigger), I want to pass a pointer to the other thread that reads the data and finally deletes them. Data in callback are not touched after radioCtrl->emit_dabEvent(pEvent).
If this is not the correct way, how to pass the data without additional copying correctly? Would it be better to use QSharedPointer<RadioControlEvent> instead?
RadioControlEvent is this structure:
struct RadioControlEvent { RadioControlEventType type; // <-- enum class RadioControlEventType dabProcNotificationStatus_t status; // <-- enum intptr_t pData; };
-
@J-Hilk said in Random application crash on Apple Silicon M1 (Qt 6.2.3):
void RadioControl::eventFromDab(RadioControlEvent * pEvent)
{
switch (pEvent->type) // <=== sanitizer complains that this is the data racethis one is, you're passing a pointer to an object around, that lives on an other thread. The QueuedConnecion will only copy the pointer not the underlying data.
Yes, that is actually my point. I do not want to do copy of the data (in this case it is small, but it can be significantly bigger), I want to pass a pointer to the other thread that reads the data and finally deletes them. Data in callback are not touched after radioCtrl->emit_dabEvent(pEvent).
If this is not the correct way, how to pass the data without additional copying correctly? Would it be better to use QSharedPointer<RadioControlEvent> instead?
RadioControlEvent is this structure:
struct RadioControlEvent { RadioControlEventType type; // <-- enum class RadioControlEventType dabProcNotificationStatus_t status; // <-- enum intptr_t pData; };
@KejPi oh my, you're handling Nitroglycerin, when you could work with the much saver Dynamite !
if you catch my allegory :D
use a mutex!
https://en.cppreference.com/w/cpp/thread/mutex
https://doc.qt.io/qt-5/qmutex.html -
@KejPi oh my, you're handling Nitroglycerin, when you could work with the much saver Dynamite !
if you catch my allegory :D
use a mutex!
https://en.cppreference.com/w/cpp/thread/mutex
https://doc.qt.io/qt-5/qmutex.html@J-Hilk said in Random application crash on Apple Silicon M1 (Qt 6.2.3):
@KejPi oh my, you're handling Nitroglycerin, when you could work with the much saver Dynamite !
if you catch my allegory :D
use a mutex!
https://en.cppreference.com/w/cpp/thread/mutex
https://doc.qt.io/qt-5/qmutex.htmlI am used to develop bare metal DSP code in very low level C - I like working with explosives :-D
I understand that mutex is the right way to protect the data but it is not for free and it may potentially block for some time the real time processing in backend library that I want to avoid. My intention is to have callback as fast as possible just to pass data and continue with processing of the data that is not waiting. It will not be easy to hit this goal with mutex :-( -
@J-Hilk said in Random application crash on Apple Silicon M1 (Qt 6.2.3):
@KejPi oh my, you're handling Nitroglycerin, when you could work with the much saver Dynamite !
if you catch my allegory :D
use a mutex!
https://en.cppreference.com/w/cpp/thread/mutex
https://doc.qt.io/qt-5/qmutex.htmlI am used to develop bare metal DSP code in very low level C - I like working with explosives :-D
I understand that mutex is the right way to protect the data but it is not for free and it may potentially block for some time the real time processing in backend library that I want to avoid. My intention is to have callback as fast as possible just to pass data and continue with processing of the data that is not waiting. It will not be easy to hit this goal with mutex :-(I am used to develop bare metal DSP code in very low level C - I like working with explosives :-D
:D
I understand that mutex is the right way to protect the data but it is not for free and it may potentially block for some time the real time processing in backend library that I want to avoid. My intention is to have callback as fast as possible just to pass data and continue with processing of the data that is not waiting. It will not be easy to hit this goal with mutex
If you're working across threads with non atomic types, you'll either have to copy stuff, or use a mutex, there is no other (save) way.
My advice, do an actual benchmark of a mutex, see what difference in time it actually does.
-
I am used to develop bare metal DSP code in very low level C - I like working with explosives :-D
:D
I understand that mutex is the right way to protect the data but it is not for free and it may potentially block for some time the real time processing in backend library that I want to avoid. My intention is to have callback as fast as possible just to pass data and continue with processing of the data that is not waiting. It will not be easy to hit this goal with mutex
If you're working across threads with non atomic types, you'll either have to copy stuff, or use a mutex, there is no other (save) way.
My advice, do an actual benchmark of a mutex, see what difference in time it actually does.
@J-Hilk I will try to insert mutex in the code to check if it solves the issue with application crash but I still to not think this is a problem because by principle only one thread is accessing the data that is created and set in callback and then sent by signal.
-
@J-Hilk said in Random application crash on Apple Silicon M1 (Qt 6.2.3):
void RadioControl::eventFromDab(RadioControlEvent * pEvent)
{
switch (pEvent->type) // <=== sanitizer complains that this is the data racethis one is, you're passing a pointer to an object around, that lives on an other thread. The QueuedConnecion will only copy the pointer not the underlying data.
Yes, that is actually my point. I do not want to do copy of the data (in this case it is small, but it can be significantly bigger), I want to pass a pointer to the other thread that reads the data and finally deletes them. Data in callback are not touched after radioCtrl->emit_dabEvent(pEvent).
If this is not the correct way, how to pass the data without additional copying correctly? Would it be better to use QSharedPointer<RadioControlEvent> instead?
RadioControlEvent is this structure:
struct RadioControlEvent { RadioControlEventType type; // <-- enum class RadioControlEventType dabProcNotificationStatus_t status; // <-- enum intptr_t pData; };
@KejPi said in Random application crash on Apple Silicon M1 (Qt 6.2.3):
Yes, that is actually my point. I do not want to do copy of the data (in this case it is small, but it can be significantly bigger), I want to pass a pointer to the other thread that reads the data and finally deletes them. Data in callback are not touched after radioCtrl->emit_dabEvent(pEvent).
If this is not the correct way, how to pass the data without additional copying correctly? Would it be better to use QSharedPointer<RadioControlEvent> instead?
Isn‘t this a „perfect“ use-case for a queue? T1 writes the data to the queue and signals T2 that data is available. T2 then retrieves the data from the queue, processes and deletes it.
Boost.Lockfree queue or spsc_queue (single producer, single consumer) come into my mind here, I don‘t know if Qt offers similar thread-safe classes (std::queue does not seem to be thread-safe). -
@KejPi said in Random application crash on Apple Silicon M1 (Qt 6.2.3):
Yes, that is actually my point. I do not want to do copy of the data (in this case it is small, but it can be significantly bigger), I want to pass a pointer to the other thread that reads the data and finally deletes them. Data in callback are not touched after radioCtrl->emit_dabEvent(pEvent).
If this is not the correct way, how to pass the data without additional copying correctly? Would it be better to use QSharedPointer<RadioControlEvent> instead?
Isn‘t this a „perfect“ use-case for a queue? T1 writes the data to the queue and signals T2 that data is available. T2 then retrieves the data from the queue, processes and deletes it.
Boost.Lockfree queue or spsc_queue (single producer, single consumer) come into my mind here, I don‘t know if Qt offers similar thread-safe classes (std::queue does not seem to be thread-safe).@DerReisende Yes, it is exactly one producer-on consumer queue. Actually my idea was to "emulate" it by Qt::QueuedConnection. But in theory I can implement simple queue by myself since it is quite simple case. Nonetheless the problem mentioned by @J-Hilk that data live in T1 that creates them and used by T2 that uses and deletes them remains. But queue is a good idea how to solve it :-)
-
@DerReisende Yes, it is exactly one producer-on consumer queue. Actually my idea was to "emulate" it by Qt::QueuedConnection. But in theory I can implement simple queue by myself since it is quite simple case. Nonetheless the problem mentioned by @J-Hilk that data live in T1 that creates them and used by T2 that uses and deletes them remains. But queue is a good idea how to solve it :-)
@KejPi said in Random application crash on Apple Silicon M1 (Qt 6.2.3):
@DerReisende Yes, it is exactly one producer-on consumer queue. Actually my idea was to "emulate" it by Qt::QueuedConnection. But in theory I can implement simple queue by myself since it is quite simple case.
Why reinvent the wheel when there are proven/well-tested solutions available? :D
Nonetheless the problem mentioned by @J-Hilk that data live in T1 that creates them and used by T2 that uses and deletes them remains. But queue is a good idea how to solve it :-)
What about using move semantics (std::move)? You should be able to move your RadioControlEvent in there and later move it out of the queue. But it would then require a move constructor.
-
@DerReisende Yes, it is exactly one producer-on consumer queue. Actually my idea was to "emulate" it by Qt::QueuedConnection. But in theory I can implement simple queue by myself since it is quite simple case. Nonetheless the problem mentioned by @J-Hilk that data live in T1 that creates them and used by T2 that uses and deletes them remains. But queue is a good idea how to solve it :-)
@KejPi Qt has QQueue, which is reentrant and thread-safe to some extent, https://doc.qt.io/qt-6/qqueue.html - but I am not sure if this will suit your needs. I used it, upon occasion, for the file processing backend to communicate/report to the UI frontend however my constraints were not as tight as yours I am afraid.
-
@KejPi said in Random application crash on Apple Silicon M1 (Qt 6.2.3):
@DerReisende Yes, it is exactly one producer-on consumer queue. Actually my idea was to "emulate" it by Qt::QueuedConnection. But in theory I can implement simple queue by myself since it is quite simple case.
Why reinvent the wheel when there are proven/well-tested solutions available? :D
Nonetheless the problem mentioned by @J-Hilk that data live in T1 that creates them and used by T2 that uses and deletes them remains. But queue is a good idea how to solve it :-)
What about using move semantics (std::move)? You should be able to move your RadioControlEvent in there and later move it out of the queue. But it would then require a move constructor.
@DerReisende said in Random application crash on Apple Silicon M1 (Qt 6.2.3):
What about using move semantics (std::move)? You should be able to move your RadioControlEvent in there and later move it out of the queue. But it would then require a move constructor.
Yes, but this implies Qt6, so far I am able to build my app for both Qt5 and Qt6 but maybe it is time to move forward.
@artwaw You are probably right, I need really light and fast solution, it is of course no problem to run the application on M1 but the target is to be able to run it on RPi2.
-
@DerReisende said in Random application crash on Apple Silicon M1 (Qt 6.2.3):
What about using move semantics (std::move)? You should be able to move your RadioControlEvent in there and later move it out of the queue. But it would then require a move constructor.
Yes, but this implies Qt6, so far I am able to build my app for both Qt5 and Qt6 but maybe it is time to move forward.
@artwaw You are probably right, I need really light and fast solution, it is of course no problem to run the application on M1 but the target is to be able to run it on RPi2.
@KejPi QList and QQueue are lightweight, at least claim to be in the documentation. I never had memory problems on raspi, then again I never did anything that would strain the resources on raspi2.
Having said that I trust there more experienced persons in this thread that would be able to judge if QList/Queue is the way to go in terms of usability or not.
-
@KejPi QList and QQueue are lightweight, at least claim to be in the documentation. I never had memory problems on raspi, then again I never did anything that would strain the resources on raspi2.
Having said that I trust there more experienced persons in this thread that would be able to judge if QList/Queue is the way to go in terms of usability or not.
@artwaw QList is reentrant but not thread-safe. At least it is not mentioned in the docs and there are several questions over at stackoverflow.
-
@artwaw QList is reentrant but not thread-safe. At least it is not mentioned in the docs and there are several questions over at stackoverflow.
@DerReisende It is confusing, I agree, however I considered the documentation before posting (and asking if someone knows better, I also wrote "to some extent" as I am not certain myself):
- QQueue is based on QList;
- documentation to the class links to the chapter about Qt's container classes https://doc.qt.io/qt-6/containers.html where we have:
they are thread-safe in situations where they are used as read-only containers by all threads used to access them.
- in the sentence above there is a link to threat-safe https://doc.qt.io/qt-6/threads-reentrancy.html which doesn't shed much lite on this particular class.
So I don't know. My limited experience with background thread passing data to QQueue in the main thread did not seem to fail.
-
I was finally able to build all libs for x64_64 and thus I can build my app for x86_64. It seems not to crash but there are few other observations that might be related:
- it seems that crashes are more frequent when I start my Mac after some time and the they are less and less happening (I know that this sounds very strange but it is my observation from today and also yesterday). So far it seems to be fully random and I still do not know what to do to make it crash.
- When I start my laptop today and started the app it was crashing almost immediately. I am running it with thread sanitizer and the crash happened even before any message about data race appeared. At the moment I am running the app for >10minutes without crash.
- x86_64 does not seem to crash, no crash observed so far but it could be related to previous point
- my feeling (only a feeling) is that it crashes more frequently when the application get focus or when I move mouse over it etc. However intensive interaction with UI (fast clicking on GUI elements) does not seem to cause crash.
EDIT: I have fixed all reported data race cases using message queue 2 days ago and today when I started my Mac it was again crashing almost immediately. After some time it is crashing less frequently. This is absolutely crazy, I do not understand it at all :-( I will try x86_64 build tomorrow but for the moment I do not know what else to do.
-
I was finally able to build all libs for x64_64 and thus I can build my app for x86_64. It seems not to crash but there are few other observations that might be related:
- it seems that crashes are more frequent when I start my Mac after some time and the they are less and less happening (I know that this sounds very strange but it is my observation from today and also yesterday). So far it seems to be fully random and I still do not know what to do to make it crash.
- When I start my laptop today and started the app it was crashing almost immediately. I am running it with thread sanitizer and the crash happened even before any message about data race appeared. At the moment I am running the app for >10minutes without crash.
- x86_64 does not seem to crash, no crash observed so far but it could be related to previous point
- my feeling (only a feeling) is that it crashes more frequently when the application get focus or when I move mouse over it etc. However intensive interaction with UI (fast clicking on GUI elements) does not seem to cause crash.
EDIT: I have fixed all reported data race cases using message queue 2 days ago and today when I started my Mac it was again crashing almost immediately. After some time it is crashing less frequently. This is absolutely crazy, I do not understand it at all :-( I will try x86_64 build tomorrow but for the moment I do not know what else to do.
@KejPi said in Random application crash on Apple Silicon M1 (Qt 6.2.3):
I was finally able to build all libs for x64_64 and thus I can build my app for x86_64. It seems not to crash but there are few other observations that might be related:
- it seems that crashes are more frequent when I start my Mac after some time and the they are less and less happening (I know that this sounds very strange but it is my observation from today and also yesterday). So far it seems to be fully random and I still do not know what to do to make it crash.
- When I start my laptop today and started the app it was crashing almost immediately. I am running it with thread sanitizer and the crash happened even before any message about data race appeared. At the moment I am running the app for >10minutes without crash.
- x86_64 does not seem to crash, no crash observed so far but it could be related to previous point
- my feeling (only a feeling) is that it crashes more frequently when the application get focus or when I move mouse over it etc. However intensive interaction with UI (fast clicking on GUI elements) does not seem to cause crash.
EDIT: I have fixed all reported data race cases using message queue 2 days ago and today when I started my Mac it was again crashing almost immediately. After some time it is crashing less frequently. This is absolutely crazy, I do not understand it at all :-( I will try x86_64 build tomorrow but for the moment I do not know what else to do.
I am having the exact same random crash symptoms with the same stack trace you reported earlier on my M1 MacBook Pro on my completely unrelated application: https://github.com/sultanqasim/cinemavi/tree/master/CMGui
My stack trace:
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 ??? 0x0 ??? 1 ImageIO 0x1b06cac68 IIOReadPlugin::callInitialize() + 120 2 ImageIO 0x1b06ca98c IIO_Reader::initImageAtOffset(CGImagePlugin*, unsigned long, unsigned long, unsigned long) + 108 3 ImageIO 0x1b06c8228 IIOImageSource::makeImagePlus(unsigned long, IIODictionary*) + 748 4 ImageIO 0x1b06d4834 IIOImageSource::createImageAtIndex(unsigned long, IIODictionary*) + 80 5 ImageIO 0x1b06d4704 CGImageSourceCreateImageAtIndex + 256 6 HIServices 0x1ad30beb4 setCursorFromBundle + 2232 7 HIServices 0x1ad30aebc CoreCursorSetAndReturnSeed + 204 8 AppKit 0x1aa44a1ec -[NSCursor _reallySet] + 684 9 AppKit 0x1aa453354 +[NSCursor _setOverrideCursor:type:] + 300 10 AppKit 0x1aa452b38 -[NSWindow(NSWindowResizing) _edgeResizingCursorUpdate:atLocation:] + 288 11 AppKit 0x1aa41a304 -[NSApplication(NSEvent) sendEvent:] + 664 12 libqcocoa.dylib 0x10376987c 0x103760000 + 39036 13 AppKit 0x1aa6d48e8 -[NSApplication _handleEvent:] + 76 14 AppKit 0x1aa29c6b8 -[NSApplication run] + 636 15 libqcocoa.dylib 0x103774fb8 0x103760000 + 85944 16 QtCore 0x104a18b3c QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) + 500 17 QtCore 0x104a0fe88 QCoreApplication::exec() + 128 18 Cinemavi 0x10291d528 main + 564 (main.cpp:22) 19 dyld 0x102cf9088 start + 516
-
I wasn't getting this crash on Mac OS 12.2.1 and earlier, but I just upgraded to Mac OS 12.3 today, and I've been getting this crash ever since then. My application was rock solid stable before today's upgrade, but is unusable due to the frequency of this particular crash now.
-
Also, for reference, I have no issues with AddressSanitizer or ThreadSanitizer, and UBSan gives the same warnings as the OP had, such as:
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior moc_cmpicturelabel.cpp:116:28 in moc_cmrenderworker.cpp:112:28: runtime error: member access within address 0x000109723180 which does not point to an object of type 'QObjectData' 0x000109723180: note: object is of type 'QObjectPrivate' 00 00 00 00 90 0d 87 04 01 00 00 00 20 59 81 0a 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ^~~~~~~~~~~~~~~~~~~~~~~ vptr for 'QObjectPrivate'
-
Ok, seems like a potential bug with the latest macOS on M1 arch,
have you guys tried and reproduced it with a minimal example?
-
I wasn't getting this crash on Mac OS 12.2.1 and earlier, but I just upgraded to Mac OS 12.3 today, and I've been getting this crash ever since then. My application was rock solid stable before today's upgrade, but is unusable due to the frequency of this particular crash now.
@sultan said in Random application crash on Apple Silicon M1 (Qt 6.2.3):
I wasn't getting this crash on Mac OS 12.2.1 and earlier, but I just upgraded to Mac OS 12.3 today, and I've been getting this crash ever since then. My application was rock solid stable before today's upgrade, but is unusable due to the frequency of this particular crash now.
This is very interesting observation. Unfortunately I have upgraded my new Mac immediately after getting it so I did not try with macOS < 12.3.
@J-Hilk said in Random application crash on Apple Silicon M1 (Qt 6.2.3):
have you guys tried and reproduced it with a minimal example?
I am afraid it would be difficult. My feeling is that it happens in more complex multi-thread applications. I will continue my investigations, I already have some more ideas what to try and in case I find something I will for sure report is here.
-
Interestingly, I'm unable to reproduce my crash today. It was consistently crashing within a couple minutes or sometimes less yesterday for me, but it hasn't crashed even once for me today. This sounds like it'll be a tricky bug to diagnose.
EDIT: I just rebooted my computer, and now it crashes all the time again. For reference, I hadn't rebooted in over a month before yesterday's update to MacOS 12.3. Maybe these crashes are unrelated to MacOS 12.3, and just related to how long it has been since the computer was last rebooted. Bizarre nevertheless. I'll see if I can make a minimal application crash with this when I have time.