From b1a882f178d71d1462b5ee7e7ffde142928b5086 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Fri, 7 Feb 2014 16:52:00 +0100 Subject: [PATCH 1/5] Fix drawCachedGlyphs on RGBA8888 drawCachedGlyphs draws with the wrong color on RGBA8888. The issue is that the draw routines bitmapblit_quint32 and alphamapblit_quint32 while safe to use on rgba formats, needs to have the input color converted. This patch adds small wrapper functions for bitmapblit and alphamapblit that converts the formats. Two tests are extended to ensure we have test coverage. Change-Id: I5f99f3795eba46a69d4df5b167e6099024e9a060 Reviewed-by: Gunnar Sletta --- src/gui/painting/qdrawhelper.cpp | 89 +++++++++++-------- src/gui/painting/qdrawhelper_avx.cpp | 1 + src/gui/painting/qdrawhelper_sse2.cpp | 7 ++ src/gui/painting/qdrawhelper_x86_p.h | 6 ++ .../gui/text/qstatictext/tst_qstatictext.cpp | 28 ++++-- 5 files changed, 87 insertions(+), 44 deletions(-) diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index c71d75cf94..865dab6597 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -5605,7 +5605,7 @@ static void qt_gradient_quint16(int count, const QSpan *spans, void *userData) } } -inline static void qt_bitmapblit_quint32(QRasterBuffer *rasterBuffer, +inline static void qt_bitmapblit_argb32(QRasterBuffer *rasterBuffer, int x, int y, quint32 color, const uchar *map, int mapWidth, int mapHeight, int mapStride) @@ -5614,6 +5614,15 @@ inline static void qt_bitmapblit_quint32(QRasterBuffer *rasterBuffer, map, mapWidth, mapHeight, mapStride); } +inline static void qt_bitmapblit_rgba8888(QRasterBuffer *rasterBuffer, + int x, int y, quint32 color, + const uchar *map, + int mapWidth, int mapHeight, int mapStride) +{ + qt_bitmapblit_template(rasterBuffer, x, y, ARGB2RGBA(color), + map, mapWidth, mapHeight, mapStride); +} + inline static void qt_bitmapblit_quint16(QRasterBuffer *rasterBuffer, int x, int y, quint32 color, const uchar *map, @@ -5725,11 +5734,11 @@ static inline void grayBlendPixel(quint32 *dst, int coverage, int sr, int sg, in } #endif -static void qt_alphamapblit_quint32(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, - const uchar *map, - int mapWidth, int mapHeight, int mapStride, - const QClipData *clip) +static void qt_alphamapblit_argb32(QRasterBuffer *rasterBuffer, + int x, int y, quint32 color, + const uchar *map, + int mapWidth, int mapHeight, int mapStride, + const QClipData *clip) { const quint32 c = color; const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint32); @@ -5820,10 +5829,19 @@ static void qt_alphamapblit_quint32(QRasterBuffer *rasterBuffer, } } -static void qt_alphargbblit_quint32(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, - const uint *src, int mapWidth, int mapHeight, int srcStride, - const QClipData *clip) +static void qt_alphamapblit_rgba8888(QRasterBuffer *rasterBuffer, + int x, int y, quint32 color, + const uchar *map, + int mapWidth, int mapHeight, int mapStride, + const QClipData *clip) +{ + qt_alphamapblit_argb32(rasterBuffer, x, y, ARGB2RGBA(color), map, mapWidth, mapHeight, mapStride, clip); +} + +static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer, + int x, int y, quint32 color, + const uint *src, int mapWidth, int mapHeight, int srcStride, + const QClipData *clip) { const quint32 c = color; @@ -5965,27 +5983,27 @@ DrawHelper qDrawHelper[QImage::NImageFormats] = { blend_color_argb, qt_gradient_argb32, - qt_bitmapblit_quint32, - qt_alphamapblit_quint32, - qt_alphargbblit_quint32, + qt_bitmapblit_argb32, + qt_alphamapblit_argb32, + qt_alphargbblit_argb32, qt_rectfill_argb32 }, // Format_ARGB32, { blend_color_generic, qt_gradient_argb32, - qt_bitmapblit_quint32, - qt_alphamapblit_quint32, - qt_alphargbblit_quint32, + qt_bitmapblit_argb32, + qt_alphamapblit_argb32, + qt_alphargbblit_argb32, qt_rectfill_nonpremul_argb32 }, // Format_ARGB32_Premultiplied { blend_color_argb, qt_gradient_argb32, - qt_bitmapblit_quint32, - qt_alphamapblit_quint32, - qt_alphargbblit_quint32, + qt_bitmapblit_argb32, + qt_alphamapblit_argb32, + qt_alphargbblit_argb32, qt_rectfill_argb32 }, // Format_RGB16 @@ -6049,42 +6067,39 @@ DrawHelper qDrawHelper[QImage::NImageFormats] = { blend_color_generic, blend_src_generic, - qt_bitmapblit_quint32, + qt_bitmapblit_rgba8888, #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - qt_alphamapblit_quint32, - qt_alphargbblit_quint32, + qt_alphamapblit_rgba8888, #else 0, - 0, #endif + 0, qt_rectfill_rgba }, // Format_RGBA8888 { blend_color_generic, blend_src_generic, - qt_bitmapblit_quint32, + qt_bitmapblit_rgba8888, #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - qt_alphamapblit_quint32, - qt_alphargbblit_quint32, + qt_alphamapblit_rgba8888, #else 0, - 0, #endif + 0, qt_rectfill_nonpremul_rgba }, // Format_RGB8888_Premultiplied { blend_color_generic, blend_src_generic, - qt_bitmapblit_quint32, + qt_bitmapblit_rgba8888, #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - qt_alphamapblit_quint32, - qt_alphargbblit_quint32, + qt_alphamapblit_rgba8888, #else 0, - 0, #endif + 0, qt_rectfill_rgba } }; @@ -6173,9 +6188,9 @@ void qInitDrawhelperAsm() qDrawHelper[QImage::Format_ARGB32].bitmapBlit = qt_bitmapblit32_avx; qDrawHelper[QImage::Format_ARGB32_Premultiplied].bitmapBlit = qt_bitmapblit32_avx; qDrawHelper[QImage::Format_RGB16].bitmapBlit = qt_bitmapblit16_avx; - qDrawHelper[QImage::Format_RGBX8888].bitmapBlit = qt_bitmapblit32_avx; - qDrawHelper[QImage::Format_RGBA8888].bitmapBlit = qt_bitmapblit32_avx; - qDrawHelper[QImage::Format_RGBA8888_Premultiplied].bitmapBlit = qt_bitmapblit32_avx; + qDrawHelper[QImage::Format_RGBX8888].bitmapBlit = qt_bitmapblit8888_avx; + qDrawHelper[QImage::Format_RGBA8888].bitmapBlit = qt_bitmapblit8888_avx; + qDrawHelper[QImage::Format_RGBA8888_Premultiplied].bitmapBlit = qt_bitmapblit8888_avx; extern void qt_scale_image_argb32_on_argb32_avx(uchar *destPixels, int dbpl, const uchar *srcPixels, int sbpl, @@ -6198,9 +6213,9 @@ void qInitDrawhelperAsm() qDrawHelper[QImage::Format_ARGB32].bitmapBlit = qt_bitmapblit32_sse2; qDrawHelper[QImage::Format_ARGB32_Premultiplied].bitmapBlit = qt_bitmapblit32_sse2; qDrawHelper[QImage::Format_RGB16].bitmapBlit = qt_bitmapblit16_sse2; - qDrawHelper[QImage::Format_RGBX8888].bitmapBlit = qt_bitmapblit32_sse2; - qDrawHelper[QImage::Format_RGBA8888].bitmapBlit = qt_bitmapblit32_sse2; - qDrawHelper[QImage::Format_RGBA8888_Premultiplied].bitmapBlit = qt_bitmapblit32_sse2; + qDrawHelper[QImage::Format_RGBX8888].bitmapBlit = qt_bitmapblit8888_sse2; + qDrawHelper[QImage::Format_RGBA8888].bitmapBlit = qt_bitmapblit8888_sse2; + qDrawHelper[QImage::Format_RGBA8888_Premultiplied].bitmapBlit = qt_bitmapblit8888_sse2; extern void qt_scale_image_argb32_on_argb32_sse2(uchar *destPixels, int dbpl, const uchar *srcPixels, int sbpl, diff --git a/src/gui/painting/qdrawhelper_avx.cpp b/src/gui/painting/qdrawhelper_avx.cpp index 7da6ce6a20..7d42525150 100644 --- a/src/gui/painting/qdrawhelper_avx.cpp +++ b/src/gui/painting/qdrawhelper_avx.cpp @@ -60,6 +60,7 @@ #define qt_memfill32_sse2 qt_memfill32_avx #define qt_memfill16_sse2 qt_memfill16_avx #define qt_bitmapblit32_sse2 qt_bitmapblit32_avx +#define qt_bitmapblit8888_sse2 qt_bitmapblit8888_avx #define qt_bitmapblit16_sse2 qt_bitmapblit16_avx #define QSimdSse2 QSimdAvx #define qt_fetch_radial_gradient_sse2 qt_fetch_radial_gradient_avx diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp index a9dc5a7fb7..ea191c2ec5 100644 --- a/src/gui/painting/qdrawhelper_sse2.cpp +++ b/src/gui/painting/qdrawhelper_sse2.cpp @@ -470,6 +470,13 @@ void qt_bitmapblit32_sse2(QRasterBuffer *rasterBuffer, int x, int y, } } +void qt_bitmapblit8888_sse2(QRasterBuffer *rasterBuffer, int x, int y, + quint32 color, + const uchar *src, int width, int height, int stride) +{ + qt_bitmapblit32_sse2(rasterBuffer, x, y, ARGB2RGBA(color), src, width, height, stride); +} + void qt_bitmapblit16_sse2(QRasterBuffer *rasterBuffer, int x, int y, quint32 color, const uchar *src, int width, int height, int stride) diff --git a/src/gui/painting/qdrawhelper_x86_p.h b/src/gui/painting/qdrawhelper_x86_p.h index d64b9cec39..aee508f641 100644 --- a/src/gui/painting/qdrawhelper_x86_p.h +++ b/src/gui/painting/qdrawhelper_x86_p.h @@ -63,6 +63,9 @@ void qt_memfill16_sse2(quint16 *dest, quint16 value, int count); void qt_bitmapblit32_sse2(QRasterBuffer *rasterBuffer, int x, int y, quint32 color, const uchar *src, int width, int height, int stride); +void qt_bitmapblit8888_sse2(QRasterBuffer *rasterBuffer, int x, int y, + quint32 color, + const uchar *src, int width, int height, int stride); void qt_bitmapblit16_sse2(QRasterBuffer *rasterBuffer, int x, int y, quint32 color, const uchar *src, int width, int height, int stride); @@ -85,6 +88,9 @@ void qt_memfill16_avx(quint16 *dest, quint16 value, int count); void qt_bitmapblit32_avx(QRasterBuffer *rasterBuffer, int x, int y, quint32 color, const uchar *src, int width, int height, int stride); +void qt_bitmapblit8888_avx(QRasterBuffer *rasterBuffer, int x, int y, + quint32 color, + const uchar *src, int width, int height, int stride); void qt_bitmapblit16_avx(QRasterBuffer *rasterBuffer, int x, int y, quint32 color, const uchar *src, int width, int height, int stride); diff --git a/tests/auto/gui/text/qstatictext/tst_qstatictext.cpp b/tests/auto/gui/text/qstatictext/tst_qstatictext.cpp index 46f97840af..4ae70fe137 100644 --- a/tests/auto/gui/text/qstatictext/tst_qstatictext.cpp +++ b/tests/auto/gui/text/qstatictext/tst_qstatictext.cpp @@ -87,6 +87,7 @@ private slots: void plainTextVsRichText(); + void setPenPlainText_data(); void setPenPlainText(); void setPenRichText(); void richTextOverridesPen(); @@ -106,6 +107,8 @@ private: QImage const m_whiteSquare; }; +Q_DECLARE_METATYPE(QImage::Format); + void tst_QStaticText::initTestCase() { // a "blank" square; we compare against in our testfunctions to verify @@ -615,30 +618,41 @@ void tst_QStaticText::plainTextVsRichText() QCOMPARE(imagePlainText, imageRichText); } +void tst_QStaticText::setPenPlainText_data() +{ + QTest::addColumn("format"); + + QTest::newRow("argb32pm") << QImage::Format_ARGB32_Premultiplied; + QTest::newRow("rgb32") << QImage::Format_RGB32; + QTest::newRow("rgba8888pm") << QImage::Format_RGBA8888_Premultiplied; + QTest::newRow("rgbx8888") << QImage::Format_RGBX8888; +} + void tst_QStaticText::setPenPlainText() { + QFETCH(QImage::Format, format); + QFont font = QGuiApplication::font(); font.setStyleStrategy(QFont::NoAntialias); QFontMetricsF fm(font); - QPixmap image(qCeil(fm.width("XXXXX")), qCeil(fm.height())); + QImage image(qCeil(fm.width("XXXXX")), qCeil(fm.height()), format); image.fill(Qt::white); { QPainter p(&image); p.setFont(font); - p.setPen(Qt::green); + p.setPen(Qt::yellow); QStaticText staticText("XXXXX"); staticText.setTextFormat(Qt::PlainText); p.drawStaticText(0, 0, staticText); } - QImage img = image.toImage(); - for (int x=0; x Date: Tue, 25 Feb 2014 14:35:46 +0100 Subject: [PATCH 2/5] CSS parser: fix the pseudo-classes array length The pseudoclass array is declared with length "NumPseudos - 1", but the declaration has actually 44 elements, not 45. This caused a zero-initialized last element to be silently appended to the array. The zero-initialized element broke the sorting of the array, which in turn broke std::lower_bound usage (although of course the problem was there from before switching to the standard library algorithms). Task-number: QTBUG-36933 Change-Id: I8a02891fc36761b6ae72d15a0a8d6c6a96813947 Reviewed-by: Olivier Goffart --- src/gui/text/qcssparser_p.h | 2 +- .../qstylesheetstyle/tst_qstylesheetstyle.cpp | 32 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/gui/text/qcssparser_p.h b/src/gui/text/qcssparser_p.h index b087a2384a..123a53c5cc 100644 --- a/src/gui/text/qcssparser_p.h +++ b/src/gui/text/qcssparser_p.h @@ -508,7 +508,7 @@ const quint64 PseudoClass_EditFocus = Q_UINT64_C(0x0000080000000000); const quint64 PseudoClass_Alternate = Q_UINT64_C(0x0000100000000000); // The Any specifier is never generated, but can be used as a wildcard in searches. const quint64 PseudoClass_Any = Q_UINT64_C(0x0000ffffffffffff); -const int NumPseudos = 46; +const int NumPseudos = 45; struct Pseudo { diff --git a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp index 24e3ac2c99..5a36ffc671 100644 --- a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp +++ b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp @@ -99,6 +99,7 @@ private slots: void task232085_spinBoxLineEditBg(); void changeStyleInChangeEvent(); void QTBUG15910_crashNullWidget(); + void QTBUG36933_brokenPseudoClassLookup(); //at the end because it mess with the style. void widgetStyle(); @@ -1656,6 +1657,37 @@ void tst_QStyleSheetStyle::QTBUG15910_crashNullWidget() QVERIFY(QTest::qWaitForWindowExposed(&w)); } +void tst_QStyleSheetStyle::QTBUG36933_brokenPseudoClassLookup() +{ + const int rowCount = 10; + const int columnCount = 10; + + QTableWidget widget(rowCount, columnCount); + + for (int row = 0; row < rowCount; ++row) { + for (int column = 0; column < columnCount; ++column) + widget.setItem(row, column, new QTableWidgetItem(QStringLiteral("row %1 column %2").arg(row + 1).arg(column + 1))); + + // put no visible text for the vertical headers, but still put some text or they will collapse + widget.setVerticalHeaderItem(row, new QTableWidgetItem(QStringLiteral(" "))); + } + + // parsing of this stylesheet must not crash, and it must be correctly applied + widget.setStyleSheet(QStringLiteral("QHeaderView::section:vertical { background-color: #FF0000 }")); + + widget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&widget)); + + widget.activateWindow(); + QApplication::setActiveWindow(&widget); + QVERIFY(QTest::qWaitForWindowActive(&widget)); + + QHeaderView *verticalHeader = widget.verticalHeader(); + QImage image(verticalHeader->size(), QImage::Format_ARGB32); + verticalHeader->render(&image); + QVERIFY(testForColors(image, QColor(0xFF, 0x00, 0x00))); +} + QTEST_MAIN(tst_QStyleSheetStyle) #include "tst_qstylesheetstyle.moc" From 15ec9907f968f3c4ebe461617b448f5c8d05e5c5 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Mon, 24 Feb 2014 14:54:30 +0100 Subject: [PATCH 3/5] Cocoa Menu: Set keyboard modifiers when item is activated MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Seems to be a regression from 4.8, which is not surprising since everything was rewritten for QPA. Task-number: QTBUG-36851 Change-Id: If89f8c9e6897fd1e02800f49e51baeb1ea181238 Reviewed-by: Morten Johan Sørvig Reviewed-by: James Turner --- src/plugins/platforms/cocoa/qcocoamenu.mm | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index 329c7a264a..aa6b71df31 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -127,6 +127,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaMenuDelegate); { QCocoaMenuItem *cocoaItem = reinterpret_cast([item tag]); QScopedLoopLevelCounter loopLevelCounter(QGuiApplicationPrivate::instance()->threadData); + QGuiApplicationPrivate::modifier_buttons = [QNSView convertKeyModifiers:[NSEvent modifierFlags]]; cocoaItem->activated(); } From bf0336a02502b3ed4d399c1cf5b4a56b1e858d42 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Wed, 19 Feb 2014 17:41:33 +0100 Subject: [PATCH 4/5] Cocoa Menus: Give platform menu ownership back to QWidgets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't want to be in the situation where a QCocoaMenuItem owns a QCocoaMenu (because that item is a submenu), and then the actual QMenu "sees" that same QCocoaMenu being deleted. Instead, since all the QCocoaMenu* classes inherit QObject, we rely on meta-object properties to set the hierarchy and climb the hierarchy when guessing the menu item's role. This ammends most of commit 370e89f06465a4d61c7b. Task-number: QTBUG-36785 Change-Id: I0e03acb593e93061c8c6c1fdd161669cf0d2a293 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoamenu.mm | 8 ++++---- src/plugins/platforms/cocoa/qcocoamenuitem.h | 3 +++ src/plugins/platforms/cocoa/qcocoamenuitem.mm | 10 +++++----- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index aa6b71df31..35e8fdebb4 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -269,7 +269,7 @@ void QCocoaMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem * QCocoaMenuItem *cocoaItem = static_cast(menuItem); QCocoaMenuItem *beforeItem = static_cast(before); - menuItem->setParent(this); + SET_COCOA_MENU_ANCESTOR(menuItem, this); cocoaItem->sync(); if (beforeItem) { int index = m_menuItems.indexOf(beforeItem); @@ -326,8 +326,8 @@ void QCocoaMenu::removeMenuItem(QPlatformMenuItem *menuItem) return; } - if (menuItem->parent() == this) - menuItem->setParent(0); + if (COCOA_MENU_ANCESTOR(menuItem) == this) + SET_COCOA_MENU_ANCESTOR(menuItem, 0); m_menuItems.removeOne(cocoaItem); if (!cocoaItem->isMerged()) { @@ -551,7 +551,7 @@ void QCocoaMenu::syncModalState(bool modal) void QCocoaMenu::setMenuBar(QCocoaMenuBar *menuBar) { m_menuBar = menuBar; - setParent(menuBar); + SET_COCOA_MENU_ANCESTOR(this, menuBar); } QCocoaMenuBar *QCocoaMenu::menuBar() const diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.h b/src/plugins/platforms/cocoa/qcocoamenuitem.h index 1e69ed5a4b..b0169b9746 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.h +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.h @@ -118,6 +118,9 @@ private: quintptr m_tag; }; +#define COCOA_MENU_ANCESTOR(m) ((m)->property("_qCocoaMenuAncestor").value()) +#define SET_COCOA_MENU_ANCESTOR(m, ancestor) (m)->setProperty("_qCocoaMenuAncestor", QVariant::fromValue(ancestor)) + QT_END_NAMESPACE #endif diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm index 3bba1ee1d5..2246d2ce46 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm @@ -126,13 +126,13 @@ void QCocoaMenuItem::setMenu(QPlatformMenu *menu) { if (menu == m_menu) return; - if (m_menu && m_menu->parent() == this) - m_menu->setParent(0); + if (m_menu && COCOA_MENU_ANCESTOR(m_menu) == this) + SET_COCOA_MENU_ANCESTOR(m_menu, 0); QCocoaAutoReleasePool pool; m_menu = static_cast(menu); if (m_menu) { - m_menu->setParent(this); + SET_COCOA_MENU_ANCESTOR(m_menu, this); } else { // we previously had a menu, but no longer // clear out our item so the nexy sync() call builds a new one @@ -217,12 +217,12 @@ NSMenuItem *QCocoaMenuItem::sync() mergeItem = [loader preferencesMenuItem]; break; case TextHeuristicRole: { - QObject *p = parent(); + QObject *p = COCOA_MENU_ANCESTOR(this); int depth = 1; QCocoaMenuBar *menubar = 0; while (depth < 3 && p && !(menubar = qobject_cast(p))) { ++depth; - p = p->parent(); + p = COCOA_MENU_ANCESTOR(p); } if (depth == 3 || !menubar) break; // Menu item too deep in the hierarchy, or not connected to any menubar From f15d9e6ccd006a2b47b50ae755fbe9534748a2eb Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Thu, 6 Mar 2014 14:21:53 +0100 Subject: [PATCH 5/5] do not use fileno calls in forked child This fixes an issue that causes QProcess::start to silently fail on OS X 10.9. Apparently, fileno(stdout) locks the handle on OS X 10.9. It may happen that the parent process fflush()s stdout while the child has just been forked. The stdout lock of the parent is never released in the child and fileno(stdout) therefore locks forever. According to the fork documentation on opengroup.org one may only call async-signal-safe functions between fork and exec in the child. The fileno() function does not appear in the list of async-signal-safe functions. Also, fileno(stdout) and friends can be easily replaced by the standard constants STDOUT_FILENO etc. Done-with: Fawzi Mohamed Task-number: QTBUG-37306 Change-Id: I2b1f5f47cc48a1ad020fb0493a955d2bc27aeb47 Reviewed-by: Thiago Macieira (cherry picked from b2216bbe06b8be2bef6d8bc2ffff1337f6d23358) --- src/corelib/io/qprocess_unix.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index 3c6d294916..8add9c56a7 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -880,18 +880,18 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv // copy the stdin socket if asked to (without closing on exec) if (inputChannelMode != QProcess::ForwardedInputChannel) - qt_safe_dup2(stdinChannel.pipe[0], fileno(stdin), 0); + qt_safe_dup2(stdinChannel.pipe[0], STDIN_FILENO, 0); // copy the stdout and stderr if asked to if (processChannelMode != QProcess::ForwardedChannels) { if (processChannelMode != QProcess::ForwardedOutputChannel) - qt_safe_dup2(stdoutChannel.pipe[1], fileno(stdout), 0); + qt_safe_dup2(stdoutChannel.pipe[1], STDOUT_FILENO, 0); // merge stdout and stderr if asked to if (processChannelMode == QProcess::MergedChannels) { - qt_safe_dup2(fileno(stdout), fileno(stderr), 0); + qt_safe_dup2(STDOUT_FILENO, STDERR_FILENO, 0); } else if (processChannelMode != QProcess::ForwardedErrorChannel) { - qt_safe_dup2(stderrChannel.pipe[1], fileno(stderr), 0); + qt_safe_dup2(stderrChannel.pipe[1], STDERR_FILENO, 0); } }