diff options
author | Adam Chlipala <adam@chlipala.net> | 2014-04-15 19:12:49 -0400 |
---|---|---|
committer | Adam Chlipala <adam@chlipala.net> | 2014-04-15 19:12:49 -0400 |
commit | cf9fb5f2ff4c5a909729e6a48fdc82b6770b496d (patch) | |
tree | 877a82cf3774bb716de357292e2cd2eb8762b99d /src/c | |
parent | e84b707851f60f67050cf6d68aaf935c20612e66 (diff) |
Tweaking uw_commit() logic, partly to fix a resource clean-up bug on SQL serialization failures
Diffstat (limited to 'src/c')
-rw-r--r-- | src/c/urweb.c | 52 |
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); |