diff options
author | Ziv Scully <ziv@mit.edu> | 2014-05-27 21:38:01 -0400 |
---|---|---|
committer | Ziv Scully <ziv@mit.edu> | 2014-05-27 21:38:01 -0400 |
commit | dc336268adfbf2b05b34ab006de5990f8ce9086c (patch) | |
tree | 22fb72ef5ad32f47571fa250515108188d7e22f9 /src/c | |
parent | d941d873c0203009ccf44aa4aed97671703ca375 (diff) | |
parent | 4cee29f03879d25963e3d8a8dda879e0a007033c (diff) |
Merge.
Diffstat (limited to 'src/c')
-rw-r--r-- | src/c/cgi.c | 6 | ||||
-rw-r--r-- | src/c/fastcgi.c | 13 | ||||
-rw-r--r-- | src/c/http.c | 14 | ||||
-rw-r--r-- | src/c/request.c | 40 | ||||
-rw-r--r-- | src/c/static.c | 6 | ||||
-rw-r--r-- | src/c/urweb.c | 117 |
6 files changed, 136 insertions, 60 deletions
diff --git a/src/c/cgi.c b/src/c/cgi.c index 539b83c2..d060532c 100644 --- a/src/c/cgi.c +++ b/src/c/cgi.c @@ -60,8 +60,10 @@ static void log_error(void *data, const char *fmt, ...) { static void log_debug(void *data, const char *fmt, ...) { } +static uw_loggers ls = {NULL, log_error, log_debug}; + int main(int argc, char *argv[]) { - uw_context ctx = uw_request_new_context(0, &uw_application, NULL, log_error, log_debug); + uw_context ctx = uw_request_new_context(0, &uw_application, &ls); uw_request_context rc = uw_new_request_context(); request_result rr; char *method = getenv("REQUEST_METHOD"), @@ -108,7 +110,7 @@ int main(int argc, char *argv[]) { uw_set_on_success(""); uw_set_headers(ctx, get_header, NULL); uw_set_env(ctx, get_env, NULL); - uw_request_init(&uw_application, NULL, log_error, log_debug); + uw_request_init(&uw_application, &ls); body[body_pos] = 0; rr = uw_request(rc, ctx, method, path, query_string, body, body_pos, diff --git a/src/c/fastcgi.c b/src/c/fastcgi.c index 5c80d3ae..f3e66e3a 100644 --- a/src/c/fastcgi.c +++ b/src/c/fastcgi.c @@ -324,7 +324,8 @@ int fastcgi_send_normal(int sock, const void *buf, ssize_t len) { static void *worker(void *data) { FCGI_Input *in = fastcgi_input(); FCGI_Output *out = fastcgi_output(); - uw_context ctx = uw_request_new_context(*(int *)data, &uw_application, out, log_error, log_debug); + uw_loggers ls = {out, log_error, log_debug}; + uw_context ctx = uw_request_new_context(*(int *)data, &uw_application, &ls); uw_request_context rc = uw_new_request_context(); headers hs; size_t body_size = 0; @@ -514,7 +515,7 @@ static void sigint(int signum) { exit(0); } -static loggers ls = {&uw_application, NULL, log_error, log_debug}; +static uw_loggers ls = {NULL, log_error, log_debug}; int main(int argc, char *argv[]) { // The skeleton for this function comes from Beej's sockets tutorial. @@ -563,7 +564,7 @@ int main(int argc, char *argv[]) { } uw_set_on_success(""); - uw_request_init(&uw_application, NULL, log_error, log_debug); + uw_request_init(&uw_application, &ls); names = calloc(nthreads, sizeof(int)); @@ -572,7 +573,11 @@ int main(int argc, char *argv[]) { { pthread_t thread; - if (pthread_create_big(&thread, NULL, client_pruner, &ls)) { + pruner_data *pd = (pruner_data *)malloc(sizeof(pruner_data)); + pd->app = &uw_application; + pd->loggers = &ls; + + if (pthread_create_big(&thread, NULL, client_pruner, pd)) { fprintf(stderr, "Error creating pruner thread\n"); return 1; } diff --git a/src/c/http.c b/src/c/http.c index 25d2a320..32dd1dd1 100644 --- a/src/c/http.c +++ b/src/c/http.c @@ -70,9 +70,11 @@ static void log_debug(void *data, const char *fmt, ...) { } } +static uw_loggers ls = {NULL, log_error, log_debug}; + static void *worker(void *data) { int me = *(int *)data; - uw_context ctx = uw_request_new_context(me, &uw_application, NULL, log_error, log_debug); + uw_context ctx = uw_request_new_context(me, &uw_application, &ls); size_t buf_size = 1024; char *buf = malloc(buf_size), *back = buf; uw_request_context rc = uw_new_request_context(); @@ -307,8 +309,6 @@ static void sigint(int signum) { exit(0); } -static loggers ls = {&uw_application, NULL, log_error, log_debug}; - int main(int argc, char *argv[]) { // The skeleton for this function comes from Beej's sockets tutorial. int sockfd; // listen on sock_fd @@ -374,7 +374,7 @@ int main(int argc, char *argv[]) { } } - uw_request_init(&uw_application, NULL, log_error, log_debug); + uw_request_init(&uw_application, &ls); names = calloc(nthreads, sizeof(int)); @@ -411,7 +411,11 @@ int main(int argc, char *argv[]) { { pthread_t thread; - if (pthread_create_big(&thread, NULL, client_pruner, &ls)) { + pruner_data *pd = (pruner_data *)malloc(sizeof(pruner_data)); + pd->app = &uw_application; + pd->loggers = &ls; + + if (pthread_create_big(&thread, NULL, client_pruner, pd)) { fprintf(stderr, "Error creating pruner thread\n"); return 1; } diff --git a/src/c/request.c b/src/c/request.c index b925cc3c..813d967c 100644 --- a/src/c/request.c +++ b/src/c/request.c @@ -12,6 +12,7 @@ #include <pthread.h> #include "urweb.h" +#include "request.h" #define MAX_RETRIES 5 @@ -32,8 +33,11 @@ static int try_rollback(uw_context ctx, int will_retry, void *logger_data, uw_lo return r; } -uw_context uw_request_new_context(int id, uw_app *app, void *logger_data, uw_logger log_error, uw_logger log_debug) { - uw_context ctx = uw_init(id, logger_data, log_debug); +uw_context uw_request_new_context(int id, uw_app *app, uw_loggers *ls) { + void *logger_data = ls->logger_data; + uw_logger log_debug = ls->log_debug; + uw_logger log_error = ls->log_error; + uw_context ctx = uw_init(id, ls); int retries_left = MAX_RETRIES; uw_set_app(ctx, app); @@ -78,20 +82,15 @@ static void *ticker(void *data) { } typedef struct { - uw_app *app; - void *logger_data; - uw_logger log_error, log_debug; -} loggers; - -typedef struct { int id; - loggers *ls; + uw_loggers *ls; uw_periodic pdic; + uw_app *app; } periodic; static void *periodic_loop(void *data) { periodic *p = (periodic *)data; - uw_context ctx = uw_request_new_context(p->id, p->ls->app, p->ls->logger_data, p->ls->log_error, p->ls->log_debug); + uw_context ctx = uw_request_new_context(p->id, p->app, p->ls); if (!ctx) exit(1); @@ -145,14 +144,17 @@ int pthread_create_big(pthread_t *outThread, void *foo, void *threadFunc, void * } } -void uw_request_init(uw_app *app, void *logger_data, uw_logger log_error, uw_logger log_debug) { +void uw_request_init(uw_app *app, uw_loggers* ls) { uw_context ctx; failure_kind fk; uw_periodic *ps; - loggers *ls = malloc(sizeof(loggers)); int id; char *stackSize_s; + uw_logger log_debug = ls->log_debug; + uw_logger log_error = ls->log_error; + void* logger_data = ls->logger_data; + if ((stackSize_s = getenv("URWEB_STACK_SIZE")) != NULL && stackSize_s[0] != 0) { stackSize = atoll(stackSize_s); @@ -162,11 +164,6 @@ void uw_request_init(uw_app *app, void *logger_data, uw_logger log_error, uw_log } } - ls->app = app; - ls->logger_data = logger_data; - ls->log_error = log_error; - ls->log_debug = log_debug; - uw_global_init(); uw_app_init(app); @@ -179,7 +176,7 @@ void uw_request_init(uw_app *app, void *logger_data, uw_logger log_error, uw_log } } - ctx = uw_request_new_context(0, app, logger_data, log_error, log_debug); + ctx = uw_request_new_context(0, app, ls); if (!ctx) exit(1); @@ -205,6 +202,7 @@ void uw_request_init(uw_app *app, void *logger_data, uw_logger log_error, uw_log arg->id = id++; arg->ls = ls; arg->pdic = *ps; + arg->app = app; if (pthread_create_big(&thread, NULL, periodic_loop, arg)) { fprintf(stderr, "Error creating periodic thread\n"); @@ -240,7 +238,7 @@ request_result uw_request(uw_request_context rc, uw_context ctx, void (*on_success)(uw_context), void (*on_failure)(uw_context), void *logger_data, uw_logger log_error, uw_logger log_debug, int sock, - int (*send)(int sockfd, const void *buf, size_t len), + int (*send)(int sockfd, const void *buf, ssize_t len), int (*close)(int fd)) { int retries_left = MAX_RETRIES; failure_kind fk; @@ -588,8 +586,8 @@ request_result uw_request(uw_request_context rc, uw_context ctx, } void *client_pruner(void *data) { - loggers *ls = (loggers *)data; - uw_context ctx = uw_request_new_context(0, ls->app, ls->logger_data, ls->log_error, ls->log_debug); + pruner_data *pd = (pruner_data *)data; + uw_context ctx = uw_request_new_context(0, pd->app, pd->loggers); if (!ctx) exit(1); diff --git a/src/c/static.c b/src/c/static.c index 80ea5387..8f35a2d4 100644 --- a/src/c/static.c +++ b/src/c/static.c @@ -7,13 +7,15 @@ extern uw_app uw_application; -static void log_debug(void *data, const char *fmt, ...) { +static void log_(void *data, const char *fmt, ...) { va_list ap; va_start(ap, fmt); vprintf(fmt, ap); } +static uw_loggers loggers = {NULL, log_, log_}; + int main(int argc, char *argv[]) { uw_context ctx; failure_kind fk; @@ -23,7 +25,7 @@ int main(int argc, char *argv[]) { return 1; } - ctx = uw_init(0, NULL, log_debug); + ctx = uw_init(0, &loggers); uw_set_app(ctx, &uw_application); uw_initialize(ctx); diff --git a/src/c/urweb.c b/src/c/urweb.c index d4c0b439..78afcd05 100644 --- a/src/c/urweb.c +++ b/src/c/urweb.c @@ -460,8 +460,7 @@ struct uw_context { void *client_data; - void *logger_data; - uw_logger log_debug; + uw_loggers *loggers; int isPost, hasPostBody; uw_Basis_postBody postBody; @@ -487,7 +486,7 @@ size_t uw_page_max = SIZE_MAX; size_t uw_heap_max = SIZE_MAX; size_t uw_script_max = SIZE_MAX; -uw_context uw_init(int id, void *logger_data, uw_logger log_debug) { +uw_context uw_init(int id, uw_loggers *lg) { uw_context ctx = malloc(sizeof(struct uw_context)); ctx->app = NULL; @@ -546,8 +545,7 @@ uw_context uw_init(int id, void *logger_data, uw_logger log_debug) { ctx->client_data = uw_init_client_data(); - ctx->logger_data = logger_data; - ctx->log_debug = log_debug; + ctx->loggers = lg; ctx->isPost = ctx->hasPostBody = 0; @@ -601,6 +599,11 @@ void *uw_get_db(uw_context ctx) { return ctx->db; } + +uw_loggers* uw_get_loggers(struct uw_context *ctx) { + return ctx->loggers; +} + void uw_free(uw_context ctx) { size_t i; @@ -1258,17 +1261,34 @@ void uw_end_initializing(uw_context ctx) { ctx->amInitializing = 0; } +static void align_heap(uw_context ctx) { + size_t posn = ctx->heap.front - ctx->heap.start; + + if (posn % 4 != 0) { + size_t bump = 4 - posn % 4; + uw_check_heap(ctx, bump); + ctx->heap.front += bump; + } +} + void *uw_malloc(uw_context ctx, size_t len) { + // On some architectures, it's important that all word-sized memory accesses + // be to word-aligned addresses, so we'll do a little bit of extra work here + // in anticipation of a possible word-aligned access to the address we'll + // return. + void *result; if (ctx->amInitializing) { - result = malloc(len); + int error = posix_memalign(&result, 4, len); - if (result) + if (!error) return result; else - uw_error(ctx, FATAL, "uw_malloc: malloc() returns 0"); + uw_error(ctx, FATAL, "uw_malloc: posix_memalign() returns %d", error); } else { + align_heap(ctx); + uw_check_heap(ctx, len); result = ctx->heap.front; @@ -1278,6 +1298,8 @@ void *uw_malloc(uw_context ctx, size_t len) { } void uw_begin_region(uw_context ctx) { + align_heap(ctx); + regions *r = (regions *) ctx->heap.front; uw_check_heap(ctx, sizeof(regions)); @@ -1588,6 +1610,9 @@ uw_Basis_source uw_Basis_new_client_source(uw_context ctx, uw_Basis_string s) { int len; size_t s_len = strlen(s); + if(ctx->id < 0) + uw_error(ctx, FATAL, "Attempt to create client source using inappropriate context"); + uw_check_script(ctx, 15 + 2 * INTS_MAX + s_len); sprintf(ctx->script.front, "s%d_%llu=sc(exec(%n", ctx->id, ctx->source_count, &len); ctx->script.front += len; @@ -3316,32 +3341,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); @@ -3455,11 +3506,12 @@ int uw_commit(uw_context ctx) { size_t uw_transactionals_max = SIZE_MAX; -void uw_register_transactional(uw_context ctx, void *data, uw_callback commit, uw_callback rollback, +int uw_register_transactional(uw_context ctx, void *data, uw_callback commit, uw_callback rollback, uw_callback_with_retry free) { if (ctx->used_transactionals >= ctx->n_transactionals) { if (ctx->used_transactionals+1 > uw_transactionals_max) - uw_error(ctx, FATAL, "Exceeded limit on number of transactionals"); + // Exceeded limit on number of transactionals. + return -1; ctx->transactionals = realloc(ctx->transactionals, sizeof(transactional) * (ctx->used_transactionals+1)); ++ctx->n_transactionals; } @@ -3468,6 +3520,8 @@ void uw_register_transactional(uw_context ctx, void *data, uw_callback commit, u ctx->transactionals[ctx->used_transactionals].commit = commit; ctx->transactionals[ctx->used_transactionals].rollback = rollback; ctx->transactionals[ctx->used_transactionals++].free = free; + + return 0; } @@ -3965,7 +4019,8 @@ uw_Basis_int uw_Basis_toSeconds(uw_context ctx, uw_Basis_time tm) { uw_Basis_time uw_Basis_fromDatetime(uw_context ctx, uw_Basis_int year, uw_Basis_int month, uw_Basis_int day, uw_Basis_int hour, uw_Basis_int minute, uw_Basis_int second) { struct tm tm = { .tm_year = year - 1900, .tm_mon = month, .tm_mday = day, - .tm_hour = hour, .tm_min = minute, .tm_sec = second }; + .tm_hour = hour, .tm_min = minute, .tm_sec = second, + .tm_isdst = -1 }; uw_Basis_time r = { timelocal(&tm) }; return r; } @@ -4136,8 +4191,8 @@ uw_Basis_int uw_Basis_naughtyDebug(uw_context ctx, uw_Basis_string s) { } uw_Basis_unit uw_Basis_debug(uw_context ctx, uw_Basis_string s) { - if (ctx->log_debug) - ctx->log_debug(ctx->logger_data, "%s\n", s); + if (ctx->loggers->log_debug) + ctx->loggers->log_debug(ctx->loggers->logger_data, "%s\n", s); else fprintf(stderr, "%s\n", s); return uw_unit_v; @@ -4379,3 +4434,13 @@ uw_Basis_postField *uw_Basis_firstFormField(uw_context ctx, uw_Basis_string s) { return f; } + +uw_Basis_string uw_Basis_blessData(uw_context ctx, uw_Basis_string s) { + char *p = s; + + for (; *p; ++p) + if (!isalnum(*p) && *p != '-' && *p != '_') + uw_error(ctx, FATAL, "Illegal HTML5 data-* attribute: %s", s); + + return s; +} |