[Interest] crashing Qt through a QObject's dtor

Tom Ward tward at thefoundry.co.uk
Tue Jan 6 16:18:08 CET 2015


I think I recently found a similar problem on OS X (in 4.8 I should add),
where we were getting events coming through for cocoa objects that had
their corresponding QWidget deleted. In my case I was getting an
"NSFlagsChanged" event, which would then try and send the event to the
QWindow, but it had been set to NULL. This seemed to only be happening on
Yosemite machines, but that might be a coincidence.

To patch this particular case, I added a macEventFilter to check for this
specific problem, maybe it'd be of use to you?

bool

MyApplication::macEventFilter(EventHandlerCallRef caller, EventRef event)

{
@try {
 const NSEvent* cocoaEvent = reinterpret_cast<const NSEvent *>(event);
NSEventType cocoaEventType = [ cocoaEvent type ];
NSUInteger cocoaModifiers = [ cocoaEvent modifierFlags ];

 if ( cocoaEventType == NSFlagsChanged )
{
 // This is an on quit Qt bug, where we seem to be getting an
NSFlagsChanged on shutdown.
 // The problem with this is that Qt tries to send the event to the
NSWindow's widget, but
 // that's already been destroyed, so causes a null ptr exception.
NSWindow* window = [cocoaEvent window];
 QWidget* widget = (QWidget*)[window QT_MANGLE_NAMESPACE(qt_qwidget)];

return (widget == NULL);
 }
}
@catch ( NSException* )
{
 // do nothing

}

 return false;

}



On Tue, Jan 6, 2015 at 2:22 PM, René J.V. <rjvbertin at gmail.com> wrote:

> On Tuesday January 06 2015 13:07:02 David Faure wrote:
>
> Let's make something clear if it wasn't already: this concerns Qt4.8 . I
> have no way of knowing at this point if a similar issue will occur in Qt5.
> Let me also add that I cannot be certain at this time that using
> obj-deleteLater() instead of delete obj will prevent the issue from
> happening.
>
> For my personal education: is it correct that the C++ delete operator is
> always immediate and irrevocable in the sense that the target object's dtor
> cannot prevent deletion to take place nor postpone it?
>
> >It's wrong because it's fixing the symptom (null d pointer) instead of
> fixing
> >the cause (using an action that was already deleted).
>
> Indeed, I never intended it to be more than a workaround fix (and possible
> means to help find the underlying cause) rather than an elegant solution.
>
> Anyway, we seem to have a diagnosis, which would lead to the conclusion
> that the bug is in Qt, somewhere between macUpdateMenuBarImmediatly and
> qt_mac_set_modal_state_helper_recursive which should know that the QAction
> they're trying to use has been deleted.
>
> If we stop at that diagnosis instead of figuring out why this deviant
> behaviour occurs, a few questions arise that aren't without interest, IMHO.
>
> I think that it implies that some part of the documentation should read
> "objects corresponding to UI elements can be deleted using C++ delete in
> the thread where they were created, except on OS X where this could lead to
> exposure of bugs in Qt's Cocoa event handling, and where they should be
> released by calling the deleteLater() method".
>
> Of course the documentation could also make a strong point to use
> deleteLater() always for that kind of objects (could be through a macro of
> course). I can only speak out of experience with KDE and its community, but
> at this point my impression is that people there mostly know (care?) about
> Linux and possibly MS Windows, and arguing why they'd need to use
> deleteLater can be difficult esp. when you don't have hard proof.
>
> The alternative would be to modify Qt's Cocoa-specific event handling
> mechanism, even if it's only to catch access to deleted objects through
> exception handling, either to pretend nothing just happened, or combined
> with a kind of registry of deleted objects that is maintained by the event
> loop so that the developer can at least trace back which object should be
> released through deleteLater.
>
> I'd actually be interested to see how well that kind of an approach would
> work to debug this and similar issues I have at hand, if someone can give
> me some guidance. I'm thinking of a registry stored in wherever deleteLater
> also stores the information required to delete an object at the appropriate
> time (so that the registry can be flushed at that point) and a modification
> to the QObject or QWidget dtor to store the this ptr in said registry.
> On the other end, I'm thinking for now of a case-by-case protection using
> traditional signal trapping and handling (combined with setjmp/longjmp)
> rather than C++ exceptions. I've used that approach before, and on i386 it
> give very little overhead IIRC. ObjC exceptions could also be used, where
> feasible.
>
> Thanks,
> René
> _______________________________________________
> Interest mailing list
> Interest at qt-project.org
> http://lists.qt-project.org/mailman/listinfo/interest
>



-- 
Tom Ward
The Foundry,
5 Golden Square, London, W1F 9HT
Tel: +44(0) 20 7479 4350   Web: www.thefoundry.co.uk

The Foundry Visionmongers Ltd.
Registered in England and Wales No: 4642027
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20150106/24c7c860/attachment.html>


More information about the Interest mailing list