Skip to content

Commit 3b6cbfb

Browse files
committed
fix(pg): prevent debug assertion crash on cloudsync_init error path
In cloudsync_init_internal, when cloudsync_init_table returns an error (e.g. unsupported DWS/AWS algorithm), the error path called database_rollback_savepoint() which internally pushes a new active snapshot via database_refresh_snapshot(). The subsequent ereport(ERROR) longjmps through PG_CATCH → SPI_finish → PL/pgSQL exception handler, where EnsurePortalSnapshotExists() finds portal->portalSnapshot still set, triggering Assert(portal->portalSnapshot == NULL) in debug builds. Replace database_rollback_savepoint() with a direct call to RollbackAndReleaseCurrentSubTransaction(), skipping the snapshot refresh. Since we're about to propagate an error, PostgreSQL's error recovery handles snapshot cleanup automatically. Other callers of database_rollback_savepoint are safe because they either run on SQLite, return normally instead of raising ereport(ERROR), or disconnect SPI before the rollback.
1 parent 7a3d1d5 commit 3b6cbfb

File tree

1 file changed

+11
-2
lines changed

1 file changed

+11
-2
lines changed

src/postgresql/cloudsync_postgresql.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,10 +305,19 @@ static bytea *cloudsync_init_internal (cloudsync_context *data, const char *tabl
305305
dbutils_settings_set_key_value(data, "schema", cur_schema);
306306
}
307307
} else {
308-
// In case of error, rollback transaction
308+
// In case of error, rollback sub-transaction and raise.
309+
// We intentionally avoid database_rollback_savepoint() here
310+
// because it calls database_refresh_snapshot() which pushes a
311+
// new active snapshot. Pushing a snapshot after rollback and
312+
// before ereport(ERROR) leaves portal->portalSnapshot non-NULL
313+
// when PL/pgSQL's exception handler later calls
314+
// EnsurePortalSnapshotExists(), triggering
315+
// Assert(portal->portalSnapshot == NULL) on debug builds.
309316
char err[1024];
310317
snprintf(err, sizeof(err), "%s", cloudsync_errmsg(data));
311-
database_rollback_savepoint(data, "cloudsync_init");
318+
if (GetCurrentTransactionNestLevel() > 1) {
319+
RollbackAndReleaseCurrentSubTransaction();
320+
}
312321
ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("%s", err)));
313322
}
314323

0 commit comments

Comments
 (0)