[Libreoffice-commits] core.git: Branch 'private/jmux/scheduler-fixes' - 2 commits - basic/source cui/source framework/source include/vcl sc/qa sc/source sd/source svx/source sw/source toolkit/source vcl/headless vcl/inc vcl/osx vcl/qa vcl/README.scheduler vcl/source vcl/unx vcl/win

Jan-Marek Glogowski glogow at fbihome.de
Tue Aug 29 18:45:11 UTC 2017


Rebased ref, commits from common ancestor:
commit 6dff7aa454cc750acb05319dd63e777b5ba314cd
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Aug 29 10:29:51 2017 +0200

    Change Reschedule default and drop nMaxEvents
    
    Normally you just want to process all pending events, so make
    it the default. nMaxEvents was never implemented on OSX and
    for the KDE4 backend it's actually impossible to handle single
    events.
    
    Change-Id: I1ab95df89b079cc8c6319a808194fe3127144d1c

diff --git a/basic/source/runtime/methods1.cxx b/basic/source/runtime/methods1.cxx
index a67de7407a6b..47c531efafc8 100644
--- a/basic/source/runtime/methods1.cxx
+++ b/basic/source/runtime/methods1.cxx
@@ -615,7 +615,7 @@ void SbRtl_DoEvents(StarBASIC *, SbxArray & rPar, bool)
 // basic runtime pcode ( on a timed basis )
     // always return 0
     rPar.Get(0)->PutInteger( 0 );
-    Application::Reschedule( true );
+    Application::Reschedule();
 }
 
 void SbRtl_GetGUIVersion(StarBASIC *, SbxArray & rPar, bool)
diff --git a/basic/source/runtime/runtime.cxx b/basic/source/runtime/runtime.cxx
index 5d9764fa7581..cee3643a6c3e 100644
--- a/basic/source/runtime/runtime.cxx
+++ b/basic/source/runtime/runtime.cxx
@@ -733,7 +733,7 @@ bool SbiRuntime::Step()
             sal_uInt32 nTime = osl_getGlobalTimer();
             if (nTime - m_nLastTime > 5 ) // 20 ms
             {
-                Application::Reschedule();
+                Application::Reschedule( false );
                 m_nLastTime = nTime;
             }
         }
