diff options
-rw-r--r-- | Makefile.in | 4 | ||||
-rw-r--r-- | include/urweb.h | 3 | ||||
-rw-r--r-- | lib/ur/string.ur | 11 | ||||
-rw-r--r-- | lib/ur/string.urs | 1 | ||||
-rw-r--r-- | src/c/request.c | 15 | ||||
-rw-r--r-- | src/c/urweb.c | 74 |
6 files changed, 80 insertions, 28 deletions
diff --git a/Makefile.in b/Makefile.in index 99e1a3ac..d3a089c4 100644 --- a/Makefile.in +++ b/Makefile.in @@ -92,6 +92,10 @@ install: libtool --silent --mode=install install -c lib/c/liburweb_http.la $(LIB)/../liburweb_http.la libtool --silent --mode=install install -c lib/c/liburweb_cgi.la $(LIB)/../liburweb_cgi.la libtool --silent --mode=install install -c lib/c/liburweb_fastcgi.la $(LIB)/../liburweb_fastcgi.la + libtool --silent --finish $(LIB)/../liburweb.la + libtool --silent --finish $(LIB)/../liburweb_http.la + libtool --silent --finish $(LIB)/../liburweb_cgi.la + libtool --silent --finish $(LIB)/../liburweb_fastcgi.la package: hg archive -t tgz -X tests /tmp/urweb.tgz diff --git a/include/urweb.h b/include/urweb.h index b62adce1..3a2d2baf 100644 --- a/include/urweb.h +++ b/include/urweb.h @@ -42,7 +42,8 @@ int uw_rollback(uw_context); __attribute__((noreturn)) void uw_error(uw_context, failure_kind, const char *fmt, ...); char *uw_error_message(uw_context); -void uw_set_error_message(uw_context, const char *); +void uw_set_error_message(uw_context, const char *fmt, ...); +int uw_has_error(uw_context); void uw_push_cleanup(uw_context, void (*func)(void *), void *arg); void uw_pop_cleanup(uw_context); diff --git a/lib/ur/string.ur b/lib/ur/string.ur index 4025cf68..07d7e6b8 100644 --- a/lib/ur/string.ur +++ b/lib/ur/string.ur @@ -38,6 +38,17 @@ fun all f s = al 0 end +fun mp f s = + let + fun mp' i acc = + if i < 0 then + acc + else + mp' (i - 1) (str (f (sub s i)) ^ acc) + in + mp' (length s - 1) "" + end + fun newlines [ctx] [[Body] ~ ctx] s : xml ([Body] ++ ctx) [] [] = case split s #"\n" of None => cdata s diff --git a/lib/ur/string.urs b/lib/ur/string.urs index 5590b50c..557e73c0 100644 --- a/lib/ur/string.urs +++ b/lib/ur/string.urs @@ -20,5 +20,6 @@ val split : t -> char -> option (string * string) val msplit : {Haystack : t, Needle : t} -> option (string * char * string) val all : (char -> bool) -> string -> bool +val mp : (char -> char) -> string -> string val newlines : ctx ::: {Unit} -> [[Body] ~ ctx] => string -> xml ([Body] ++ ctx) [] [] 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; |