# HG changeset patch # User Adam Chlipala # Date 1264535959 18000 # Node ID 94e83c5533d29da459dbb2a5c043e082ef73d763 # Parent 67d875c8ac713c3bb7b607bd87072bd8f8bf541a Handling errors during commit diff -r 67d875c8ac71 -r 94e83c5533d2 Makefile.in --- a/Makefile.in Tue Jan 26 09:04:55 2010 -0500 +++ b/Makefile.in Tue Jan 26 14:59:19 2010 -0500 @@ -92,6 +92,10 @@ 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 -r 67d875c8ac71 -r 94e83c5533d2 include/urweb.h --- a/include/urweb.h Tue Jan 26 09:04:55 2010 -0500 +++ b/include/urweb.h Tue Jan 26 14:59:19 2010 -0500 @@ -42,7 +42,8 @@ __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 -r 67d875c8ac71 -r 94e83c5533d2 lib/ur/string.ur --- a/lib/ur/string.ur Tue Jan 26 09:04:55 2010 -0500 +++ b/lib/ur/string.ur Tue Jan 26 14:59:19 2010 -0500 @@ -38,6 +38,17 @@ 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 -r 67d875c8ac71 -r 94e83c5533d2 lib/ur/string.urs --- a/lib/ur/string.urs Tue Jan 26 09:04:55 2010 -0500 +++ b/lib/ur/string.urs Tue Jan 26 14:59:19 2010 -0500 @@ -20,5 +20,6 @@ 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 -r 67d875c8ac71 -r 94e83c5533d2 src/c/request.c --- a/src/c/request.c Tue Jan 26 09:04:55 2010 -0500 +++ b/src/c/request.c Tue Jan 26 14:59:19 2010 -0500 @@ -339,7 +339,20 @@ 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, "Fatal Error"); + uw_write(ctx, "Fatal error: "); + uw_write(ctx, uw_error_message(ctx)); + uw_write(ctx, "\n"); + + 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 -r 67d875c8ac71 -r 94e83c5533d2 src/c/urweb.c --- a/src/c/urweb.c Tue Jan 26 09:04:55 2010 -0500 +++ b/src/c/urweb.c Tue Jan 26 14:59:19 2010 -0500 @@ -613,6 +613,10 @@ 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 @@ 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 (ctx->app->db_commit(ctx)) - uw_error(ctx, FATAL, "Error running SQL COMMIT"); + if (uw_has_error(ctx)) { + uw_rollback(ctx); + return; + } + } + + 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 @@ } } -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;