--- a/common.c Thu Jun 26 01:32:56 2008 +0300
+++ b/common.c Thu Jun 26 02:57:20 2008 +0300
@@ -8,7 +8,7 @@
#include "common.h"
static void _generic_err_vargs (int use_stderr, const char *func, int perr, const char *fmt, va_list va) {
- FILE *stream = use_stderr ? stderr : stdin;
+ FILE *stream = use_stderr ? stderr : stdout;
if (func)
fprintf(stream, "%s: ", func);
--- a/common.h Thu Jun 26 01:32:56 2008 +0300
+++ b/common.h Thu Jun 26 02:57:20 2008 +0300
@@ -44,7 +44,7 @@
#ifdef DEBUG_ENABLED
#define DEBUG(...) err_func(__func__, __VA_ARGS__)
#else
-#define DEBUG(...) if (0) { }
+#define DEBUG(...) (void) (0)
#endif
// default is to enable INFO
@@ -55,7 +55,7 @@
#if INFO_ENABLED
#define INFO(...) info(__VA_ARGS__)
#else
-#define INFO(...) if (0) { }
+#define INFO(...) (void) (0)
#endif
/*
--- a/node_main.c Thu Jun 26 01:32:56 2008 +0300
+++ b/node_main.c Thu Jun 26 02:57:20 2008 +0300
@@ -31,6 +31,10 @@
perr_exit("sigaction");
}
+void log_null (int severity, const char *msg) {
+ // ignore
+}
+
/*
* State needed to handle a client
*/
@@ -76,9 +80,13 @@
free(ctx);
}
-static void handle_render_done (struct render_thread *thread_info, void *arg) {
+static void handle_render_done (struct render_thread *thread_info, int err, void *arg) {
struct client_info *ctx = arg;
+#if INFO_ENABLED
+ INFO("client [%p]: %s", ctx, err ? "failed" : "done");
+#endif
+
// just free it, it takes care of closing it as well
client_free(ctx);
}
@@ -151,7 +159,7 @@
return;
}
- PWARNING("eventbuffer: %s %s",
+ PWARNING("client [%p]: eventbuffer error: %s %s", ctx,
(what & EVBUFFER_READ) ? "read" : ((what & EVBUFFER_WRITE) ? "write" : "???"),
(what & EVBUFFER_EOF) ? "eof" : ((what & EVBUFFER_ERROR) ? "error" : ((what & EVBUFFER_TIMEOUT) ? "timeout" : "???"))
);
@@ -175,6 +183,13 @@
if ((socket = accept(fd, (struct sockaddr *) &addr, &addr_len)) == -1)
PERROR("accept");
+ // alloc a new client_info
+ if (!(ctx = calloc(1, sizeof(*ctx))))
+ ERROR("calloc");
+
+ // store the socket
+ ctx->socket = socket;
+
#if INFO_ENABLED
assert(INET_ADDRSTRLEN < INET6_ADDRSTRLEN);
@@ -201,17 +216,9 @@
addr_str = addr_buf;
}
- INFO("ACCEPT: %s:%hu\n", addr_str, ntohs(nport));
-
+ INFO("client [%p]: accept from %s:%hu", ctx, addr_str, ntohs(nport));
#endif
- // alloc a new client_info
- if (!(ctx = calloc(1, sizeof(*ctx))))
- ERROR("calloc");
-
- // store the socket
- ctx->socket = socket;
-
// then a bufferevent so that we can read in the command
if (!(ctx->bufev = bufferevent_new(ctx->socket, &handle_read, NULL, &handle_error, ctx)))
ERROR("bufferevent_new");
@@ -224,6 +231,7 @@
bufferevent_setwatermark(ctx->bufev, EV_READ, sizeof(struct render_cmd), 0);
// now we just wait for the cmd...
+ return;
error:
if (ctx)
@@ -240,6 +248,7 @@
// parse arguments
int opt;
const char *port_name = NULL;
+ int enable_debug = 0;
unsigned short port;
while ((opt = getopt(argc, argv, "l:")) != -1) {
@@ -251,11 +260,20 @@
port_name = optarg;
break;
+ case 'd':
+ // enable libevent debugging
+ enable_debug = 1;
+ break;
+
default:
- err_exit("Usage: %s [-l port]", argv[0]);
+ err_exit("Usage: %s [-l port] [-d]", argv[0]);
}
}
+ // init libevent
+ if (!(ev_base = event_init()))
+ FATAL("event_init");
+
// post-process arguments
if (!port_name)
port_name = RENDER_PORT_NAME;
@@ -263,9 +281,9 @@
if (!(port = atoi(port_name)))
ERROR("invalid port: %s", port_name);
- // init libevent
- if (!(ev_base = event_init()))
- FATAL("event_init");
+ // per default it is enabled
+ if (!enable_debug)
+ event_set_log_callback(&log_null);
// create the socket
if ((ssock = socket(PF_INET, SOCK_STREAM, 0)) == -1)
@@ -284,7 +302,7 @@
// create the listen event
struct event listen_ev;
- event_set(&listen_ev, ssock, EV_READ, &handle_accept, NULL);
+ event_set(&listen_ev, ssock, EV_READ | EV_PERSIST, &handle_accept, NULL);
if (event_add(&listen_ev, NULL))
PERROR("event_add");
@@ -293,12 +311,12 @@
sigpipe_ignore();
// run the libevent mainloop
- printf("RUN: %s:%hu\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
+ INFO("run: %s:%hu", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
if (event_base_dispatch(ev_base))
WARNING("event_dispatch");
- printf("SHUTDOWN\n");
+ INFO("SHUTDOWN");
event_base_free(ev_base);
--- a/render_local.c Thu Jun 26 01:32:56 2008 +0300
+++ b/render_local.c Thu Jun 26 02:57:20 2008 +0300
@@ -5,54 +5,61 @@
#include "common.h"
#include "render_struct.h"
#include "render_local.h"
-#include "render_png_struct.h"
#include "render_png.h"
-#include "render_raw_struct.h"
#include "render_raw.h"
#include "render_mandelbrot.h"
int render_local (struct render *render, double *duration) {
- unsigned char *rowbuf = NULL;
- struct render_png png_ctx;
- struct render_raw raw_ctx;
- int must_deinit = 0;
- clock_t t1, t2;
+ struct render_local ctx;
- if (duration)
- *duration = -1;
+ if (render_local_init(&ctx, render))
+ return -1;
+
+ int err = render_local_run(&ctx, duration);
+
+ render_local_deinit(&ctx);
+
+ return err;
+}
+
+int render_local_init (struct render_local *ctx, struct render *render) {
+ // zero
+ memset(ctx, 0, sizeof(*ctx));
+
+ ctx->render_info = render;
// alloc the memory buffer
- if (!(rowbuf = malloc(render->img_w)))
+ if (!(ctx->rowbuf = malloc(render->img_w)))
ERROR("malloc");
// what mode?
switch (render->mode) {
case RENDER_PNG :
// the render_png stuff
- memset(&png_ctx, 0, sizeof(png_ctx));
+ memset(&ctx->png_ctx, 0, sizeof(ctx->png_ctx));
- if (render_png_init(&png_ctx, render))
+ if (render_png_init(&ctx->png_ctx, render))
ERROR("render_png_init");
- must_deinit = RENDER_PNG;
+ ctx->must_deinit = RENDER_PNG;
// set render_* to use the render_png
- if (render_local_mem(render, &rowbuf, (int(*)(void *arg, unsigned char *)) &render_png_row, &png_ctx))
+ if (render_local_mem(render, &ctx->rowbuf, (int(*)(void *arg, unsigned char *)) &render_png_row, &ctx->png_ctx))
ERROR("render_local_mem");
break;
case RENDER_RAW :
// the render_raw stuff
- memset(&raw_ctx, 0, sizeof(raw_ctx));
+ memset(&ctx->raw_ctx, 0, sizeof(ctx->raw_ctx));
- if (render_raw_init(&raw_ctx, render))
+ if (render_raw_init(&ctx->raw_ctx, render))
ERROR("render_raw_init");
- must_deinit = RENDER_RAW;
+ ctx->must_deinit = RENDER_RAW;
// set render_* to use the render_raw
- if (render_local_mem(render, &rowbuf, (int(*)(void *arg, unsigned char *)) &render_raw_row, &raw_ctx))
+ if (render_local_mem(render, &ctx->rowbuf, (int(*)(void *arg, unsigned char *)) &render_raw_row, &ctx->raw_ctx))
ERROR("render_local_mem");
break;
@@ -60,14 +67,33 @@
default :
assert(0);
}
-
+
+ // success
+ return 0;
+
+error:
+ render_local_deinit(ctx);
+
+ return -1;
+}
+
+int render_local_run (struct render_local *ctx, double *duration) {
+ clock_t t1, t2;
+
+ if (duration)
+ *duration = -1;
+
// then we can actually render
t1 = clock();
- if (render_mandelbrot(render))
- ERROR("render_mandelbrot");
+ if (render_mandelbrot(ctx->render_info))
+ goto error;
t2 = clock();
+
+ // flush the PNG
+ if (render_png_done(&ctx->png_ctx))
+ goto error;
// calculate the time taken
if (duration)
@@ -77,14 +103,18 @@
return 0;
error:
- free(rowbuf);
-
- if (must_deinit == RENDER_PNG)
- render_png_deinit(&png_ctx);
-
- else if (must_deinit == RENDER_RAW)
- render_raw_deinit(&raw_ctx);
-
+ // caller must deinit
+ //
return -1;
}
+void render_local_deinit (struct render_local *ctx) {
+ free(ctx->rowbuf);
+
+ if (ctx->must_deinit == RENDER_PNG)
+ render_png_deinit(&ctx->png_ctx);
+
+ else if (ctx->must_deinit == RENDER_RAW)
+ render_raw_deinit(&ctx->raw_ctx);
+}
+
--- a/render_local.h Thu Jun 26 01:32:56 2008 +0300
+++ b/render_local.h Thu Jun 26 02:57:20 2008 +0300
@@ -2,6 +2,16 @@
#define RENDER_LOCAL_H
#include "render.h"
+#include "render_png_struct.h"
+#include "render_raw_struct.h"
+
+struct render_local {
+ struct render *render_info;
+ unsigned char *rowbuf;
+ struct render_png png_ctx;
+ struct render_raw raw_ctx;
+ int must_deinit;
+};
/*
* Renders the given struct render locally in one operation.
@@ -9,7 +19,12 @@
* How this operates depends on the render mode:
* RENDER_PNG - see render_png_init
* RENDER_RAW - see render_raw_init
+ *
+ * Note that the given render MUST remain valid across calls to init/run/deinit
*/
int render_local (struct render *render, double *duration);
+int render_local_init (struct render_local *ctx, struct render *render);
+int render_local_run (struct render_local *ctx, double *duration);
+void render_local_deinit (struct render_local *ctx);
#endif /* RENDER_LOCAL_H */
--- a/render_png.c Thu Jun 26 01:32:56 2008 +0300
+++ b/render_png.c Thu Jun 26 02:57:20 2008 +0300
@@ -154,18 +154,10 @@
}
int render_png_abort (struct render_png *ctx) {
- // libpng error handling
- if (setjmp(png_jmpbuf(ctx->png_ptr)))
- ERROR("libpng");
-
// just free it
_render_png_free(ctx);
// success
return 0;
-
-error:
- free(ctx);
- return -1;
}
--- a/render_thread.c Thu Jun 26 01:32:56 2008 +0300
+++ b/render_thread.c Thu Jun 26 02:57:20 2008 +0300
@@ -18,18 +18,30 @@
// measure how long it takes
double duration;
- // render it...
- if (render_local(&ctx->render_info, &duration))
- goto error;
+ struct render_local local_ctx;
+
+ // initialize it...
+ if (!(ctx->err = render_local_init(&local_ctx, &ctx->render_info))) {
+ // setup the cancel exit handlers
+ pthread_cleanup_push( (void (*)(void *)) render_local_deinit, &local_ctx);
-#ifdef DEBUG_INFO
- u_int32_t img_w, img_h;
+ // render it...
+ ctx->err = render_local_run(&local_ctx, &duration);
+
+ if (!ctx->err) {
+#if INFO_ENABLED
+ u_int32_t img_w, img_h;
- render_get_size(&ctx->render_info, &img_w, &img_h);
+ render_get_size(&ctx->render_info, &img_w, &img_h);
- // report the duration
- INFO("rendered [%ux%u] in %f seconds", img_w, img_h, duration);
+ // report the duration
+ INFO("rendered [%ux%u] in %f seconds", img_w, img_h, duration);
#endif
+ }
+
+ // cleanup
+ pthread_cleanup_pop(1);
+ }
// notify completion, writeall()
ssize_t ret;
@@ -52,6 +64,7 @@
return NULL;
error:
+ // if notifying of completion failed...
return ctx;
}
@@ -59,6 +72,14 @@
struct render_thread *ctx = arg;
void *thread_return;
+ // join the thread and check the return value
+ if (pthread_join(ctx->thread_id, &thread_return))
+ PWARNING("pthread_join");
+ else if (thread_return == PTHREAD_CANCELED)
+ PWARNING("PTHREAD_CANCELED");
+ else if (thread_return != NULL)
+ PWARNING("thread_return != NULL");
+
// make a lazy effort to read the contents of the pipe
struct render_thread *ctx2;
char *buf = (void *) &ctx2;
@@ -82,19 +103,11 @@
if (close(ctx->notify_fd))
PWARNING("close(pipe-write)");
- // join the thread and check the return value
- if (pthread_join(ctx->thread_id, &thread_return))
- PWARNING("pthread_join");
- else if (thread_return == PTHREAD_CANCELED)
- PWARNING("PTHREAD_CANCELED");
- else if (thread_return != NULL)
- PWARNING("thread_return != NULL");
-
// mark it as done
ctx->is_active = 0;
// call our callback
- ctx->cb_func(ctx, ctx->cb_arg);
+ ctx->cb_func(ctx, ctx->err, ctx->cb_arg);
}
int render_thread_init (struct render_thread *ctx, struct render *render_info, render_thread_done_cb cb_func, void *cb_arg) {
--- a/render_thread.h Thu Jun 26 01:32:56 2008 +0300
+++ b/render_thread.h Thu Jun 26 02:57:20 2008 +0300
@@ -10,7 +10,7 @@
struct render_thread;
-typedef void (*render_thread_done_cb)(struct render_thread *ctx, void *arg);
+typedef void (*render_thread_done_cb)(struct render_thread *ctx, int err, void *arg);
struct render_thread *render_thread_alloc (struct render *render, render_thread_done_cb cb_func, void *cb_arg);
--- a/render_thread_struct.h Thu Jun 26 01:32:56 2008 +0300
+++ b/render_thread_struct.h Thu Jun 26 02:57:20 2008 +0300
@@ -26,6 +26,9 @@
// the notification event
struct event ev;
+ // did the render fail?
+ int err;
+
// already canceled/done?
int is_active;
};
--- a/web_main.c Thu Jun 26 01:32:56 2008 +0300
+++ b/web_main.c Thu Jun 26 02:57:20 2008 +0300
@@ -169,14 +169,13 @@
// render context
struct render render;
- if (render_init(&render, RENDER_PNG))
- ERROR("render_alloc");
-
- if (render_set_size(&render, img_w, img_h))
- ERROR("render_set_size");
-
- if (render_region_full(&render))
- ERROR("render_region_full");
+ if (
+ render_init(&render)
+ || render_set_mode(&render, RENDER_PNG)
+ || render_set_size(&render, img_w, img_h)
+ || render_region_full(&render)
+ )
+ ERROR("render_*");
// initiate the remote render operation
if ((ctx->render_info = render_remote(&render, &remote_pool,