diff --git a/cui/source/dialogs/cuigaldlg.cxx b/cui/source/dialogs/cuigaldlg.cxx
index 599ec984b70f..c098f875e48a 100644
--- a/cui/source/dialogs/cuigaldlg.cxx
+++ b/cui/source/dialogs/cuigaldlg.cxx
@@ -483,8 +483,7 @@ IMPL_LINK( ActualizeProgress, TimeoutHdl, Timer*, _pTimer, void)
 
 IMPL_LINK( ActualizeProgress, ActualizeHdl, const INetURLObject&, rURL, void )
 {
-    for( long i = 0; i < 128; i++ )
-        Application::Reschedule();
+    Application::Reschedule();
 
     Flush();
 
diff --git a/framework/source/helper/statusindicatorfactory.cxx b/framework/source/helper/statusindicatorfactory.cxx
index 2d5563d1213c..dab31d0d6912 100644
--- a/framework/source/helper/statusindicatorfactory.cxx
+++ b/framework/source/helper/statusindicatorfactory.cxx
@@ -519,7 +519,7 @@ void StatusIndicatorFactory::impl_reschedule(bool bForce)
 
         {
             SolarMutexGuard g;
-            Application::Reschedule(true);
+            Application::Reschedule();
         }
 
         // SAFE ->
diff --git a/include/vcl/scheduler.hxx b/include/vcl/scheduler.hxx
index 5c9d8f0d0d6e..fb76e7571a86 100644
--- a/include/vcl/scheduler.hxx
+++ b/include/vcl/scheduler.hxx
@@ -53,7 +53,12 @@ public:
     static void       CallbackTaskScheduling();
     /// Process one pending task ahead of time with highest priority.
     static bool       ProcessTaskScheduling();
-    /// Process all events until we are idle
+    /**
+     * Process all events until we are idle
+     *
+     * Idle is defined as no mpre system events and no more pending LO tasks.
+     * This basically runs Application::Reschedule( true ), until it fails.
+     */
     static void       ProcessEventsToIdle();
     /**
      * Process events until the parameter turns true,
diff --git a/include/vcl/svapp.hxx b/include/vcl/svapp.hxx
index d6e186350424..71829eb3fbe4 100644
--- a/include/vcl/svapp.hxx
+++ b/include/vcl/svapp.hxx
@@ -466,32 +466,34 @@ public:
     /** Attempt to process current pending event(s)
 
      It doesn't sleep if no events are available for processing.
+     It normally just processes all current events and ignores new tasks
+     added by the processing tasks, therefore you can't deadlock it by
+     restarting tasks.
 
      @param bAllEvents  If set to true, then try to process all the
         events. If set to false, then only process the current
-        event. Defaults to false.
+        event. Defaults to true.
 
      @returns true if any event was processed.
 
-     @see Execute, Quit, Yield, EndYield, GetSolarMutex,
-          GetMainThreadIdentifier, ReleaseSolarMutex, AcquireSolarMutex,
+     @see Yield, Scheduler::ProcessEventsToIdle,
      */
-    static bool                 Reschedule( bool bAllEvents = false );
+    static bool                 Reschedule( bool bAllEvents = true );
 
     /** Process the next event.
 
      It sleeps if no event is available for processing and just returns
      if an event was processed.
 
-     @see Execute, Quit, Reschedule, EndYield, GetSolarMutex,
-          GetMainThreadIdentifier, ReleaseSolarMutex, AcquireSolarMutex,
+     @see Reschedule, EndYield, Scheduler::ProcessEventsToIdle,
     */
     static void                 Yield();
 
-    /**
+    /** Wake up a yielding thread
 
-     @see Execute, Quit, Reschedule, Yield, GetSolarMutex,
-          GetMainThreadIdentifier, ReleaseSolarMutex, AcquireSolarMutex,
+     Basically generates a dummy event to wake up a yielding thread.
+
+     @see Execute, Reschedule, Yield
     */
     static void                 EndYield();
 
diff --git a/sc/qa/extras/macros-test.cxx b/sc/qa/extras/macros-test.cxx
index da4e30bfc20d..db962e08d134 100644
--- a/sc/qa/extras/macros-test.cxx
+++ b/sc/qa/extras/macros-test.cxx
@@ -308,7 +308,7 @@ void ScMacrosTest::testVba()
         // process all events such as OnLoad events etc.
         // otherwise the tend to arrive later at a random
         // time - while processing other StarBasic methods.
-        Application::Reschedule(true);
+        Application::Reschedule();
 
         Any aRet;
         Sequence< sal_Int16 > aOutParamIndex;
diff --git a/sc/qa/unit/tiledrendering/tiledrendering.cxx b/sc/qa/unit/tiledrendering/tiledrendering.cxx
index 3d7aba5d1b26..64fae54b0958 100644
--- a/sc/qa/unit/tiledrendering/tiledrendering.cxx
+++ b/sc/qa/unit/tiledrendering/tiledrendering.cxx
@@ -1400,7 +1400,6 @@ void ScTiledRenderingTest::testDisableUndoRepair()
     pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::RETURN);
     pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::RETURN);
     Scheduler::ProcessEventsToIdle();
