From dfb9e4355f14afd9b543b9967aa3095eb6b431eb Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Mon, 5 Feb 2018 11:23:36 +0100 Subject: Sqlite: Transaction catch exception in destructor Fixes coverity warning. We want to throw an exception in the destructor in this case, which is save because it is a RAII pattern and holds only trivial values. Actually this is the only way to communicate that rollback was failing. It is quite rare that it will be happen without an exception is already thrown. There is a non throwing variant too if you want to use it as a class member. Change-Id: Ie71ead19678619465c6ad9334d36ee666225dce7 Reviewed-by: Ivan Donchevskii --- src/libs/sqlite/sqlitetransaction.h | 77 +++++++++++++++++++++++++++++-------- 1 file changed, 62 insertions(+), 15 deletions(-) (limited to 'src/libs/sqlite') diff --git a/src/libs/sqlite/sqlitetransaction.h b/src/libs/sqlite/sqlitetransaction.h index 4fe80d27ec..c58519eb7d 100644 --- a/src/libs/sqlite/sqlitetransaction.h +++ b/src/libs/sqlite/sqlitetransaction.h @@ -27,6 +27,7 @@ #include "sqliteglobal.h" +#include #include namespace Sqlite { @@ -52,12 +53,6 @@ public: class AbstractTransaction { public: - ~AbstractTransaction() - { - if (!m_isAlreadyCommited) - m_interface.rollback(); - } - AbstractTransaction(const AbstractTransaction &) = delete; AbstractTransaction &operator=(const AbstractTransaction &) = delete; @@ -73,39 +68,91 @@ protected: { } -private: +protected: TransactionInterface &m_interface; bool m_isAlreadyCommited = false; }; -class DeferredTransaction final : public AbstractTransaction +class AbstractThrowingTransaction : public AbstractTransaction { public: - DeferredTransaction(TransactionInterface &interface) + ~AbstractThrowingTransaction() noexcept(false) + { + try { + if (!m_isAlreadyCommited) + m_interface.rollback(); + } catch (...) { + if (!std::uncaught_exception()) + throw; + } + } + +protected: + AbstractThrowingTransaction(TransactionInterface &interface) : AbstractTransaction(interface) { - interface.deferredBegin(); } }; -class ImmediateTransaction final : public AbstractTransaction +class AbstractNonThrowingDestructorTransaction : public AbstractTransaction { public: - ImmediateTransaction(TransactionInterface &interface) + ~AbstractNonThrowingDestructorTransaction() + { + try { + if (!m_isAlreadyCommited) + m_interface.rollback(); + } catch (...) { + } + } + +protected: + AbstractNonThrowingDestructorTransaction(TransactionInterface &interface) : AbstractTransaction(interface) + { + } +}; + +template +class BasicDeferredTransaction final : public BaseTransaction +{ +public: + BasicDeferredTransaction(TransactionInterface &interface) + : BaseTransaction(interface) + { + interface.deferredBegin(); + } +}; + +using DeferredTransaction = BasicDeferredTransaction; +using DeferredNonThrowingDestructorTransaction = BasicDeferredTransaction; + +template +class BasicImmediateTransaction final : public BaseTransaction +{ +public: + BasicImmediateTransaction(TransactionInterface &interface) + : BaseTransaction(interface) { interface.immediateBegin(); } }; -class ExclusiveTransaction final : public AbstractTransaction +using ImmediateTransaction = BasicImmediateTransaction; +using ImmediateNonThrowingDestructorTransaction = BasicImmediateTransaction; + +template +class BasicExclusiveTransaction final : public BaseTransaction { public: - ExclusiveTransaction(TransactionInterface &interface) - : AbstractTransaction(interface) + BasicExclusiveTransaction(TransactionInterface &interface) + : BaseTransaction(interface) { interface.exclusiveBegin(); } }; +using ExclusiveTransaction = BasicExclusiveTransaction; +using ExclusiveNonThrowingDestructorTransaction = BasicExclusiveTransaction; + } // namespace Sqlite -- cgit v1.2.1