Resolves: tdf#81883 dispose OCalcConnection's doc before shutdown

if noone else does it, then ensure the doc is disposed before
XDesktop it torn down

Change-Id: I3136802a40c9cfb43039307dc65949d3264b6f2b
Reviewed-on: https://gerrit.libreoffice.org/28428
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
This commit is contained in:
Caolán McNamara 2016-08-27 21:32:39 +01:00
parent 5bdea25f68
commit 45e01be111
2 changed files with 77 additions and 7 deletions

View File

@ -31,7 +31,6 @@
#include "calc/CPreparedStatement.hxx" #include "calc/CPreparedStatement.hxx"
#include "calc/CStatement.hxx" #include "calc/CStatement.hxx"
#include <unotools/pathoptions.hxx> #include <unotools/pathoptions.hxx>
#include <unotools/closeveto.hxx>
#include <connectivity/dbexception.hxx> #include <connectivity/dbexception.hxx>
#include <cppuhelper/exc_hlp.hxx> #include <cppuhelper/exc_hlp.hxx>
#include <comphelper/processfactory.hxx> #include <comphelper/processfactory.hxx>
@ -164,7 +163,8 @@ Reference< XSpreadsheetDocument> const & OCalcConnection::acquireDoc()
::dbtools::throwGenericSQLException( sError, *this, aErrorDetails ); ::dbtools::throwGenericSQLException( sError, *this, aErrorDetails );
} }
osl_atomic_increment(&m_nDocCount); osl_atomic_increment(&m_nDocCount);
m_pCloseListener.reset(new utl::CloseVeto(m_xDoc, true)); m_xCloseVetoButTerminateListener.set(new CloseVetoButTerminateListener);
m_xCloseVetoButTerminateListener->start(m_xDoc, xDesktop);
return m_xDoc; return m_xDoc;
} }
@ -172,7 +172,11 @@ void OCalcConnection::releaseDoc()
{ {
if ( osl_atomic_decrement(&m_nDocCount) == 0 ) if ( osl_atomic_decrement(&m_nDocCount) == 0 )
{ {
m_pCloseListener.reset(); // dispose m_xDoc if (m_xCloseVetoButTerminateListener.is())
{
m_xCloseVetoButTerminateListener->stop(); // dispose m_xDoc
m_xCloseVetoButTerminateListener.clear();
}
m_xDoc.clear(); m_xDoc.clear();
} }
} }
@ -182,7 +186,11 @@ void OCalcConnection::disposing()
::osl::MutexGuard aGuard(m_aMutex); ::osl::MutexGuard aGuard(m_aMutex);
m_nDocCount = 0; m_nDocCount = 0;
m_pCloseListener.reset(); // dispose m_xDoc if (m_xCloseVetoButTerminateListener.is())
{
m_xCloseVetoButTerminateListener->stop(); // dispose m_xDoc
m_xCloseVetoButTerminateListener.clear();
}
m_xDoc.clear(); m_xDoc.clear();
OConnection::disposing(); OConnection::disposing();

View File

@ -21,7 +21,10 @@
#define INCLUDED_CONNECTIVITY_SOURCE_INC_CALC_CCONNECTION_HXX #define INCLUDED_CONNECTIVITY_SOURCE_INC_CALC_CCONNECTION_HXX
#include "file/FConnection.hxx" #include "file/FConnection.hxx"
#include <com/sun/star/frame/XDesktop2.hpp>
#include <com/sun/star/frame/XTerminateListener.hpp>
#include <com/sun/star/uno/DeploymentException.hpp> #include <com/sun/star/uno/DeploymentException.hpp>
#include <unotools/closeveto.hxx>
namespace com { namespace sun { namespace star { namespace com { namespace sun { namespace star {
namespace sheet { class XSpreadsheetDocument; } namespace sheet { class XSpreadsheetDocument; }
@ -39,12 +42,71 @@ namespace connectivity
{ {
// the spreadsheet document: // the spreadsheet document:
css::uno::Reference< css::sheet::XSpreadsheetDocument > m_xDoc; css::uno::Reference< css::sheet::XSpreadsheetDocument > m_xDoc;
/// close listener that vetoes so nobody disposes m_xDoc
::std::unique_ptr< ::utl::CloseVeto> m_pCloseListener;
OUString m_sPassword; OUString m_sPassword;
OUString m_aFileName; OUString m_aFileName;
oslInterlockedCount m_nDocCount; oslInterlockedCount m_nDocCount;
class CloseVetoButTerminateListener : public cppu::WeakComponentImplHelper<css::frame::XTerminateListener>
{
private:
/// close listener that vetoes so nobody else disposes m_xDoc
std::unique_ptr<utl::CloseVeto> m_pCloseListener;
/// but also listen to XDesktop and if app is terminating anyway, dispose m_xDoc while
/// its still possible to do so properly
css::uno::Reference<css::frame::XDesktop2> m_xDesktop;
osl::Mutex m_aMutex;
public:
CloseVetoButTerminateListener()
: cppu::WeakComponentImplHelper<css::frame::XTerminateListener>(m_aMutex)
{
}
void start(const css::uno::Reference<css::uno::XInterface>& rCloseable,
const css::uno::Reference<css::frame::XDesktop2>& rDesktop)
{
m_xDesktop = rDesktop;
m_xDesktop->addTerminateListener(this);
m_pCloseListener.reset(new utl::CloseVeto(rCloseable, true));
}
void stop()
{
m_pCloseListener.reset();
if (!m_xDesktop.is())
return;
m_xDesktop->removeTerminateListener(this);
m_xDesktop.clear();
}
// XTerminateListener
virtual void SAL_CALL queryTermination(const css::lang::EventObject& /*rEvent*/)
throw(css::frame::TerminationVetoException, css::uno::RuntimeException, std::exception) override
{
}
virtual void SAL_CALL notifyTermination(const css::lang::EventObject& /*rEvent*/)
throw(css::uno::RuntimeException, std::exception) override
{
stop();
}
virtual void SAL_CALL disposing() override
{
stop();
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)
stop();
}
};
rtl::Reference<CloseVetoButTerminateListener> m_xCloseVetoButTerminateListener;
public: public:
OCalcConnection(ODriver* _pDriver); OCalcConnection(ODriver* _pDriver);
virtual ~OCalcConnection(); virtual ~OCalcConnection();
@ -84,7 +146,7 @@ namespace connectivity
} }
~ODocHolder() ~ODocHolder()
{ {
m_xDoc.clear(); m_xDoc.clear();
m_pConnection->releaseDoc(); m_pConnection->releaseDoc();
} }
const css::uno::Reference< css::sheet::XSpreadsheetDocument>& getDoc() const { return m_xDoc; } const css::uno::Reference< css::sheet::XSpreadsheetDocument>& getDoc() const { return m_xDoc; }