mooa

Lua + lubev + sandboxing
git clone https://code.literati.org/mooa.git
Log | Files | Refs | README | LICENSE

commit eb667788c6800fa49600b3b35773f368ae60064a
parent 0cc710d8ad7a36f59a1457211ccc351b675f4f78
Author: Sean Lynch <seanl@literati.org>
Date:   Mon, 23 Jun 2014 17:45:10 -0700

Get things a little closer to working

Diffstat:
Mdns.c | 5+++--
Mmain.lua | 9+++++----
Mmooa.c | 2++
Mtask.c | 58+++++++++++++++++++++++++++++++++++++++++++++-------------
Mtask.h | 1+
5 files changed, 56 insertions(+), 19 deletions(-)

diff --git a/dns.c b/dns.c @@ -25,14 +25,15 @@ typedef struct mooa_dns_state { -static void mooa_dns_timer_cb(struct ev_loop *loop, ev_timer *timer) { +static void mooa_dns_timer_cb(struct ev_loop *loop, ev_timer *timer, + int revents) { mooa_dns_context_t *context = timer->data; dns_timeouts(context->ctx, -1, (time_t)ev_now(mooa_task_get_loop(context->coro))); } -static void mooa_dns_io_cb(struct ev_loop *loop, ev_io *io) { +static void mooa_dns_io_cb(struct ev_loop *loop, ev_io *io, int revents) { mooa_dns_context_t *context = io->data; dns_ioevent(context->ctx, (time_t)ev_now(loop)); diff --git a/main.lua b/main.lua @@ -26,10 +26,11 @@ function test_connect() utils.dump(s) s:connect("66.181.143.21", 80) s:write("GET / HTTP/1.0\nHost: www.literati.org\n\n") - data = s:read(1024) - print(data) - callbacks = get_http_callbacks() - parser:execute(data, callbacks) + repeat + data = s:read(1024) + callbacks = get_http_callbacks() + parser:execute(data, callbacks) + until data == "" utils.dump(callbacks.get_headers()) end diff --git a/mooa.c b/mooa.c @@ -96,6 +96,8 @@ static lua_State *mooa_state_new() { L = lua_newstate(mooa_alloc, (void *)state); lua_atpanic(L, mooa_panic); + mooa_task_init_state(L); + luaL_requiref(L, "base", luaopen_base, 0); luaL_requiref(L, "package", luaopen_package, 1); mooa_state_makesafe(L); diff --git a/task.c b/task.c @@ -1,4 +1,6 @@ #include <assert.h> +#include <err.h> +#include <stdbool.h> #include <stdlib.h> /* lua */ @@ -22,24 +24,43 @@ typedef struct mooa_task { typedef struct mooa_task_state { - struct ev_loop *loop; mooa_task_t *runnable_tasks; mooa_task_t *last_runnable_task; } mooa_task_state_t; +static int mooa_task_state_finalize(lua_State *L) { + mooa_task_state_t *state = lua_touserdata(L, 1); + return 0; +} + + void mooa_task_init_state(lua_State *L) { + luaL_Reg state_funcs[] = { + {"__gc", mooa_task_state_finalize}, + {NULL, NULL} + }; + + luaL_newmetatable(L, "mooa_task_state"); + luaL_setfuncs(L, state_funcs, 0); + lua_pop(L, 1); + mooa_task_state_t *state = lua_newuserdata(L, sizeof(mooa_task_state_t)); + state->runnable_tasks = NULL; state->last_runnable_task = NULL; + + luaL_setmetatable(L, "mooa_task_state"); lua_setfield(L, LUA_REGISTRYINDEX, "mooa_task_state"); } mooa_task_state_t *mooa_task_get_state(lua_State *L) { mooa_task_state_t *state; + assert(L != NULL); lua_getfield(L, LUA_REGISTRYINDEX, "mooa_task_state"); state = lua_touserdata(L, -1); + assert(state != NULL); lua_pop(L, 1); return state; } @@ -60,6 +81,7 @@ struct ev_loop *mooa_task_get_loop(lua_State *L) { struct ev_loop *loop; lua_getfield(L, LUA_REGISTRYINDEX, "mooa_task_loop"); loop = lua_touserdata(L, -1); + assert(loop != NULL); lua_pop(L, 1); return loop; } @@ -103,38 +125,40 @@ void mooa_task_wait_for_write(lua_State *L, int fd) { /* Delete the task from the registry so it gets garbage collected. */ static void mooa_task_delete(mooa_task_t *task) { + warnx("Deleting task %p", task); lua_pushnil(task->coro); lua_rawsetp(task->coro, LUA_REGISTRYINDEX, task->coro); + task->coro = NULL; } -static void mooa_task_step(mooa_task_t *task) { +static bool mooa_task_step(mooa_task_t *task) { + assert(task->coro != NULL); int result = lua_resume(task->coro, NULL, task->nargs); switch (result) { case LUA_OK: /* Task completed. */ - mooa_task_delete(task); - break; + return false; case LUA_YIELD: lua_settop(task->coro, 0); - break; + return true; case LUA_ERRRUN: /* TODO: do something with the error */ fprintf(stderr, "Runtime error\n"); lua_error(task->coro); - break; + return false; case LUA_ERRMEM: fprintf(stderr, "Memory error\n"); lua_error(task->coro); - break; + return false; case LUA_ERRERR: fprintf(stderr, "Error running message handler\n"); lua_error(task->coro); - break; + return false; case LUA_ERRGCMM: fprintf(stderr, "Error running GC metamethod\n"); lua_error(task->coro); - break; + return false; default: fprintf(stderr, "Unknown error\n"); abort(); @@ -180,13 +204,20 @@ static mooa_task_t *mooa_task_new(lua_State *L) { void mooa_task_loop(lua_State *L) { mooa_task_state_t *state = mooa_task_get_state(L); - mooa_task_t *task; + struct ev_loop *loop = mooa_task_get_loop(L); + mooa_task_t *task, **next; bool running; do { - running = ev_run(state->loop, state->runnable_tasks ? EVRUN_NOWAIT : 0); - for (task = state->runnable_tasks; task != NULL; task = task->next) { - mooa_task_step(task); + running = ev_run(loop, state->runnable_tasks ? EVRUN_NOWAIT : 0); + next = &state->runnable_tasks; + while ((task = *next) != NULL) { + if (mooa_task_step(task)) { + next = &task->next; + } else { + *next = task->next; + mooa_task_delete(task); + } } } while (running || state->runnable_tasks); } @@ -226,6 +257,7 @@ static int mooa_task_sleep(lua_State *L) { luaL_checknumber(L, 1); secs = lua_tonumber(L, 1); task = mooa_task_get(L); + warnx("Sleeping task %p for %g seconds", task, secs); ev_timer_set(&task->timer, secs, 0.0); ev_timer_start(mooa_task_get_loop(L), &task->timer); return lua_yield(L, 0); diff --git a/task.h b/task.h @@ -5,6 +5,7 @@ struct ev_loop; +extern void mooa_task_init_state(lua_State *L); extern struct ev_loop *mooa_task_get_loop(lua_State *L); extern void mooa_task_loop(lua_State *L); extern int mooa_task_open(lua_State *L);