diff options
-rw-r--r-- | include/urweb/urweb_cpp.h | 1 | ||||
-rw-r--r-- | src/c/http.c | 4 | ||||
-rw-r--r-- | src/c/urweb.c | 24 | ||||
-rw-r--r-- | src/cjr_print.sml | 12 |
4 files changed, 32 insertions, 9 deletions
diff --git a/include/urweb/urweb_cpp.h b/include/urweb/urweb_cpp.h index 4779b95a..fb3c83a2 100644 --- a/include/urweb/urweb_cpp.h +++ b/include/urweb/urweb_cpp.h @@ -37,6 +37,7 @@ void uw_set_on_success(char *); void uw_set_headers(struct uw_context *, char *(*get_header)(void *, const char *), void *get_header_data); void uw_set_env(struct uw_context *, char *(*get_env)(void *, const char *), void *get_env_data); failure_kind uw_begin(struct uw_context *, char *path); +void uw_ensure_transaction(struct uw_context *); failure_kind uw_begin_onError(struct uw_context *, char *msg); void uw_login(struct uw_context *); void uw_commit(struct uw_context *); diff --git a/src/c/http.c b/src/c/http.c index 5ceca059..d19ce350 100644 --- a/src/c/http.c +++ b/src/c/http.c @@ -260,7 +260,9 @@ static void *worker(void *data) { close(sock); sock = 0; } - } else if (rr != KEEP_OPEN) + } else if (rr == KEEP_OPEN) + sock = 0; + else fprintf(stderr, "Illegal uw_request return code: %d\n", rr); break; diff --git a/src/c/urweb.c b/src/c/urweb.c index 8bd5ada9..cd724cbf 100644 --- a/src/c/urweb.c +++ b/src/c/urweb.c @@ -431,6 +431,7 @@ struct uw_context { unsigned long long source_count; void *db; + int transaction_started; jmp_buf jmp_buf; @@ -507,6 +508,7 @@ uw_context uw_init(int id, void *logger_data, uw_logger log_debug) { ctx->sz_inputs = ctx->n_subinputs = ctx->used_subinputs = 0; ctx->db = NULL; + ctx->transaction_started = 0; ctx->regions = NULL; @@ -631,6 +633,7 @@ void uw_reset_keep_error_message(uw_context ctx) { ctx->amInitializing = 0; ctx->usedSig = 0; ctx->needsResig = 0; + ctx->transaction_started = 0; } void uw_reset_keep_request(uw_context ctx) { @@ -766,16 +769,20 @@ void uw_login(uw_context ctx) { failure_kind uw_begin(uw_context ctx, char *path) { int r = setjmp(ctx->jmp_buf); - if (r == 0) { - if (ctx->app->db_begin(ctx)) - uw_error(ctx, BOUNDED_RETRY, "Error running SQL BEGIN"); - + if (r == 0) ctx->app->handle(ctx, path); - } return r; } +void uw_ensure_transaction(uw_context ctx) { + if (!ctx->transaction_started) { + if (ctx->app->db_begin(ctx)) + uw_error(ctx, BOUNDED_RETRY, "Error running SQL BEGIN"); + ctx->transaction_started = 1; + } +} + uw_Basis_client uw_Basis_self(uw_context ctx) { if (ctx->client == NULL) uw_error(ctx, FATAL, "Call to Basis.self() from page that has only server-side code"); @@ -3205,7 +3212,7 @@ int uw_rollback(uw_context ctx, int will_retry) { if (ctx->transactionals[i].free) ctx->transactionals[i].free(ctx->transactionals[i].data, will_retry); - return ctx->app ? ctx->app->db_rollback(ctx) : 0; + return (ctx->app && ctx->transaction_started) ? ctx->app->db_rollback(ctx) : 0; } static const char begin_xhtml[] = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">"; @@ -3262,7 +3269,7 @@ void uw_commit(uw_context ctx) { } } - if (ctx->app->db_commit(ctx)) { + if (ctx->transaction_started && ctx->app->db_commit(ctx)) { uw_set_error_message(ctx, "Error running SQL COMMIT"); return; } @@ -3453,6 +3460,7 @@ failure_kind uw_initialize(uw_context ctx) { if (r == 0) { if (ctx->app->db_begin(ctx)) uw_error(ctx, FATAL, "Error running SQL BEGIN"); + ctx->transaction_started = 1; ctx->app->initializer(ctx); if (ctx->app->db_commit(ctx)) uw_error(ctx, FATAL, "Error running SQL COMMIT"); @@ -4037,6 +4045,7 @@ failure_kind uw_runCallback(uw_context ctx, void (*callback)(uw_context)) { if (r == 0) { if (ctx->app->db_begin(ctx)) uw_error(ctx, BOUNDED_RETRY, "Error running SQL BEGIN"); + ctx->transaction_started = 1; callback(ctx); } @@ -4085,6 +4094,7 @@ failure_kind uw_begin_onError(uw_context ctx, char *msg) { if (r == 0) { if (ctx->app->db_begin(ctx)) uw_error(ctx, BOUNDED_RETRY, "Error running SQL BEGIN"); + ctx->transaction_started = 1; uw_buffer_reset(&ctx->outHeaders); if (on_success[0]) diff --git a/src/cjr_print.sml b/src/cjr_print.sml index bc8f1be6..e98918e6 100644 --- a/src/cjr_print.sml +++ b/src/cjr_print.sml @@ -2079,6 +2079,8 @@ and p_exp' par tail env (e, loc) = newline, string "int dummy = (uw_begin_region(ctx), 0);", newline, + string "uw_ensure_transaction(ctx);", + newline, case prepared of NONE => @@ -2140,6 +2142,8 @@ and p_exp' par tail env (e, loc) = p_exp' false false env dml, string ";", newline, + string "uw_ensure_transaction(ctx);", + newline, newline, #dml (Settings.currentDbms ()) (loc, mode)] | SOME {id, dml = dml'} => @@ -2159,8 +2163,10 @@ and p_exp' par tail env (e, loc) = string ";"]) inputs, newline, + string "uw_ensure_transaction(ctx);", newline, - + newline, + #dmlPrepared (Settings.currentDbms ()) {loc = loc, id = id, dml = dml', @@ -2184,6 +2190,8 @@ and p_exp' par tail env (e, loc) = newline, string "uw_Basis_int n;", newline, + string "uw_ensure_transaction(ctx);", + newline, case prepared of NONE => #nextval (Settings.currentDbms ()) {loc = loc, @@ -2204,6 +2212,8 @@ and p_exp' par tail env (e, loc) = | ESetval {seq, count} => box [string "({", newline, + string "uw_ensure_transaction(ctx);", + newline, #setval (Settings.currentDbms ()) {loc = loc, seqE = p_exp' false false env seq, |