summaryrefslogtreecommitdiff
path: root/src/c
diff options
context:
space:
mode:
authorGravatar Adam Chlipala <adamc@hcoop.net>2008-07-29 15:25:42 -0400
committerGravatar Adam Chlipala <adamc@hcoop.net>2008-07-29 15:25:42 -0400
commitcb3b3831a07d6674a5fa02e3e8a1e4329b58cb34 (patch)
tree7b6064344549091735d28d42ac9fb19073e9760a /src/c
parent6855e4766fa8d07e2f3e3cd468de6c58fed0c903 (diff)
Unurlifying a datatype; longjmp-based error signaling mechanism
Diffstat (limited to 'src/c')
-rw-r--r--src/c/driver.c62
-rw-r--r--src/c/lacweb.c51
2 files changed, 105 insertions, 8 deletions
diff --git a/src/c/driver.c b/src/c/driver.c
index 90538104..21001d0c 100644
--- a/src/c/driver.c
+++ b/src/c/driver.c
@@ -13,8 +13,6 @@ int lw_port = 8080;
int lw_backlog = 10;
int lw_bufsize = 1024;
-void lw_handle(lw_context, char*);
-
typedef struct node {
int fd;
struct node *next;
@@ -51,6 +49,8 @@ static int dequeue() {
static pthread_mutex_t queue_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t queue_cond = PTHREAD_COND_INITIALIZER;
+#define MAX_RETRIES 5
+
static void *worker(void *data) {
int me = *(int *)data;
lw_context ctx = lw_init(1024, 1024);
@@ -68,6 +68,7 @@ static void *worker(void *data) {
printf("Handling connection with thread #%d.\n", me);
while (1) {
+ unsigned retries_left = MAX_RETRIES;
int r = recv(sock, back, lw_bufsize - (back - buf), 0);
if (r < 0) {
@@ -138,11 +139,58 @@ static void *worker(void *data) {
printf("Serving URI %s....\n", path);
- lw_write (ctx, "HTTP/1.1 200 OK\r\n");
- lw_write(ctx, "Content-type: text/html\r\n\r\n");
- lw_write(ctx, "<html>");
- lw_handle(ctx, path);
- lw_write(ctx, "</html>");
+ while (1) {
+ failure_kind fk;
+
+ lw_write(ctx, "HTTP/1.1 200 OK\r\n");
+ lw_write(ctx, "Content-type: text/html\r\n\r\n");
+ lw_write(ctx, "<html>");
+
+ fk = lw_begin(ctx, path);
+ if (fk == SUCCESS) {
+ lw_write(ctx, "</html>");
+ break;
+ } else if (fk == BOUNDED_RETRY) {
+ if (retries_left) {
+ printf("Error triggers bounded retry: %s\n", lw_error_message(ctx));
+ --retries_left;
+ }
+ else {
+ printf("Fatal error (out of retries): %s\n", lw_error_message(ctx));
+
+ lw_reset_keep_error_message(ctx);
+ lw_write(ctx, "HTTP/1.1 500 Internal Server Error\n\r");
+ lw_write(ctx, "Content-type: text/plain\r\n\r\n");
+ lw_write(ctx, "Fatal error (out of retries): ");
+ lw_write(ctx, lw_error_message(ctx));
+ lw_write(ctx, "\n");
+ }
+ } else if (fk == UNLIMITED_RETRY)
+ printf("Error triggers unlimited retry: %s\n", lw_error_message(ctx));
+ else if (fk == FATAL) {
+ printf("Fatal error: %s\n", lw_error_message(ctx));
+
+ lw_reset_keep_error_message(ctx);
+ lw_write(ctx, "HTTP/1.1 500 Internal Server Error\n\r");
+ lw_write(ctx, "Content-type: text/plain\r\n\r\n");
+ lw_write(ctx, "Fatal error: ");
+ lw_write(ctx, lw_error_message(ctx));
+ lw_write(ctx, "\n");
+
+ break;
+ } else {
+ printf("Unknown lw_handle return code!\n");
+
+ lw_reset_keep_request(ctx);
+ lw_write(ctx, "HTTP/1.1 500 Internal Server Error\n\r");
+ lw_write(ctx, "Content-type: text/plain\r\n\r\n");
+ lw_write(ctx, "Unknown lw_handle return code!\n");
+
+ break;
+ }
+
+ lw_reset_keep_request(ctx);
+ }
lw_send(ctx, sock);
diff --git a/src/c/lacweb.c b/src/c/lacweb.c
index 9543c642..523071fd 100644
--- a/src/c/lacweb.c
+++ b/src/c/lacweb.c
@@ -3,15 +3,24 @@
#include <string.h>
#include <ctype.h>
#include <assert.h>
+#include <setjmp.h>
+#include <stdarg.h>
#include "types.h"
lw_unit lw_unit_v = {};
+#define ERROR_BUF_LEN 1024
+
struct lw_context {
char *page, *page_front, *page_back;
char *heap, *heap_front, *heap_back;
char **inputs;
+
+ jmp_buf jmp_buf;
+
+ failure_kind failure_kind;
+ char error_message[ERROR_BUF_LEN];
};
extern int lw_inputs_len;
@@ -27,6 +36,9 @@ lw_context lw_init(size_t page_len, size_t heap_len) {
ctx->inputs = calloc(lw_inputs_len, sizeof(char *));
+ ctx->failure_kind = SUCCESS;
+ ctx->error_message[0] = 0;
+
return ctx;
}
@@ -37,12 +49,49 @@ void lw_free(lw_context ctx) {
free(ctx);
}
-void lw_reset(lw_context ctx) {
+void lw_reset_keep_request(lw_context ctx) {
+ ctx->page_front = ctx->page;
+ ctx->heap_front = ctx->heap;
+
+ ctx->failure_kind = SUCCESS;
+ ctx->error_message[0] = 0;
+}
+
+void lw_reset_keep_error_message(lw_context ctx) {
ctx->page_front = ctx->page;
ctx->heap_front = ctx->heap;
+
+ ctx->failure_kind = SUCCESS;
+}
+
+void lw_reset(lw_context ctx) {
+ lw_reset_keep_request(ctx);
memset(ctx->inputs, 0, lw_inputs_len * sizeof(char *));
}
+void lw_handle(lw_context, char *);
+
+failure_kind lw_begin(lw_context ctx, char *path) {
+ if (!setjmp(ctx->jmp_buf))
+ lw_handle(ctx, path);
+
+ return ctx->failure_kind;
+}
+
+void lw_error(lw_context ctx, failure_kind fk, const char *fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+
+ ctx->failure_kind = fk;
+ vsnprintf(ctx->error_message, ERROR_BUF_LEN, fmt, ap);
+
+ longjmp(ctx->jmp_buf, 1);
+}
+
+char *lw_error_message(lw_context ctx) {
+ return ctx->error_message;
+}
+
int lw_input_num(char*);
void lw_set_input(lw_context ctx, char *name, char *value) {