[Libreoffice-commits] core.git: 4 commits - extensions/source framework/inc framework/source svx/source vcl/source vcl/unx

Caolán McNamara caolanm at redhat.com
Wed Jun 22 10:34:26 UTC 2016


 extensions/source/update/check/updatecheckjob.cxx |   16 +-
 framework/inc/services/desktop.hxx                |   12 ++
 framework/source/services/desktop.cxx             |   23 ++++
 svx/source/form/fmscriptingenv.cxx                |  118 +++++++++++++++++++++-
 vcl/source/gdi/bitmap3.cxx                        |    3 
 vcl/unx/gtk/glomenu.cxx                           |    4 
 6 files changed, 166 insertions(+), 10 deletions(-)

New commits:
commit 2822d1891b551a58c691cac37c11d3b9c2255755
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Wed Jun 22 11:31:23 2016 +0100

    valgrind: use after free
    
    sal/osl/unx/conditn.cxx:90: pthread_cond_destroy failed: Device or resource busy
    sal/osl/unx/conditn.cxx:92: pthread_mutex_destroy failed: Device or resource busy
    
    "Desktop disposed before terminating it"
    
    seen under valgrind with CppunitTest_sccomp_lpsolver
    
    Change-Id: I643cf114b902c38a6a54487fd78c55d84ed78cfc

diff --git a/extensions/source/update/check/updatecheckjob.cxx b/extensions/source/update/check/updatecheckjob.cxx
index ba41067..5d48471 100644
--- a/extensions/source/update/check/updatecheckjob.cxx
+++ b/extensions/source/update/check/updatecheckjob.cxx
@@ -106,9 +106,9 @@ private:
     std::unique_ptr< InitUpdateCheckJobThread > m_pInitThread;
 
     void handleExtensionUpdates( const uno::Sequence< beans::NamedValue > &rListProp );
+    void terminateAndJoinThread();
 };
 
-
 InitUpdateCheckJobThread::InitUpdateCheckJobThread(
             const uno::Reference< uno::XComponentContext > &xContext,
             const uno::Sequence< beans::NamedValue > &xParameters,
@@ -155,7 +155,6 @@ UpdateCheckJob::~UpdateCheckJob()
 {
 }
 
-
 uno::Sequence< OUString >
 UpdateCheckJob::getServiceNames()
 {
@@ -281,6 +280,7 @@ void SAL_CALL UpdateCheckJob::disposing( lang::EventObject const & rEvt )
 
     if ( shutDown && m_xDesktop.is() )
     {
+        terminateAndJoinThread();
         m_xDesktop->removeTerminateListener( this );
         m_xDesktop.clear();
     }
@@ -293,19 +293,23 @@ void SAL_CALL UpdateCheckJob::queryTermination( lang::EventObject const & )
 {
 }
 
-
-void SAL_CALL UpdateCheckJob::notifyTermination( lang::EventObject const & )
-    throw ( uno::RuntimeException, std::exception )
+void UpdateCheckJob::terminateAndJoinThread()
 {
     if ( m_pInitThread.get() != nullptr )
     {
         m_pInitThread->setTerminating();
         m_pInitThread->join();
+        m_pInitThread.reset();
     }
 }
 
-} // anonymous namespace
+void SAL_CALL UpdateCheckJob::notifyTermination( lang::EventObject const & )
+    throw ( uno::RuntimeException, std::exception )
+{
+    terminateAndJoinThread();
+}
 
+} // anonymous namespace
 
 static uno::Reference<uno::XInterface> SAL_CALL
 createJobInstance(const uno::Reference<uno::XComponentContext>& xContext)
commit 8488b3ba00e23e8ae6e089f450965c93c7a13d26
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Wed Jun 22 11:00:42 2016 +0100

    G_MENU_ATTRIBUTE_ICON is only in glib >= 2.38
    
    Change-Id: I7761ac05fbc9be39a6982ba66054c75a331816be

