diff options
-rwxr-xr-x | bin/createpackage.pl | 24 | ||||
-rwxr-xr-x | bin/patch_capabilities.pl | 26 | ||||
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_symbian.cpp | 38 | ||||
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_symbian_p.h | 8 | ||||
-rw-r--r-- | src/openvg/qpaintengine_vg.cpp | 7 | ||||
-rw-r--r-- | tests/auto/qapplication/test/test.pro | 2 | ||||
-rw-r--r-- | tests/auto/qtimer/tst_qtimer.cpp | 27 |
7 files changed, 98 insertions, 34 deletions
diff --git a/bin/createpackage.pl b/bin/createpackage.pl index cce0b54..85be5d3 100755 --- a/bin/createpackage.pl +++ b/bin/createpackage.pl @@ -212,21 +212,21 @@ my $certpath = File::Spec->catdir($scriptpath, File::Spec->updir(), "src/s60inst # Check some pre-conditions and print error messages if needed. unless (length($templatepkg)) { - print "\nError: Template PKG filename is not defined!\n"; + print "\nERROR: Template PKG filename is not defined!\n"; Usage(); } # Check template exist stat($templatepkg); unless( -e _ ) { - print "\nError: Package description file '$templatepkg' does not exist!\n"; + print "\nERROR: Package description file '$templatepkg' does not exist!\n"; Usage(); } # Check certifcate preconditions and set default certificate variables if needed if (length($certificate)) { unless(length($key)) { - print "\nError: Custom certificate key file parameter missing.!\n"; + print "\nERROR: Custom certificate key file parameter missing.!\n"; Usage(); } } else { @@ -261,7 +261,7 @@ if (length($certfile)) { # Do some validation unless(scalar(@certinfo) >= 2 && scalar(@certinfo) <= 3 && length($certinfo[0]) && length($certinfo[1]) ) { - print "\nError: $certfile line '$_' does not contain valid information!\n"; + print "\nERROR: $certfile line '$_' does not contain valid information!\n"; Usage(); } @@ -280,14 +280,14 @@ if (!$preservePkgOutput) { local $/; # read template file -open( TEMPLATE, $templatepkg) or die "Error '$templatepkg': $!\n"; +open( TEMPLATE, $templatepkg) or die "ERROR: '$templatepkg': $!"; $_=<TEMPLATE>; close (TEMPLATE); # If the pkg file does not contain macros, there is no need for platform or target. if (m/\$\(PLATFORM\)/) { unless (length($platform) && length($target)) { - print "\nError: Platform or target is not defined!\n"; + print "\nERROR: Platform or target is not defined!\n"; Usage(); } } @@ -297,7 +297,7 @@ s/\$\(PLATFORM\)/$platform/gm; s/\$\(TARGET\)/$target/gm; #write the output -open( OUTPUT, ">$pkgoutput" ) or die "Error '$pkgoutput' $!\n"; +open( OUTPUT, ">$pkgoutput" ) or die "ERROR: '$pkgoutput' $!"; print OUTPUT $_; close OUTPUT; @@ -306,7 +306,7 @@ if ($preprocessonly) { } if($stub) { - if(!($epocroot)) { die("EPOCROOT must be set to create stub sis files"); } + if(!($epocroot)) { die("ERROR: EPOCROOT must be set to create stub sis files"); } my $systeminstall = "$epocroot/epoc32/data/z/system/install"; mkpath($systeminstall); my $stub_sis_name = $systeminstall."/".$stub_sis_name; @@ -319,15 +319,15 @@ if($stub) { && !$onlyUnsigned) { print("Auto-patching capabilities for self signed package.\n"); my $patch_capabilities = File::Spec->catfile(dirname($0), "patch_capabilities"); - system ("$patch_capabilities $pkgoutput"); + system ("$patch_capabilities $pkgoutput") and die ("ERROR: Automatic patching failed"); } # Create SIS. # The 'and' is because system uses 0 to indicate success. if($epocroot) { - system ("$epocroot/epoc32/tools/makesis $pkgoutput $unsigned_sis_name") and die ("makesis failed"); + system ("$epocroot/epoc32/tools/makesis $pkgoutput $unsigned_sis_name") and die ("ERROR: makesis failed"); } else { - system ("makesis $pkgoutput $unsigned_sis_name") and die ("makesis failed"); + system ("makesis $pkgoutput $unsigned_sis_name") and die ("ERROR: makesis failed"); } print("\n"); @@ -354,7 +354,7 @@ if($stub) { my $relcert = File::Spec->abs2rel($certificate); my $relkey = File::Spec->abs2rel($key); # The 'and' is because system uses 0 to indicate success. - system ("signsis $unsigned_sis_name $signed_sis_name $relcert $relkey $passphrase") and die ("signsis failed"); + system ("signsis $unsigned_sis_name $signed_sis_name $relcert $relkey $passphrase") and die ("ERROR: signsis failed"); # Check if creating signed SIS Succeeded stat($signed_sis_name); diff --git a/bin/patch_capabilities.pl b/bin/patch_capabilities.pl index a85f073..06ab116 100755 --- a/bin/patch_capabilities.pl +++ b/bin/patch_capabilities.pl @@ -152,7 +152,7 @@ if (@ARGV) my $newLine = $line; # Patch pkg UID if it's in protected range - if ($line =~ m/^\#.*\((0x[0-7][0-9|a-f|A-F]*)\).*$/) + if ($line =~ m/^\#.*\((0x[0-7][0-9a-fA-F]*)\).*$/) { my $oldUID = $1; my $newUID = $oldUID; @@ -162,7 +162,7 @@ if (@ARGV) } # Patch embedded sis name and UID if UID is in protected range - if ($line =~ m/^@\"*(.*\.sis).*\((0x[0-7][0-9|a-f|A-F]*)\).*$/) + if ($line =~ m/^@\"*(.*\.sis).*\((0x[0-7][0-9a-fA-F]*)\).*$/) { my $oldSisName = $1; my $oldUID = $2; @@ -280,7 +280,16 @@ if (@ARGV) my $capabilitiesToAllow = join(" ", @capabilitiesToAllow); my @capabilitiesToDrop; while (<$dllCaps>) { - if (/^Vendor ID: (.*)$/) { + if (/^Secure ID: ([0-7][0-9a-fA-F]*)$/) { + my $exeSid = $1; + if ($binaryBaseName =~ /\.exe$/) { + # Installer refuses to install protected executables in a self signed package, so abort if one is detected. + # We can't simply just patch the executable SID, as any registration resources executable uses will be linked to it via SID. + print ("Patching: Executable with SID in the protected range (0x$exeSid) detected: \"$binaryBaseName\". A self-signed sis with protected executables is not supported.\n"); + exit(1); + } + } + if (/^Vendor ID: ([0-9a-fA-F]*)$/) { $originalVid = "$1"; } if (!$capsFound) { @@ -303,8 +312,15 @@ if (@ARGV) my $capsToDropStr = join("\", \"", @capabilitiesToDrop); $capsToDropStr =~ s/\", \"$//; - print ("Patching: The following capabilities used in \"$binaryBaseName\" are not compatible with a self-signed package and will be removed: \"$capsToDropStr\".\n"); - $executeNeeded = 1; + if ($binaryBaseName =~ /\.exe$/) { + # While libraries often have capabilities they do not themselves need just to enable them to be loaded by wider variety of processes, + # executables are more likely to need every capability they have been assigned or they won't function correctly. + print ("Patching: Executable with capabilities incompatible with self-signing detected: \"$binaryBaseName\". (Incompatible capabilities: \"$capsToDropStr\".) Reducing capabilities is only supported for libraries.\n"); + exit(1); + } else { + print ("Patching: The following capabilities used in \"$binaryBaseName\" are not compatible with a self-signed package and will be removed: \"$capsToDropStr\".\n"); + $executeNeeded = 1; + } } $commandToExecute = sprintf($baseCommandToExecute, join(" ", @capabilitiesToSet)); } diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp index 5cc6ae3..d8cc344 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian.cpp +++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp @@ -127,9 +127,9 @@ private: * cannot change active objects that we do not own, but the active objects that Qt owns will use * this as a base class with convenience functions. * - * Here is how it works: On every RunL, the deriving class should call okToRun(). This will allow - * exactly one run of the active object, and mark it as such. If it is called again, it will return - * false, and add the object to a queue so it can be run later. + * Here is how it works: On every RunL, the deriving class should call maybeQueueForLater(). + * This will return whether the active object has been queued, or whether it should run immediately. + * Queued objects will run again after other events have been processed. * * The QCompleteDeferredAOs class is a special object that runs after all others, which will * reactivate the objects that were previously not run. @@ -149,7 +149,7 @@ QActiveObject::~QActiveObject() m_dispatcher->removeDeferredActiveObject(this); } -bool QActiveObject::okToRun() +bool QActiveObject::maybeQueueForLater() { Q_ASSERT(!m_hasRunAgain); @@ -157,12 +157,12 @@ bool QActiveObject::okToRun() // First occurrence of this event in this iteration. m_hasAlreadyRun = true; m_iterationCount = m_dispatcher->iterationCount(); - return true; + return false; } else { // The event has already occurred. m_dispatcher->addDeferredActiveObject(this); m_hasRunAgain = true; - return false; + return true; } } @@ -178,8 +178,7 @@ void QActiveObject::reactivateAndComplete() } QWakeUpActiveObject::QWakeUpActiveObject(QEventDispatcherSymbian *dispatcher) - : CActive(WAKE_UP_PRIORITY), - m_dispatcher(dispatcher) + : QActiveObject(WAKE_UP_PRIORITY, dispatcher) { CActiveScheduler::Add(this); iStatus = KRequestPending; @@ -201,6 +200,9 @@ void QWakeUpActiveObject::DoCancel() void QWakeUpActiveObject::RunL() { + if (maybeQueueForLater()) + return; + iStatus = KRequestPending; SetActive(); QT_TRYCATCH_LEAVING(m_dispatcher->wakeUpWasCalled()); @@ -270,7 +272,7 @@ void QTimerActiveObject::Run() return; } - if (!okToRun()) + if (maybeQueueForLater()) return; if (m_timerInfo->interval > 0) { @@ -630,7 +632,7 @@ void QSocketActiveObject::DoCancel() void QSocketActiveObject::RunL() { - if (!okToRun()) + if (maybeQueueForLater()) return; QT_TRYCATCH_LEAVING(m_dispatcher->socketFired(this)); @@ -722,6 +724,7 @@ QEventDispatcherSymbian::QEventDispatcherSymbian(QObject *parent) m_interrupt(false), m_wakeUpDone(0), m_iterationCount(0), + m_insideTimerEvent(false), m_noSocketEvents(false) { #ifdef QT_SYMBIAN_PRIORITY_DROP @@ -772,6 +775,9 @@ bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags fla { bool handledAnyEvent = false; bool oldNoSocketEventsValue = m_noSocketEvents; + bool oldInsideTimerEventValue = m_insideTimerEvent; + + m_insideTimerEvent = false; QT_TRY { Q_D(QAbstractEventDispatcher); @@ -862,6 +868,7 @@ bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags fla } m_noSocketEvents = oldNoSocketEventsValue; + m_insideTimerEvent = oldInsideTimerEventValue; return handledAnyEvent; } @@ -882,10 +889,13 @@ void QEventDispatcherSymbian::timerFired(int timerId) } timerInfo->inTimerEvent = true; + bool oldInsideTimerEventValue = m_insideTimerEvent; + m_insideTimerEvent = true; QTimerEvent event(timerInfo->timerId); QCoreApplication::sendEvent(timerInfo->receiver, &event); + m_insideTimerEvent = oldInsideTimerEventValue; timerInfo->inTimerEvent = false; return; @@ -1052,6 +1062,14 @@ void QEventDispatcherSymbian::registerTimer ( int timerId, int interval, QObject m_timerList.insert(timerId, timer); timer->timerAO->Start(); + + if (m_insideTimerEvent) + // If we are inside a timer event, we need to prevent event starvation + // by preventing newly created timers from running in the same event processing + // iteration. Do this by calling the maybeQueueForLater() function to "fake" that we have + // already run once. This will cause the next run to be added to the deferred + // queue instead. + timer->timerAO->maybeQueueForLater(); } bool QEventDispatcherSymbian::unregisterTimer ( int timerId ) diff --git a/src/corelib/kernel/qeventdispatcher_symbian_p.h b/src/corelib/kernel/qeventdispatcher_symbian_p.h index bc42753..1486db5 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian_p.h +++ b/src/corelib/kernel/qeventdispatcher_symbian_p.h @@ -82,7 +82,7 @@ public: QActiveObject(TInt priority, QEventDispatcherSymbian *dispatcher); ~QActiveObject(); - bool okToRun(); + bool maybeQueueForLater(); void reactivateAndComplete(); @@ -95,7 +95,7 @@ private: int m_iterationCount; }; -class QWakeUpActiveObject : public CActive +class QWakeUpActiveObject : public QActiveObject { public: QWakeUpActiveObject(QEventDispatcherSymbian *dispatcher); @@ -106,9 +106,6 @@ public: protected: void DoCancel(); void RunL(); - -private: - QEventDispatcherSymbian *m_dispatcher; }; struct SymbianTimerInfo : public QSharedData @@ -277,6 +274,7 @@ private: QAtomicInt m_wakeUpDone; unsigned char m_iterationCount; + bool m_insideTimerEvent; bool m_noSocketEvents; QList<QSocketActiveObject *> m_deferredSocketEvents; diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp index 3c2fd3d..74395a2 100644 --- a/src/openvg/qpaintengine_vg.cpp +++ b/src/openvg/qpaintengine_vg.cpp @@ -248,7 +248,11 @@ public: inline void ensurePathTransform() { if (!pathTransformSet) { - setTransform(VG_MATRIX_PATH_USER_TO_SURFACE, pathTransform); + QTransform aliasedTransform = pathTransform; + if (renderingQuality == VG_RENDERING_QUALITY_NONANTIALIASED && currentPen != Qt::NoPen) + aliasedTransform = aliasedTransform + * QTransform::fromTranslate(aliasedCoordinateDelta, -aliasedCoordinateDelta); + setTransform(VG_MATRIX_PATH_USER_TO_SURFACE, aliasedTransform); pathTransformSet = true; } } @@ -306,6 +310,7 @@ inline void QVGPaintEnginePrivate::setRenderingQuality(VGRenderingQuality mode) if (renderingQuality != mode) { vgSeti(VG_RENDERING_QUALITY, mode); renderingQuality = mode; + pathTransformSet = false; // need to tweak transform for aliased stroking } } diff --git a/tests/auto/qapplication/test/test.pro b/tests/auto/qapplication/test/test.pro index 30eb751..2c54c37 100644 --- a/tests/auto/qapplication/test/test.pro +++ b/tests/auto/qapplication/test/test.pro @@ -12,7 +12,7 @@ wince* { } symbian: { - additional.sources = ../desktopsettingsaware/desktopsettingsaware.exe + additional.sources = $$OUT_PWD/../desktopsettingsaware/desktopsettingsaware.exe additional.path = desktopsettingsaware someTest.sources = test.pro someTest.path = test diff --git a/tests/auto/qtimer/tst_qtimer.cpp b/tests/auto/qtimer/tst_qtimer.cpp index f23d065..102308e 100644 --- a/tests/auto/qtimer/tst_qtimer.cpp +++ b/tests/auto/qtimer/tst_qtimer.cpp @@ -89,6 +89,7 @@ private slots: void recurseOnTimeoutAndStopTimer(); void QTBUG13633_dontBlockEvents(); + void postedEventsShouldNotStarveTimers(); }; class TimerHelper : public QObject @@ -723,5 +724,31 @@ void tst_QTimer::QTBUG13633_dontBlockEvents() QVERIFY(t.total > 2); } +class SlotRepeater : public QObject { + Q_OBJECT +public: + SlotRepeater() {} + +public slots: + void repeatThisSlot() + { + QMetaObject::invokeMethod(this, "repeatThisSlot", Qt::QueuedConnection); + } +}; + +void tst_QTimer::postedEventsShouldNotStarveTimers() +{ + TimerHelper timerHelper; + QTimer timer; + connect(&timer, SIGNAL(timeout()), &timerHelper, SLOT(timeout())); + timer.setInterval(0); + timer.setSingleShot(false); + timer.start(); + SlotRepeater slotRepeater; + slotRepeater.repeatThisSlot(); + QTest::qWait(100); + QVERIFY(timerHelper.count > 5); +} + QTEST_MAIN(tst_QTimer) #include "tst_qtimer.moc" |