-    Scheduler::ProcessEventsToIdle();
     {
         SfxItemSet aSet1(pView1->GetPool(), svl::Items<SID_UNDO, SID_UNDO>{});
         SfxItemSet aSet2(pView2->GetPool(), svl::Items<SID_UNDO, SID_UNDO>{});
diff --git a/sc/source/ui/miscdlgs/optsolver.cxx b/sc/source/ui/miscdlgs/optsolver.cxx
index 7c7eb3fd5704..f462c3874602 100644
--- a/sc/source/ui/miscdlgs/optsolver.cxx
+++ b/sc/source/ui/miscdlgs/optsolver.cxx
@@ -836,7 +836,7 @@ bool ScOptSolverDlg::CallSolver()       // return true -> close dialog after cal
     aProgress->Update();
     aProgress->Flush();
     // try to make sure the progress dialog is painted before continuing
-    Application::Reschedule(true);
+    Application::Reschedule();
 
     // collect solver parameters
 
diff --git a/sd/source/ui/dlg/animobjs.cxx b/sd/source/ui/dlg/animobjs.cxx
index d047d6a39f02..2b0a85286fb3 100644
--- a/sd/source/ui/dlg/animobjs.cxx
+++ b/sd/source/ui/dlg/animobjs.cxx
@@ -635,7 +635,7 @@ void AnimationWindow::WaitInEffect( sal_uLong nMilliSeconds, sal_uLong nTime,
         if( pProgress )
             pProgress->SetState( nTime + nMilliSeconds + aCurrent - aEnd );
 
-        Application::Reschedule();
+        Application::Reschedule( false );
 
         if( !bMovie )
             return;
diff --git a/svx/source/form/fmsrcimp.cxx b/svx/source/form/fmsrcimp.cxx
index eb05a3676639..bc75918fa587 100644
--- a/svx/source/form/fmsrcimp.cxx
+++ b/svx/source/form/fmsrcimp.cxx
@@ -312,12 +312,6 @@ FmSearchEngine::SearchResult FmSearchEngine::SearchSpecial(bool _bSearchForNull,
     do
     {
         Application::Reschedule();
-        Application::Reschedule();
-        // do 2 reschedules because of #70226# : some things done within this loop's body may cause an user event
-        // to be posted (deep within vcl), and these user events will be handled before any keyinput or paintings
-        // or anything like that. So within each loop we create one user event and handle one user event (and no
-        // paintings and these), so the office seems to be frozen while searching.
-        // FS - 70226 - 02.12.99
 
         // the content to be compared currently
         iterFieldLoop->xContents->getString();  // needed for wasNull
@@ -377,12 +371,6 @@ FmSearchEngine::SearchResult FmSearchEngine::SearchWildcard(const OUString& strE
     do
     {
         Application::Reschedule();
-        Application::Reschedule();
-        // do 2 reschedules because of #70226# : some things done within this loop's body may cause an user event
-        // to be posted (deep within vcl), and these user events will be handled before any keyinput or paintings
-        // or anything like that. So within each loop we create one user event and handle one user event (and no
-        // paintings and these), so the office seems to be frozen while searching.
-        // FS - 70226 - 02.12.99
 
         // the content to be compared currently
         OUString sCurrentCheck;
@@ -477,12 +465,6 @@ FmSearchEngine::SearchResult FmSearchEngine::SearchRegularApprox(const OUString&
     do
     {
         Application::Reschedule();
-        Application::Reschedule();
-        // do 2 reschedules because of #70226# : some things done within this loop's body may cause an user event
-        // to be posted (deep within vcl), and these user events will be handled before any keyinput or paintings
-        // or anything like that. So within each loop we create one user event and handle one user event (and no
-        // paintings and these), so the office seems to be frozen while searching.
-        // FS - 70226 - 02.12.99
 
         // the content to be compared currently
         OUString sCurrentCheck;
diff --git a/sw/source/ui/dbui/addresslistdialog.cxx b/sw/source/ui/dbui/addresslistdialog.cxx
index 96c77cd9edd7..a0e3a4468d58 100644
--- a/sw/source/ui/dbui/addresslistdialog.cxx
+++ b/sw/source/ui/dbui/addresslistdialog.cxx
@@ -487,8 +487,7 @@ IMPL_LINK(SwAddressListDialog, StaticListBoxSelectHdl_Impl, void*, p, void)
             m_pListLB->SetEntryText(m_sConnecting, pSelect, ITEMID_TABLE - 1);
             // allow painting of the new entry
             m_pListLB->Window::Invalidate(InvalidateFlags::Update);
-            for (int i = 0; i < 10; ++i)
-                Application::Reschedule();
+            Application::Reschedule();
         }
 
         pUserData = static_cast<AddressUserData_Impl*>(pSelect->GetUserData());
diff --git a/sw/source/ui/dbui/mmresultdialogs.cxx b/sw/source/ui/dbui/mmresultdialogs.cxx
index 1c3f17b4b52a..b8b1697bd73d 100644
--- a/sw/source/ui/dbui/mmresultdialogs.cxx
+++ b/sw/source/ui/dbui/mmresultdialogs.cxx
@@ -719,8 +719,7 @@ IMPL_LINK(SwMMResultSaveDialog, SaveOutputHdl_Impl, Button*, pButton, void)
             while(true)
             {
                 //time for other slots is needed
-                for(sal_Int16 r = 0; r < 10; ++r)
-                    Application::Reschedule();
+                Application::Reschedule();
                 bool bFailed = false;
                 try
                 {
@@ -1088,8 +1087,7 @@ IMPL_LINK(SwMMResultEmailDialog, SendDocumentsHdl_Impl, Button*, pButton, void)
     //help to force painting the dialog
     //TODO/CLEANUP
     //predetermined breaking point
-    for ( sal_Int16 i = 0; i < 25; i++)
-        Application::Reschedule();
+    Application::Reschedule();
     for(sal_uInt32 nDoc = nBegin; nDoc < nEnd; ++nDoc)
     {
         SwDocMergeInfo& rInfo = xConfigItem->GetDocumentMergeInfo(nDoc);
@@ -1231,8 +1229,7 @@ IMPL_LINK(SwMMResultEmailDialog, SendDocumentsHdl_Impl, Button*, pButton, void)
         aDesc.sBCC = m_sBCC;
         pDlg->AddDocument( aDesc );
         //help to force painting the dialog
-        for ( sal_Int16 i = 0; i < 25; i++)
-            Application::Reschedule();
+        Application::Reschedule();
         //stop creating of data when dialog has been closed
         if(!pDlg->IsVisible())
         {
diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 1d691bff3bed..4616aebea6d5 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -147,11 +147,6 @@ using namespace ::com::sun::star;
 
 namespace {
 
-void rescheduleGui() {
-    for( sal_uInt16 i = 0; i < 25; i++)
-        Application::Reschedule();
-}
-
 void lcl_emitEvent(SfxEventHintId nEventId, sal_Int32 nStrId, SfxObjectShell* pDocShell)
 {
     SfxGetpApp()->NotifyEvent(SfxEventHint(nEventId,
@@ -1257,7 +1252,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
         pProgressDlg->SetCancelHdl( LINK(this, SwDBManager, PrtCancelHdl) );
         pProgressDlg->Show();
 
-        rescheduleGui();
+        Application::Reschedule();
     }
 
     if( bCreateSingleFile && !pTargetView )
@@ -1400,7 +1395,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
                 pProgressDlg->Update();
             }
 
-            rescheduleGui();
+            Application::Reschedule();
 
             // Create a copy of the source document and work with that one instead of the source.
             // If we're not in the single file mode (which requires modifying the document for the merging),
@@ -1570,7 +1565,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
     }
     else if( IsMergeOk() ) // && bCreateSingleFile
     {
-        rescheduleGui();
+        Application::Reschedule();
 
         // sw::DocumentLayoutManager::CopyLayoutFormat() did not generate
         // unique fly names, do it here once.
@@ -1589,7 +1584,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
             aLayout->AllCheckPageDescs();
         }
 
-        rescheduleGui();
+        Application::Reschedule();
 
         if( IsMergeOk() && bMT_FILE )
         {
@@ -1627,7 +1622,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell,
     else if( xTargetDocShell.is() )
         xTargetDocShell->DoClose();
 
-    rescheduleGui();
+    Application::Reschedule();
 
     pProgressDlg.disposeAndClear();
 
diff --git a/toolkit/source/awt/vclxtoolkit.cxx b/toolkit/source/awt/vclxtoolkit.cxx
index eb888f6f0872..5161c4422676 100644
--- a/toolkit/source/awt/vclxtoolkit.cxx
+++ b/toolkit/source/awt/vclxtoolkit.cxx
@@ -1890,7 +1890,7 @@ void VCLXToolkit::callFocusListeners(::VclSimpleEvent const * pEvent,
 void SAL_CALL VCLXToolkit::reschedule()
 {
     SolarMutexGuard aSolarGuard;
-    Application::Reschedule(true);
+    Application::Reschedule();
 }
 
 // css::awt::XToolkitExperimental
diff --git a/vcl/headless/svpinst.cxx b/vcl/headless/svpinst.cxx
index 1966727ac936..8a805ea345b1 100644
--- a/vcl/headless/svpinst.cxx
+++ b/vcl/headless/svpinst.cxx
@@ -180,7 +180,7 @@ bool SvpSalInstance::PostedEventsInQueue()
     bool result = false;
     {
         osl::MutexGuard g(m_aEventGuard);
-        result = m_aUserEvents.size() > 0;
+        result = !m_aUserEvents.empty();
     }
     return result;
 }
diff --git a/vcl/inc/headless/svpinst.hxx b/vcl/inc/headless/svpinst.hxx
index 0883981c4406..1db4f1ac0025 100644
--- a/vcl/inc/headless/svpinst.hxx
+++ b/vcl/inc/headless/svpinst.hxx
@@ -70,6 +70,7 @@ class VCL_DLLPUBLIC SvpSalInstance : public SalGenericInstance
         ImplSVEvent*        m_pData;
         SalEvent            m_nEvent;
 
+        SalUserEvent() : m_pFrame( nullptr ), m_pData( nullptr ), m_nEvent( SalEvent::NONE ) {}
         SalUserEvent( const SalFrame* pFrame, ImplSVEvent* pData, SalEvent nEvent )
                 : m_pFrame( pFrame ),
                   m_pData( pData ),
diff --git a/vcl/qa/cppunit/timer.cxx b/vcl/qa/cppunit/timer.cxx
index 7b712bd76c04..e454698a14d1 100644
--- a/vcl/qa/cppunit/timer.cxx
+++ b/vcl/qa/cppunit/timer.cxx
@@ -326,7 +326,7 @@ void TimerTest::testAutoTimerStop()
     while (nMaxCount != nTimerCount)
         Application::Yield();
     CPPUNIT_ASSERT( !aAutoTimer.IsActive() );
-    CPPUNIT_ASSERT( !Application::Reschedule() );
+    CPPUNIT_ASSERT( !Application::Reschedule( false ) );
 }
 
 
@@ -525,7 +525,7 @@ void TimerTest::testRoundRobin()
     sal_uInt32 nCount1 = 0, nCount2 = 0;
     TestAutoIdleRR aIdle1( nCount1, "TestAutoIdleRR aIdle1" ),
                    aIdle2( nCount2, "TestAutoIdleRR aIdle2" );
-    while ( Application::Reschedule() )
+    while ( Application::Reschedule( false ) )
     {
         CPPUNIT_ASSERT( nCount1 == nCount2 || nCount1 - 1 == nCount2 );
         CPPUNIT_ASSERT( nCount1 <= 3 );
diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx
index fdfc02a684d4..895d068c2601 100644
--- a/vcl/source/app/svapp.cxx
+++ b/vcl/source/app/svapp.cxx
@@ -486,11 +486,6 @@ bool Application::Reschedule( bool i_bAllEvents )
     return ImplYield(false, i_bAllEvents);
 }
 
-void Scheduler::ProcessEventsToSignal(bool& bSignal)
-{
-    while (!bSignal && Application::Reschedule( false ) );
-}
-
 void Scheduler::ProcessEventsToIdle()
 {
     int nSanity = 1;
@@ -516,7 +511,8 @@ void Scheduler::ProcessEventsToIdle()
             Idle *pIdle = dynamic_cast<Idle*>( pSchedulerData->mpTask );
             if ( pIdle && pIdle->IsActive() )
             {
-                SAL_WARN( "vcl.schedule", "Unprocessed Idle: " << pIdle->GetDebugName() );
+                SAL_WARN( "vcl.schedule", "Unprocessed Idle: "
+                          << pIdle << " " << pIdle->GetDebugName() );
             }
         }
         pSchedulerData = pSchedulerData->mpNext;
@@ -524,6 +520,11 @@ void Scheduler::ProcessEventsToIdle()
 #endif
 }
 
+void Scheduler::ProcessEventsToSignal(bool& bSignal)
+{
+    while (!bSignal && Application::Reschedule( false ) );
+}
+
 extern "C" {
 /// used by unit tests that test only via the LOK API
 SAL_DLLPUBLIC_EXPORT void unit_lok_process_events_to_idle()
diff --git a/vcl/source/gdi/print2.cxx b/vcl/source/gdi/print2.cxx
index 2ccb80ce2a36..129b716670db 100644
--- a/vcl/source/gdi/print2.cxx
+++ b/vcl/source/gdi/print2.cxx
@@ -1232,8 +1232,7 @@ bool OutputDevice::RemoveTransparenciesFromMetaFile( const GDIMetaFile& rInMtf,
                                             pCurrAct->Execute( aPaintVDev.get() );
                                         }
 
-                                        if( !( nActionNum % 8 ) )
-                                            Application::Reschedule();
+                                        Application::Reschedule();
                                     }
 
                                     const bool bOldMap = mbMap;
diff --git a/vcl/source/gdi/print3.cxx b/vcl/source/gdi/print3.cxx
index e70c4d02dd82..358ede2c79ab 100644
--- a/vcl/source/gdi/print3.cxx
+++ b/vcl/source/gdi/print3.cxx
@@ -966,7 +966,7 @@ PrinterController::PageSize PrinterController::getPageFile( int i_nUnfilteredPag
         if( mpImplData->mpProgress->isCanceled() )
             return PrinterController::PageSize();
         mpImplData->mpProgress->tick();
-        Application::Reschedule( true );
+        Application::Reschedule();
     }
 
     if( i_bMayUseCache )
diff --git a/vcl/unx/generic/app/saldata.cxx b/vcl/unx/generic/app/saldata.cxx
index fb5131473e5a..33cee0888019 100644
--- a/vcl/unx/generic/app/saldata.cxx
+++ b/vcl/unx/generic/app/saldata.cxx
@@ -660,23 +660,20 @@ SalXLib::Yield( bool bWait, bool bHandleAllCurrentEvents )
     if (p_prioritize_timer != nullptr)
         bHandledEvent = CheckTimeout();
 
-    const int nMaxEvents = bHandleAllCurrentEvents ? 100 : 1;
-
     // first, check for already queued events.
     for ( int nFD = 0; nFD < nFDs_; nFD++ )
     {
         YieldEntry* pEntry = &(yieldTable[nFD]);
-        if ( pEntry->fd )
+        if ( pEntry->fd && pEntry->HasPendingEvent() )
         {
             SAL_WARN_IF( nFD != pEntry->fd, "vcl", "wrong fd in Yield()" );
-            for( int i = 0; i < nMaxEvents && pEntry->HasPendingEvent(); i++ )
+            do
             {
                 pEntry->HandleNextEvent();
-                if( ! bHandleAllCurrentEvents )
-                {
+                if ( !bHandleAllCurrentEvents )
                     return true;
-                }
             }
+            while ( pEntry->HasPendingEvent() );
         }
     }
 
@@ -689,7 +686,6 @@ SalXLib::Yield( bool bWait, bool bHandleAllCurrentEvents )
     timeval  Timeout      = noyield_;
     timeval *pTimeout     = &Timeout;
 
-
     if (bWait)
     {
         pTimeout = nullptr;
@@ -765,12 +761,14 @@ SalXLib::Yield( bool bWait, bool bHandleAllCurrentEvents )
                 }
                 if ( FD_ISSET( nFD, &ReadFDS ) )
                 {
-                    for( int i = 0; pEntry->IsEventQueued() && i < nMaxEvents; i++ )
+                    if ( pEntry->IsEventQueued() )
                     {
-                        pEntry->HandleNextEvent();
-                        bHandledEvent = true;
-                        // if a recursive call has done the job
-                        // so abort here
+                        do
+                        {
+                            pEntry->HandleNextEvent();
+                            bHandledEvent = true;
+                        }
+                        while ( bHandleAllCurrentEvents && pEntry->IsEventQueued() );
                     }
                     nFound--;
                 }
diff --git a/vcl/unx/generic/dtrans/X11_selection.cxx b/vcl/unx/generic/dtrans/X11_selection.cxx
index 7c89186505e0..637e32075408 100644
--- a/vcl/unx/generic/dtrans/X11_selection.cxx
+++ b/vcl/unx/generic/dtrans/X11_selection.cxx
@@ -3739,7 +3739,7 @@ void SelectionManager::shutdown() throw()
         {
             {   // drop mutex before write - otherwise may deadlock
                 SolarMutexGuard guard2;
-                Application::Reschedule();
+                Application::Reschedule( false );
             }
             // trigger poll()'s wait end by writing a dummy value
             char dummy=0;
diff --git a/vcl/unx/gtk/gtkdata.cxx b/vcl/unx/gtk/gtkdata.cxx
index 19ea9f2f0fcd..aa0f4ae28a39 100644
--- a/vcl/unx/gtk/gtkdata.cxx
+++ b/vcl/unx/gtk/gtkdata.cxx
@@ -481,14 +481,14 @@ bool GtkData::Yield( bool bWait, bool bHandleAllCurrentEvents )
 
         if( bDispatchThread )
         {
-            int nMaxEvents = bHandleAllCurrentEvents ? 100 : 1;
-            gboolean wasOneEvent = TRUE;
-            while( nMaxEvents-- && wasOneEvent )
+            bool wasOneEvent = false;
+            do
             {
                 wasOneEvent = g_main_context_iteration( nullptr, bWait && !bWasEvent );
                 if( wasOneEvent )
                     bWasEvent = true;
             }
+            while ( bHandleAllCurrentEvents && wasOneEvent );
         }
         else if( bWait )
         {
diff --git a/vcl/unx/gtk3/gtk3gtkdata.cxx b/vcl/unx/gtk3/gtk3gtkdata.cxx
index 2690c2614ae6..4739479cc99a 100644
--- a/vcl/unx/gtk3/gtk3gtkdata.cxx
+++ b/vcl/unx/gtk3/gtk3gtkdata.cxx
@@ -457,14 +457,14 @@ bool GtkData::Yield( bool bWait, bool bHandleAllCurrentEvents )
 
         if( bDispatchThread )
         {
-            int nMaxEvents = bHandleAllCurrentEvents ? 100 : 1;
-            gboolean wasOneEvent = TRUE;
-            while( nMaxEvents-- && wasOneEvent )
+            bool wasOneEvent = false;
+            do
             {
                 wasOneEvent = g_main_context_iteration( nullptr, bWait && !bWasEvent );
                 if( wasOneEvent )
                     bWasEvent = true;
             }
+            while ( bHandleAllCurrentEvents && wasOneEvent );
             if (m_aException.hasValue())
                 ::cppu::throwException(m_aException);
         }
diff --git a/vcl/unx/kde4/KDEXLib.cxx b/vcl/unx/kde4/KDEXLib.cxx
index a44b9f1a3233..d56c67e008cb 100644
--- a/vcl/unx/kde4/KDEXLib.cxx
+++ b/vcl/unx/kde4/KDEXLib.cxx
@@ -293,8 +293,7 @@ bool KDEXLib::Yield( bool bWait, bool bHandleAllCurrentEvents )
         // (it's ok to release it here, since even normal processYield() would
         // temporarily do it while checking for new events)
         SalYieldMutexReleaser aReleaser;
-        Q_EMIT processYieldSignal( bWait, bHandleAllCurrentEvents );
-        return false;
+        return Q_EMIT processYieldSignal( bWait, bHandleAllCurrentEvents );
     }
 }
 
diff --git a/vcl/unx/kde4/KDEXLib.hxx b/vcl/unx/kde4/KDEXLib.hxx
index 01076286c429..2fe497d019fa 100644
--- a/vcl/unx/kde4/KDEXLib.hxx
+++ b/vcl/unx/kde4/KDEXLib.hxx
@@ -68,7 +68,7 @@ class KDEXLib : public QObject, public SalXLib
 
     Q_SIGNALS:
         void startTimeoutTimerSignal();
-        void processYieldSignal( bool bWait, bool bHandleAllCurrentEvents );
+        bool processYieldSignal( bool bWait, bool bHandleAllCurrentEvents );
         css::uno::Reference< css::ui::dialogs::XFilePicker2 >
             createFilePickerSignal( const css::uno::Reference< css::uno::XComponentContext >& );
 
diff --git a/vcl/win/app/salinst.cxx b/vcl/win/app/salinst.cxx
index f2e337c3244b..1e69ec2c075a 100644
--- a/vcl/win/app/salinst.cxx
+++ b/vcl/win/app/salinst.cxx
@@ -510,7 +510,6 @@ static bool ImplSalYield( bool bWait, bool bHandleAllCurrentEvents )
     ImplSVData *const pSVData = ImplGetSVData();
     WinSalTimer* pTimer = static_cast<WinSalTimer*>( pSVData->maSchedCtx.mpSalTimer );
 
-    int nMaxEvents = bHandleAllCurrentEvents ? 100 : 1;
     do
     {
         bOneEvent = PeekMessageW( &aMsg, nullptr, 0, 0, PM_REMOVE );
@@ -527,11 +526,11 @@ static bool ImplSalYield( bool bWait, bool bHandleAllCurrentEvents )
             if ( pTimer && pTimer->WantBusyLoop() && !bWait )
             {
                 SwitchToThread();
-                nMaxEvents++;
                 bOneEvent = true;
                 bWasMsg = true;
             }
-    } while( --nMaxEvents && bOneEvent );
+    }
+    while( bHandleAllCurrentEvents && bOneEvent );
 
     // Also check that we don't wait when application already has quit
     if ( bWait && !bWasMsg && !pSVData->maAppData.mbAppQuit )
diff --git a/vcl/win/gdi/salprn.cxx b/vcl/win/gdi/salprn.cxx
index 7847c5465ec3..ca8de12d44f6 100644
--- a/vcl/win/gdi/salprn.cxx
+++ b/vcl/win/gdi/salprn.cxx
@@ -1291,7 +1291,7 @@ BOOL CALLBACK SalPrintAbortProc( HDC hPrnDC, int /* nError */ )
     do
     {
         // process messages
-        bWhile = Application::Reschedule( true );
+        bWhile = Application::Reschedule();
 
         pPrinter = pSalData->mpFirstPrinter;
         while ( pPrinter )
@@ -1454,7 +1454,7 @@ bool WinSalPrinter::StartJob( const OUString* pFileName,
 
     // As the Telecom Balloon Fax driver tends to send messages repeatedly
     // we try to process first all, and then insert a dummy message
-    while ( Application::Reschedule( true ) );
+    while ( Application::Reschedule() );
     BOOL const ret = PostMessageW(GetSalData()->mpFirstInstance->mhComWnd, SAL_MSG_DUMMY, 0, 0);
     SAL_WARN_IF(0 == ret, "vcl", "ERROR: PostMessage() failed!");
 
diff --git a/vcl/win/window/salframe.cxx b/vcl/win/window/salframe.cxx
index 7195b3b91fb0..c00ab908820f 100644
--- a/vcl/win/window/salframe.cxx
+++ b/vcl/win/window/salframe.cxx
@@ -5710,7 +5710,7 @@ LRESULT CALLBACK SalFrameWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lP
                 // messages in the message queue and dispatch them before we return control to the system.
 
                 if ( nRet )
-                    while ( Application::Reschedule( true ) );
+                    while ( Application::Reschedule() );
             }
             else
             {
commit 5ffb90e21d30a4d18f4feb3847b992ea7723e4a0
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Aug 29 09:40:01 2017 +0200

    Don't wait-yield non-main threads in the main thread
    
    This prevents blocking the main thread by a yielding non-main thread.
    The current solution is to wait on a condition, which is set by the
    main thread on wakeup.
    
    Change-Id: I8d680bb51a36ce1e0d3d4713d47d8e2ef93d7297

diff --git a/vcl/README.scheduler b/vcl/README.scheduler
index e960b9c8a697..7a7dee3c4c7a 100644
--- a/vcl/README.scheduler
+++ b/vcl/README.scheduler
@@ -104,6 +104,14 @@ normally wait for the SolarMutex.
 Eventually this will move into the GenericSolarMutex. KDE / Qt also does main
 thread redirects using Qt::BlockingQueuedConnection.
 
+= General: non-main thread yield =
+
+Yielding from a non-main thread must not wait in the main thread, as this
+may block the main thread until some events happen.
+
+Currently we wait on an extra conditional, which is cleared by the main event
+loop.
+
 == MacOS implementation details ==
 
 Generally the Scheduler is handled as expected, except on resize, which is
diff --git a/vcl/inc/osx/salinst.h b/vcl/inc/osx/salinst.h
index 32434325dd3e..5ebcbf977fe6 100644
--- a/vcl/inc/osx/salinst.h
+++ b/vcl/inc/osx/salinst.h
@@ -72,6 +72,8 @@ class AquaSalInstance : public SalInstance
         {}
     };
 
+    bool RunInMainYield( bool bHandleAllCurrentEvents );
+
 public:
     SalYieldMutex*                          mpSalYieldMutex;        // Sal-Yield-Mutex
     OUString                                maDefaultPrinter;
diff --git a/vcl/osx/salinst.cxx b/vcl/osx/salinst.cxx
index 0b5e4a68d4dc..e2219fee0136 100644
--- a/vcl/osx/salinst.cxx
+++ b/vcl/osx/salinst.cxx
@@ -548,6 +548,13 @@ void AquaSalInstance::handleAppDefinedEvent( NSEvent* pEvent )
     };
 }
 
+bool AquaSalInstance::RunInMainYield( bool bHandleAllCurrentEvents )
+{
+    OSX_SALDATA_RUNINMAIN_UNION( DoYield( false, bHandleAllCurrentEvents), boolean )
+    assert( false && "Don't call this from the main thread!" );
+    return false;
+}
+
 bool AquaSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents)
 {
     bool bHadEvent = false;
@@ -620,13 +627,17 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
         }
         maWaitingYieldCond.set();
     }
-    else if( bWait )
+    else
     {
-        // #i103162#
-        // wait until the main thread has dispatched an event
-        maWaitingYieldCond.reset();
-        SolarMutexReleaser aReleaser;
-        maWaitingYieldCond.wait();
+        bHadEvent = RunInMainYield( bHandleAllCurrentEvents );
+        if ( !bHadEvent && bWait )
+        {
+            // #i103162#
+            // wait until the main thread has dispatched an event
+            maWaitingYieldCond.reset();
+            SolarMutexReleaser aReleaser;
+            maWaitingYieldCond.wait();
+        }
     }
 
     // we get some apple events way too early
diff --git a/vcl/win/app/salinst.cxx b/vcl/win/app/salinst.cxx
index 8ad33066ebaf..f2e337c3244b 100644
--- a/vcl/win/app/salinst.cxx
+++ b/vcl/win/app/salinst.cxx
@@ -558,31 +558,16 @@ bool WinSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents)
     SolarMutexReleaser aReleaser;
     if ( !IsMainThread() )
     {
-        if ( bWait )
+        // If you change the SendMessageW function, you might need to update
+        // the PeekMessage( ... PM_QS_POSTMESSAGE) calls!
+        bDidWork = SendMessageW( mhComWnd, SAL_MSG_THREADYIELD,
+                                 (WPARAM) false, (LPARAM) bHandleAllCurrentEvents );
+        if ( !bDidWork && bWait )
         {
             maWaitingYieldCond.reset();
             maWaitingYieldCond.wait();
             bDidWork = true;
         }
-        else {
-            // #97739# A SendMessage call blocks until the called thread (here: the main thread)
-            // returns. During a yield however, messages are processed in the main thread that might
-            // result in a new message loop due to opening a dialog. Thus, SendMessage would not
-            // return which will block this thread!
-            // Solution: just give up the time slice and hope that messages are processed
-            // by the main thread anyway (where all windows are created)
-            // If the mainthread is not currently handling messages, then our SendMessage would
-            // also do nothing, so this seems to be reasonable.
-
-            // #i18883# only sleep if potential deadlock scenario, ie, when a dialog is open
-            if( ImplGetSVData()->maAppData.mnModalMode )
-                Sleep(1);
-            else
-                // If you change the SendMessageW function, you might need to update
-                // the PeekMessage( ... PM_QS_POSTMESSAGE) calls!
-                bDidWork = SendMessageW( mhComWnd, SAL_MSG_THREADYIELD,
-                                         (WPARAM)bWait, (LPARAM)bHandleAllCurrentEvents );
-        }
     }
     else
     {
@@ -601,7 +586,8 @@ LRESULT CALLBACK SalComWndProc( HWND, UINT nMsg, WPARAM wParam, LPARAM lParam, i
     switch ( nMsg )
     {
         case SAL_MSG_THREADYIELD:
-            nRet = static_cast<LRESULT>(ImplSalYield( (bool)wParam, (bool)lParam ));
+            assert( !(bool)wParam );
+            nRet = static_cast<LRESULT>(ImplSalYield( false, (bool)lParam ));
             rDef = FALSE;
             break;
         case SAL_MSG_STARTTIMER:


More information about the Libreoffice-commits mailing list