diff --git a/vcl/unx/gtk/glomenu.cxx b/vcl/unx/gtk/glomenu.cxx
index aab6857..f91a469 100644
--- a/vcl/unx/gtk/glomenu.cxx
+++ b/vcl/unx/gtk/glomenu.cxx
@@ -248,6 +248,10 @@ g_lo_menu_set_icon (GLOMenu     *menu,
     else
         value = nullptr;
 
+#ifndef G_MENU_ATTRIBUTE_ICON
+#    define G_MENU_ATTRIBUTE_ICON "icon"
+#endif
+
     g_lo_menu_set_attribute_value (menu, position, G_MENU_ATTRIBUTE_ICON, value);
 }
 
commit 911c4d8472303053c19b14457a533d8b2f0a2ea9
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Wed Jun 22 10:55:24 2016 +0100

    crashtesting: assert on export of tdf96006-1.odt to rtf
    
    revealed since...
    
    commit 81e3ca4f60e6ac0823c1233841c22a759cfe937f
    Author: Tor Lillqvist <tml at collabora.com>
    Date:   Tue Jun 21 10:34:21 2016 +0300
    
    surely here we should ask the palette how many entries are
    in it, not assume from the original bitcount that all entries
    exist.
    
    presumably the palette can only have <= 1 << BitCount entries in it
    
    Change-Id: Ieb1b98f2f13f702a6a6a20d8cf3d8e9a695141b2

