summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Adam Chlipala <adam@chlipala.net>2014-04-15 19:12:49 -0400
committerGravatar Adam Chlipala <adam@chlipala.net>2014-04-15 19:12:49 -0400
commitcf9fb5f2ff4c5a909729e6a48fdc82b6770b496d (patch)
tree877a82cf3774bb716de357292e2cd2eb8762b99d /src
parente84b707851f60f67050cf6d68aaf935c20612e66 (diff)
Tweaking uw_commit() logic, partly to fix a resource clean-up bug on SQL serialization failures
Diffstat (limited to 'src')
-rw-r--r--src/c/urweb.c52
1 files changed, 39 insertions, 13 deletions
diff --git a/src/c/urweb.c b/src/c/urweb.c
index df137e77..7417e4b7 100644
--- a/src/c/urweb.c
+++ b/src/c/urweb.c
@@ -3304,32 +3304,58 @@ int uw_commit(uw_context ctx) {
}
}
- for (i = ctx->used_transactionals-1; i >= 0; --i)
- if (ctx->transactionals[i].rollback == NULL)
- if (ctx->transactionals[i].commit) {
- ctx->transactionals[i].commit(ctx->transactionals[i].data);
- if (uw_has_error(ctx)) {
- uw_rollback(ctx, 0);
- return 0;
- }
- }
-
if (ctx->transaction_started) {
int code = ctx->app->db_commit(ctx);
if (code) {
- if (code == -1)
+ if (ctx->client)
+ release_client(ctx->client);
+
+ if (code == -1) {
+ // This case is for a serialization failure, which is not really an "error."
+ // The transaction will restart, so we should rollback any transactionals
+ // that triggered above.
+
+ for (i = ctx->used_transactionals-1; i >= 0; --i)
+ if (ctx->transactionals[i].rollback != NULL)
+ ctx->transactionals[i].rollback(ctx->transactionals[i].data);
+
+ for (i = ctx->used_transactionals-1; i >= 0; --i)
+ if (ctx->transactionals[i].free)
+ ctx->transactionals[i].free(ctx->transactionals[i].data, 1);
+
return 1;
+ }
for (i = ctx->used_transactionals-1; i >= 0; --i)
- if (ctx->transactionals[i].free)
- ctx->transactionals[i].free(ctx->transactionals[i].data, 0);
+ if (ctx->transactionals[i].free)
+ ctx->transactionals[i].free(ctx->transactionals[i].data, 0);
uw_set_error_message(ctx, "Error running SQL COMMIT");
return 0;
}
}
+ for (i = ctx->used_transactionals-1; i >= 0; --i)
+ if (ctx->transactionals[i].rollback == NULL)
+ if (ctx->transactionals[i].commit) {
+ ctx->transactionals[i].commit(ctx->transactionals[i].data);
+ if (uw_has_error(ctx)) {
+ if (ctx->client)
+ release_client(ctx->client);
+
+ for (i = ctx->used_transactionals-1; i >= 0; --i)
+ if (ctx->transactionals[i].rollback != NULL)
+ ctx->transactionals[i].rollback(ctx->transactionals[i].data);
+
+ for (i = ctx->used_transactionals-1; i >= 0; --i)
+ if (ctx->transactionals[i].free)
+ ctx->transactionals[i].free(ctx->transactionals[i].data, 0);
+
+ return 0;
+ }
+ }
+
for (i = 0; i < ctx->used_deltas; ++i) {
delta *d = &ctx->deltas[i];
client *c = find_client(d->client);