summaryrefslogtreecommitdiff
path: root/src/c
diff options
context:
space:
mode:
Diffstat (limited to 'src/c')
-rw-r--r--src/c/cgi.c6
-rw-r--r--src/c/fastcgi.c13
-rw-r--r--src/c/http.c14
-rw-r--r--src/c/request.c40
-rw-r--r--src/c/static.c6
-rw-r--r--src/c/urweb.c117
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;
+}