diff --git a/vcl/source/gdi/bitmap3.cxx b/vcl/source/gdi/bitmap3.cxx
index c5de584..98ede14 100644
--- a/vcl/source/gdi/bitmap3.cxx
+++ b/vcl/source/gdi/bitmap3.cxx
@@ -623,8 +623,9 @@ bool Bitmap::ImplConvertUp(sal_uInt16 nBitCount, Color* pExtColor)
 
             if (pWriteAcc->HasPalette())
             {
-                const sal_uInt16 nOldCount = 1 << GetBitCount();
                 const BitmapPalette& rOldPalette = pReadAcc->GetPalette();
+                const sal_uInt16 nOldCount = rOldPalette.GetEntryCount();
+                assert(nOldCount <= (1 << GetBitCount()));
 
                 aPalette.SetEntryCount(1 << nBitCount);
 
commit 68cf256f506d4601a2d2cf3ec2d56713afd491e6
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Tue Jun 21 21:29:25 2016 +0100

    Resolves: tdf#88985 block app from exiting during macro execution
    
    but stop basic execution on the exit attempt, and then resend exit at a safe
    place when basic execution has stopped
    
    Change-Id: I77c43acffa0b82e8125dcb3b10ad9bf0d6dd26c3

diff --git a/framework/inc/services/desktop.hxx b/framework/inc/services/desktop.hxx
index e8fd001..6e0c215 100644
--- a/framework/inc/services/desktop.hxx
+++ b/framework/inc/services/desktop.hxx
@@ -428,6 +428,18 @@ class Desktop : private cppu::BaseMutex,
           */
         css::uno::Reference< css::frame::XTerminateListener > m_xQuickLauncher;
 
+        /** special terminate listener active when a macro is executing.
+          * Because basic runs Application::Yield internally the application may quit
+          * while running inside the internal basic event loop. So all the basic
+          * infrastructure may be deleted while the call is executing, leading to
+          * a varient of crashes. So this special terminate listener will
+          * veto the current quit attempt, stop basic execution, which will
+          * cause the inner event loop to quit, and on return to the outer normal
+          * application event loop then resend the quit attempt.
+          * So these implementation must be a special terminate listener too .-(
+          */
+        css::uno::Reference< css::frame::XTerminateListener > m_xStarBasicQuitGuard;
+
         /** special terminate listener which loads images asynchronous for current open documents.
           * Because internally it uses blocking system APIs... it can't be guaranteed that
           * running jobs can be cancelled successfully if the corresponding document will be closed...
diff --git a/framework/source/services/desktop.cxx b/framework/source/services/desktop.cxx
index 64e7e64..0ec0bce 100644
--- a/framework/source/services/desktop.cxx
+++ b/framework/source/services/desktop.cxx
@@ -171,6 +171,7 @@ Desktop::Desktop( const css::uno::Reference< css::uno::XComponentContext >& xCon
         ,   m_xDispatchRecorderSupplier(                                            )
         ,   m_xPipeTerminator       (                                               )
         ,   m_xQuickLauncher        (                                               )
+        ,   m_xStarBasicQuitGuard   (                                               )
         ,   m_xSWThreadManager      (                                               )
         ,   m_xSfxTerminator        (                                               )
         ,   m_xTitleNumberGenerator (                                               )
@@ -214,6 +215,7 @@ sal_Bool SAL_CALL Desktop::terminate()
 
     css::uno::Reference< css::frame::XTerminateListener > xPipeTerminator    = m_xPipeTerminator;
     css::uno::Reference< css::frame::XTerminateListener > xQuickLauncher     = m_xQuickLauncher;
+    css::uno::Reference< css::frame::XTerminateListener > xStarBasicQuitGuard = m_xStarBasicQuitGuard;
     css::uno::Reference< css::frame::XTerminateListener > xSWThreadManager   = m_xSWThreadManager;
     css::uno::Reference< css::frame::XTerminateListener > xSfxTerminator     = m_xSfxTerminator;
 
@@ -275,6 +277,12 @@ sal_Bool SAL_CALL Desktop::terminate()
             lCalledTerminationListener.push_back( xQuickLauncher );
         }
 
+        if ( xStarBasicQuitGuard.is() )
+        {
+            xStarBasicQuitGuard->queryTermination( aEvent );
+            lCalledTerminationListener.push_back( xStarBasicQuitGuard );
+        }
+
         if ( xSWThreadManager.is() )
         {
             xSWThreadManager->queryTermination( aEvent );
@@ -322,6 +330,9 @@ sal_Bool SAL_CALL Desktop::terminate()
             xQuickLauncher->notifyTermination( aEvent );
         }
 
+        if ( xStarBasicQuitGuard.is() )
+            xStarBasicQuitGuard->notifyTermination( aEvent );
+
         if ( xSWThreadManager.is() )
             xSWThreadManager->notifyTermination( aEvent );
 
@@ -395,6 +406,11 @@ void SAL_CALL Desktop::addTerminateListener( const css::uno::Reference< css::fra
             m_xQuickLauncher = xListener;
             return;
         }
+        if( sImplementationName == "com.sun.star.comp.svx.StarBasicQuitGuard" )
+        {
+            m_xStarBasicQuitGuard = xListener;
+            return;
+        }
         if( sImplementationName == "com.sun.star.util.comp.FinalThreadManager" )
         {
             m_xSWThreadManager = xListener;
@@ -436,6 +452,12 @@ void SAL_CALL Desktop::removeTerminateListener( const css::uno::Reference< css::
             return;
         }
 
+        if( sImplementationName == "com.sun.star.comp.svx.StarBasicQuitGuard" )
+        {
+            m_xStarBasicQuitGuard.clear();
+            return;
+        }
+
         if( sImplementationName == "com.sun.star.util.comp.FinalThreadManager" )
         {
             m_xSWThreadManager.clear();
@@ -1068,6 +1090,7 @@ void SAL_CALL Desktop::disposing()
 
     m_xPipeTerminator.clear();
     m_xQuickLauncher.clear();
+    m_xStarBasicQuitGuard.clear();
     m_xSWThreadManager.clear();
     m_xSfxTerminator.clear();
     m_xCommandOptions.reset();
diff --git a/svx/source/form/fmscriptingenv.cxx b/svx/source/form/fmscriptingenv.cxx
index 3cc284e..b79d421 100644
--- a/svx/source/form/fmscriptingenv.cxx
+++ b/svx/source/form/fmscriptingenv.cxx
@@ -22,14 +22,18 @@
 #include "fmscriptingenv.hxx"
 #include "svx/fmmodel.hxx"
 
-#include <com/sun/star/lang/IllegalArgumentException.hpp>
-#include <com/sun/star/script/XScriptListener.hpp>
+#include <com/sun/star/awt/XControl.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/frame/XTerminateListener.hpp>
 #include <com/sun/star/lang/DisposedException.hpp>
 #include <com/sun/star/lang/EventObject.hpp>
-#include <com/sun/star/awt/XControl.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/script/XScriptListener.hpp>
 
 #include <tools/diagnose_ex.h>
 #include <cppuhelper/implbase.hxx>
+#include <cppuhelper/compbase.hxx>
 #include <comphelper/processfactory.hxx>
 #include <vcl/svapp.hxx>
 #include <osl/mutex.hxx>
@@ -764,6 +768,111 @@ namespace svxform
         m_pScriptExecutor = nullptr;
     }
 
+    // tdf#88985 If LibreOffice tries to exit during the execution of a macro
+    // then: detect the effort, stop basic execution, block until the macro
+    // returns due to that stop, then restart the quit. This avoids the app
+    // exiting and destroying itself until the macro is parked at a safe place
+    // to do that.
+    class QuitGuard
+    {
+    private:
+
+        class TerminateListener : public cppu::WeakComponentImplHelper<css::frame::XTerminateListener,
+                                                                       css::lang::XServiceInfo>
+        {
+        private:
+            css::uno::Reference<css::frame::XDesktop2> m_xDesktop;
+            osl::Mutex maMutex;
+            bool mbQuitBlocked;
+        public:
+            // XTerminateListener
+            virtual void SAL_CALL queryTermination(const css::lang::EventObject& /*rEvent*/)
+                throw(css::frame::TerminationVetoException, css::uno::RuntimeException, std::exception) override
+            {
+                mbQuitBlocked = true;
+                StarBASIC::Stop();
+                throw css::frame::TerminationVetoException();
+            }
+
+            virtual void SAL_CALL notifyTermination(const css::lang::EventObject& /*rEvent*/)
+                throw(css::uno::RuntimeException, std::exception) override
+            {
+                mbQuitBlocked = false;
+            }
+
+            using cppu::WeakComponentImplHelperBase::disposing;
+
+            virtual void SAL_CALL disposing(const css::lang::EventObject& rEvent)
+                throw(css::uno::RuntimeException, std::exception) override
+            {
+                const bool bShutDown = (rEvent.Source == m_xDesktop);
+                if (bShutDown && m_xDesktop.is())
+                {
+                    m_xDesktop->removeTerminateListener(this);
+                    m_xDesktop.clear();
+                }
+            }
+
+            // XServiceInfo
+            virtual OUString SAL_CALL getImplementationName()
+                throw (css::uno::RuntimeException, std::exception) override
+            {
+                return OUString("com.sun.star.comp.svx.StarBasicQuitGuard");
+            }
+
+            virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName)
+                throw (css::uno::RuntimeException, std::exception) override
+            {
+                return cppu::supportsService(this, ServiceName);
+            }
+
+            virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames()
+                throw (css::uno::RuntimeException, std::exception) override
+            {
+                css::uno::Sequence<OUString> aSeq { "com.sun.star.svx.StarBasicQuitGuard" };
+                return aSeq;
+            }
+
+        public:
+            TerminateListener()
+                : cppu::WeakComponentImplHelper<css::frame::XTerminateListener,
+                                                css::lang::XServiceInfo>(maMutex)
+                , mbQuitBlocked(false)
+            {
+            }
+
+            void start()
+            {
+                css::uno::Reference<css::uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
+                m_xDesktop = css::frame::Desktop::create(xContext);
+                m_xDesktop->addTerminateListener(this);
+            }
+
+            void stop()
+            {
+                if (!m_xDesktop.is())
+                    return;
+                m_xDesktop->removeTerminateListener(this);
+                if (mbQuitBlocked)
+                    m_xDesktop->terminate();
+            }
+        };
+
+        TerminateListener* mpListener;
+        css::uno::Reference<css::frame::XTerminateListener> mxLifeCycle;
+    public:
+        QuitGuard()
+            : mpListener(new TerminateListener)
+            , mxLifeCycle(mpListener)
+        {
+            mpListener->start();
+        }
+
+        ~QuitGuard()
+        {
+            mpListener->stop();
+        }
+    };
 
     IMPL_LINK_TYPED( FormScriptListener, OnAsyncScriptEvent, void*, p, void )
     {
@@ -776,7 +885,10 @@ namespace svxform
             ::osl::ClearableMutexGuard aGuard( m_aMutex );
 
             if ( !impl_isDisposed_nothrow() )
+            {
+                QuitGuard aQuitGuard;
                 impl_doFireScriptEvent_nothrow( aGuard, *_pEvent, nullptr );
+            }
         }
 
         delete _pEvent;


More information about the Libreoffice-commits mailing list