From ad0d2f463a0905c4705660d96e8a514539c51d36 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Mon, 25 Jul 2016 12:37:20 +0200 Subject: Cocoa integration - fix a crash in QMacPasteboard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QMacPasteboard's dtor skips LazyRequest promises and this leaves pasteboard manager in broken state, since we release the pasteboard itself of the next step in destructor. As a result, not only Qt's app doing D & D (and thus via QCocoaDrag creating a stack-allocated QMacPasteboard) can die suddenly when somebody inspects a pasteboard, this 'somebody' ... can also die amazingly. So now we DO resolve promises using PasteboardResolvePromises (but we also preserve the original intent of not providing or providing empty data for lazy requests). Task-number: QTBUG-54663 Task-number: QTBUG-54832 Change-Id: I3ce90bd0a012dd3cbb30c93b2b17dce9473acb28 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qmacclipboard.mm | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'src/plugins/platforms/cocoa/qmacclipboard.mm') diff --git a/src/plugins/platforms/cocoa/qmacclipboard.mm b/src/plugins/platforms/cocoa/qmacclipboard.mm index f4fd32ffd1..d0e2c39895 100644 --- a/src/plugins/platforms/cocoa/qmacclipboard.mm +++ b/src/plugins/platforms/cocoa/qmacclipboard.mm @@ -81,6 +81,7 @@ QMacPasteboard::QMacPasteboard(PasteboardRef p, uchar mt) mime_type = mt ? mt : uchar(QMacInternalPasteboardMime::MIME_ALL); paste = p; CFRetain(paste); + resolvingBeforeDestruction = false; } QMacPasteboard::QMacPasteboard(uchar mt) @@ -94,6 +95,7 @@ QMacPasteboard::QMacPasteboard(uchar mt) } else { qDebug("PasteBoard: Error creating pasteboard: [%d]", (int)err); } + resolvingBeforeDestruction = false; } QMacPasteboard::QMacPasteboard(CFStringRef name, uchar mt) @@ -107,23 +109,14 @@ QMacPasteboard::QMacPasteboard(CFStringRef name, uchar mt) } else { qDebug("PasteBoard: Error creating pasteboard: %s [%d]", QCFString::toQString(name).toLatin1().constData(), (int)err); } + resolvingBeforeDestruction = false; } QMacPasteboard::~QMacPasteboard() { // commit all promises for paste after exit close - for (int i = 0; i < promises.count(); ++i) { - const Promise &promise = promises.at(i); - // At this point app teardown has started and control is somewhere in the Q[Core]Application - // destructor. Skip "lazy" promises where the application has not provided data; - // the application will generally not be in a state to provide it. - if (promise.dataRequestType == LazyRequest) - continue; - QCFString flavor = QCFString(promise.convertor->flavorFor(promise.mime)); - NSInteger pbItemId = promise.itemId; - promiseKeeper(paste, reinterpret_cast(pbItemId), flavor, this); - } - + resolvingBeforeDestruction = true; + PasteboardResolvePromises(paste); if (paste) CFRelease(paste); } @@ -175,7 +168,7 @@ OSStatus QMacPasteboard::promiseKeeper(PasteboardRef paste, PasteboardItemID id, // to request the data from the application. QVariant promiseData; if (promise.dataRequestType == LazyRequest) { - if (!promise.mimeData.isNull()) + if (!qpaste->resolvingBeforeDestruction && !promise.mimeData.isNull()) promiseData = promise.mimeData->variantData(promise.mime); } else { promiseData = promise.variantData; -- cgit v1.2.3