Skip to content

Fix Savepoint destructor exception-safety and rollback bookkeeping#559

Merged
SRombauts merged 2 commits into
masterfrom
fix-savepoint-destructor-exception-safety
Jul 1, 2026
Merged

Fix Savepoint destructor exception-safety and rollback bookkeeping#559
SRombauts merged 2 commits into
masterfrom
fix-savepoint-destructor-exception-safety

Conversation

@SRombauts

Copy link
Copy Markdown
Owner

Summary

Fixes two findings from the deep code review (SP-03, SP-02) in the Savepoint destructor. The documented auto-rollback-on-scope-exit semantics are unchanged.

SP-03 — destructor could call std::terminate

~Savepoint() caught only SQLite::Exception. Building the "ROLLBACK TO SAVEPOINT " + msName / "RELEASE SAVEPOINT " + msName strings can throw std::bad_alloc, and any non-SQLite::Exception thrown during cleanup would escape the implicitly noexcept destructor and terminate the process. The handler is now catch (...), matching the stated intent ("Never throw an exception in a destructor").

SP-02 — no rolled-back state, fragile double-rollback

There was a single mbReleased flag and no notion of "already rolled back", so after a manual rollbackTo() (or on the normal scope-exit path) the destructor issued a ROLLBACK TO and then a RELEASE, relying on SQLite tolerating a repeated ROLLBACK TO. A new mbRolledBack flag (set in rollbackTo()) lets the destructor do the minimum: skip the redundant ROLLBACK TO and just RELEASE.

Test plan

  • Added Savepoint.rollbackToThenRelease covering a manual rollbackTo() followed by release() and a clean scope exit.
  • Built SQLiteCpp_tests (MSVC, Debug); ctest -C Debug 100% passed, including the existing Savepoint.commitRollback and Savepoint.destructorSwallowsException tests.

No public API or behavioural change on the happy path; only the (previously UB-on-OOM) destructor error handling and the redundant-command path change.

@coveralls

coveralls commented Jun 30, 2026

Copy link
Copy Markdown

Coverage Status

coverage: 99.689% (+0.001%) from 99.688% — fix-savepoint-destructor-exception-safety into master

@SRombauts SRombauts self-assigned this Jun 30, 2026
@SRombauts SRombauts added the bug label Jun 30, 2026
The destructor caught only SQLite::Exception, so a std::bad_alloc thrown
while building the "ROLLBACK TO SAVEPOINT ..." / "RELEASE SAVEPOINT ..."
strings (or any other non-SQLite exception) escaped the implicitly noexcept
destructor and called std::terminate. Broaden the handler to catch(...).

Track an explicit mbRolledBack state so the destructor issues the minimum
commands: when a rollback already happened (manual rollbackTo(), or the
scope-exit path), it now does a single RELEASE instead of relying on SQLite
tolerating a repeated ROLLBACK TO. The documented auto-rollback semantics
are unchanged.

Add a regression test covering a manual rollbackTo() followed by release().

Fixes SP-02 and SP-03 from the code review.
@SRombauts SRombauts force-pushed the fix-savepoint-destructor-exception-safety branch from 8cd214f to afa51d3 Compare June 30, 2026 21:50
The destructor caught only SQLite::Exception, so a std::bad_alloc thrown
while building the "ROLLBACK TRANSACTION" string (or any other non-SQLite
exception) escaped the implicitly noexcept destructor and called
std::terminate. Broaden the handler to catch(...), matching the Savepoint
fix (afa51d3).

Fixes TXN-08 from the code review.
@SRombauts SRombauts merged commit 4ee4be1 into master Jul 1, 2026
38 checks passed
@SRombauts SRombauts deleted the fix-savepoint-destructor-exception-safety branch July 1, 2026 09:33
SRombauts added a commit that referenced this pull request Jul 1, 2026
The Transaction destructor already catches (...) since #559, and the T1
throw-from-destructor theme is resolved with it.
SRombauts added a commit that referenced this pull request Jul 1, 2026
The Transaction destructor already catches (...) since #559, and the T1
throw-from-destructor theme is resolved with it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants