[Libreoffice-commits] core.git: Branch 'feature/fixes10' - 2 commits - sc/source

Michael Stahl mstahl at redhat.com
Mon Oct 5 10:10:35 PDT 2015


 sc/source/ui/vba/vbaeventshelper.cxx |   16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

New commits:
commit 8cd187c351fe9babbbc5d23a38c5b35b0d523c47
Author: Michael Stahl <mstahl at redhat.com>
Date:   Wed Sep 30 10:31:23 2015 +0200

    sc: fix crash in ScVbaEventListener::processWindowResizeEvent()
    
    This was crashing in CppunitTest_sc_macros_test on Windows with
    --enable-mergelibs (release build), because the first invocation of
    processWindowResizeEvent() deleted the vcl::Window, and the
    maControllers.count(pWindow) test creates a VclPtr for it, so ends up
    with a double-free.
    
    TODO: is processWindowResizeEvent() supposed to be idempotent?
    It would be possible to detect that there is already an event posted by
    checking m_PostedWindows in postWindowResizeEvent().
    
    Change-Id: I7b72f2baf21bb8223e9fe4bd929d826217b920e5
    (cherry picked from commit 520514cfe6a99f68b9e1d458fae20026f1a8f66b)
    Reviewed-on: https://gerrit.libreoffice.org/19022
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/sc/source/ui/vba/vbaeventshelper.cxx b/sc/source/ui/vba/vbaeventshelper.cxx
index e787031..d92f640 100644
--- a/sc/source/ui/vba/vbaeventshelper.cxx
+++ b/sc/source/ui/vba/vbaeventshelper.cxx
@@ -169,7 +169,7 @@ private:
     uno::Reference< frame::XModel > mxModel;
     ScDocShell*         mpDocShell;
     WindowControllerMap maControllers;          /// Maps VCL top windows to their controllers.
-    std::set< VclPtr<vcl::Window> > maPostedWindows; /// Keeps processWindowResizeEvent windows from being deleted between postWindowResizeEvent and processWindowResizeEvent
+    std::multiset< VclPtr<vcl::Window> > m_PostedWindows; /// Keeps processWindowResizeEvent windows from being deleted between postWindowResizeEvent and processWindowResizeEvent
     VclPtr<vcl::Window>            mpActiveWindow; /// Currently activated window, to prevent multiple (de)activation.
     bool                mbWindowResized;        /// True = window resize system event processed.
     bool                mbBorderChanged;        /// True = borders changed system event processed.
@@ -471,7 +471,7 @@ void ScVbaEventListener::postWindowResizeEvent( vcl::Window* pWindow )
     {
         mbWindowResized = mbBorderChanged = false;
         acquire();  // ensure we don't get deleted before the timer fires
-        maPostedWindows.insert(pWindow);
+        m_PostedWindows.insert(pWindow);
         Application::PostUserEvent( LINK( this, ScVbaEventListener, processWindowResizeEvent ), pWindow );
     }
 }
@@ -504,7 +504,14 @@ IMPL_LINK( ScVbaEventListener, processWindowResizeEvent, vcl::Window*, pWindow )
             }
         }
     }
-    maPostedWindows.erase(pWindow);
+    {
+        // note: there may be multiple processWindowResizeEvent outstanding
+        // for pWindow, so it may have been added to m_PostedWindows multiple
+        // times - so this must delete exactly one of these elements!
+        auto const iter(m_PostedWindows.find(pWindow));
+        assert(iter != m_PostedWindows.end());
+        m_PostedWindows.erase(iter);
+    }
     release();
     return 0;
 }
commit b61f03fe7f6799e909c3feaf6557f61b63fae67c
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Wed Jun 3 10:57:18 2015 +0100

    intermittent CppunitTest_sc_macros_test failure
    
    void OutputDevice::acquire() const: Assertion `mnRefCnt>0' failed"
    
    Window gets destroyed between postWindowResizeEvent and processWindowResizeEvent
    
    Change-Id: I3452a23ad8c3b6d863a56b73166520ef103dad1b
    (cherry picked from commit 5f36b1954438caef95053c2c0b7d0417e1aa5b31)
    Signed-off-by: Michael Stahl <mstahl at redhat.com>

diff --git a/sc/source/ui/vba/vbaeventshelper.cxx b/sc/source/ui/vba/vbaeventshelper.cxx
index d35e885..e787031 100644
--- a/sc/source/ui/vba/vbaeventshelper.cxx
+++ b/sc/source/ui/vba/vbaeventshelper.cxx
@@ -169,7 +169,8 @@ private:
     uno::Reference< frame::XModel > mxModel;
     ScDocShell*         mpDocShell;
     WindowControllerMap maControllers;          /// Maps VCL top windows to their controllers.
-    VclPtr<vcl::Window>            mpActiveWindow;         /// Currently activated window, to prevent multiple (de)activation.
+    std::set< VclPtr<vcl::Window> > maPostedWindows; /// Keeps processWindowResizeEvent windows from being deleted between postWindowResizeEvent and processWindowResizeEvent
+    VclPtr<vcl::Window>            mpActiveWindow; /// Currently activated window, to prevent multiple (de)activation.
     bool                mbWindowResized;        /// True = window resize system event processed.
     bool                mbBorderChanged;        /// True = borders changed system event processed.
     bool                mbDisposed;
@@ -219,7 +220,9 @@ void ScVbaEventListener::startControllerListening( const uno::Reference< frame::
         try { xControllerBorder->addBorderResizeListener( this ); } catch( uno::Exception& ) {}
 
     if( vcl::Window* pWindow = VCLUnoHelper::GetWindow( xWindow ) )
+    {
         maControllers[ pWindow ] = rxController;
+    }
 }
 
 void ScVbaEventListener::stopControllerListening( const uno::Reference< frame::XController >& rxController )
@@ -468,6 +471,7 @@ void ScVbaEventListener::postWindowResizeEvent( vcl::Window* pWindow )
     {
         mbWindowResized = mbBorderChanged = false;
         acquire();  // ensure we don't get deleted before the timer fires
+        maPostedWindows.insert(pWindow);
         Application::PostUserEvent( LINK( this, ScVbaEventListener, processWindowResizeEvent ), pWindow );
     }
 }
@@ -484,7 +488,7 @@ IMPL_LINK( ScVbaEventListener, processWindowResizeEvent, vcl::Window*, pWindow )
         This is handled via the disposing() function which removes the window
         pointer from the member maControllers. Thus, checking whether
         maControllers contains pWindow ensures that the window is still alive. */
-    if( !mbDisposed && pWindow && (maControllers.count( pWindow ) > 0) )
+    if( !mbDisposed && pWindow && !pWindow->IsDisposed() && (maControllers.count(pWindow) > 0) )
     {
         // do not fire event unless all mouse buttons have been released
         vcl::Window::PointerState aPointerState = pWindow->GetPointerState();
@@ -500,6 +504,7 @@ IMPL_LINK( ScVbaEventListener, processWindowResizeEvent, vcl::Window*, pWindow )
             }
         }
     }
+    maPostedWindows.erase(pWindow);
     release();
     return 0;
 }


More information about the Libreoffice-commits mailing list