diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/c/request.c | 15 | ||||
-rw-r--r-- | src/c/urweb.c | 74 |
2 files changed, 62 insertions, 27 deletions
diff --git a/src/c/request.c b/src/c/request.c index 1a2c0a93..247ae92c 100644 --- a/src/c/request.c +++ b/src/c/request.c @@ -339,7 +339,20 @@ request_result uw_request(uw_request_context rc, uw_context ctx, fk = uw_begin(ctx, rc->path_copy); if (fk == SUCCESS || fk == RETURN_INDIRECTLY) { uw_commit(ctx); - return SERVED; + if (uw_has_error(ctx)) { + log_error(logger_data, "Fatal error: %s\n", uw_error_message(ctx)); + + uw_reset_keep_error_message(ctx); + on_failure(ctx); + uw_write_header(ctx, "Content-type: text/html\r\n"); + uw_write(ctx, "<html><head><title>Fatal Error</title></head><body>"); + uw_write(ctx, "Fatal error: "); + uw_write(ctx, uw_error_message(ctx)); + uw_write(ctx, "\n</body></html>"); + + return FAILED; + } else + return SERVED; } else if (fk == BOUNDED_RETRY) { if (retries_left) { log_debug(logger_data, "Error triggers bounded retry: %s\n", uw_error_message(ctx)); diff --git a/src/c/urweb.c b/src/c/urweb.c index 8ccecdaa..28b73715 100644 --- a/src/c/urweb.c +++ b/src/c/urweb.c @@ -613,6 +613,10 @@ static void uw_set_error(uw_context ctx, const char *fmt, ...) { vsnprintf(ctx->error_message, ERROR_BUF_LEN, fmt, ap); } +int uw_has_error(uw_context ctx) { + return ctx->error_message[0] != 0; +} + __attribute__((noreturn)) void uw_error(uw_context ctx, failure_kind fk, const char *fmt, ...) { cleanup *cl; @@ -2888,21 +2892,61 @@ uw_unit uw_Basis_send(uw_context ctx, uw_Basis_channel chn, uw_Basis_string msg) return uw_unit_v; } +int uw_rollback(uw_context ctx) { + int i; + cleanup *cl; + + if (ctx->client) + release_client(ctx->client); + + for (cl = ctx->cleanup; cl < ctx->cleanup_front; ++cl) + cl->func(cl->arg); + + ctx->cleanup_front = ctx->cleanup; + + 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); + + return ctx->app->db_rollback(ctx); +} + void uw_commit(uw_context ctx) { int i; + if (uw_has_error(ctx)) { + uw_rollback(ctx); + return; + } + for (i = ctx->used_transactionals-1; i >= 0; --i) if (ctx->transactionals[i].rollback != NULL) - if (ctx->transactionals[i].commit) + if (ctx->transactionals[i].commit) { ctx->transactionals[i].commit(ctx->transactionals[i].data); + if (uw_has_error(ctx)) { + uw_rollback(ctx); + return; + } + } for (i = ctx->used_transactionals-1; i >= 0; --i) if (ctx->transactionals[i].rollback == NULL) - if (ctx->transactionals[i].commit) + if (ctx->transactionals[i].commit) { ctx->transactionals[i].commit(ctx->transactionals[i].data); + if (uw_has_error(ctx)) { + uw_rollback(ctx); + return; + } + } - if (ctx->app->db_commit(ctx)) - uw_error(ctx, FATAL, "Error running SQL COMMIT"); + if (ctx->app->db_commit(ctx)) { + uw_set_error_message(ctx, "Error running SQL COMMIT"); + return; + } for (i = 0; i < ctx->used_deltas; ++i) { delta *d = &ctx->deltas[i]; @@ -2954,28 +2998,6 @@ void uw_commit(uw_context ctx) { } } -int uw_rollback(uw_context ctx) { - int i; - cleanup *cl; - - if (ctx->client) - release_client(ctx->client); - - for (cl = ctx->cleanup; cl < ctx->cleanup_front; ++cl) - cl->func(cl->arg); - - ctx->cleanup_front = ctx->cleanup; - - 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); - - return ctx->app->db_rollback(ctx); -} size_t uw_transactionals_max = SIZE_MAX; |