static int queue_file(int argc, char *argv[], int fidx) { lua_State *T = lem_newthread(); const char *filename; int i; if (fidx < argc) filename = argv[fidx]; else filename = LEM_LDIR "lem/repl.lua"; switch (luaL_loadfile(T, filename)) { case LUA_OK: /* success */ break; case LUA_ERRMEM: oom(); default: lem_log_error("lem: %s", lua_tostring(T, 1)); return -1; } lua_createtable(T, argc, 0); for (i = 0; i < argc; i++) { lua_pushstring(T, argv[i]); lua_rawseti(T, -2, i - fidx); } lua_setglobal(T, "arg"); lem_queue(T, 0); return 0; }
static int setsignal(int signal, void (*handler)(int), int flags) { struct sigaction act; act.sa_handler = handler; sigemptyset(&act.sa_mask); act.sa_flags = flags; if (sigaction(signal, &act, NULL)) { lem_log_error("lem: error setting signal %d: %s", signal, strerror(errno)); return -1; } return 0; }
int main(int argc, char *argv[]) { #if EV_MULTIPLICITY lem_loop = ev_default_loop(LEM_LOOPFLAGS); if (lem_loop == NULL) { #else if (!ev_default_loop(LEM_LOOPFLAGS)) { #endif lem_log_error("lem: error initializing event loop"); return EXIT_FAILURE; } if (setsignal(SIGPIPE, SIG_IGN, 0) #if !EV_CHILD_ENABLE || setsignal(SIGCHLD, SIG_DFL, SA_NOCLDSTOP | SA_NOCLDWAIT) #endif ) goto error; /* create main Lua state */ L = luaL_newstate(); if (L == NULL) { lem_log_error("lem: error initializing Lua state"); goto error; } luaL_openlibs(L); /* push thread table */ lua_newtable(L); /* initialize runqueue */ ev_idle_init(&rq.w, runqueue_pop); ev_idle_start(LEM_ &rq.w); rq.queue = lem_xmalloc(LEM_INITIAL_QUEUESIZE * sizeof(struct lem_runqueue_slot)); rq.first = rq.last = 0; rq.mask = LEM_INITIAL_QUEUESIZE - 1; /* initialize threadpool */ if (pool_init()) { lem_log_error("lem: error initializing threadpool"); goto error; } /* load file */ if (queue_file(argc, argv, 1)) goto error; /* start the mainloop */ ev_loop(LEM_ 0); lem_debug("event loop exited"); /* if there is an error message left on L print it */ if (lua_type(L, -1) == LUA_TSTRING) lem_log_error("lem: %s", lua_tostring(L, -1)); /* shutdown Lua */ lua_close(L); /* free runqueue */ free(rq.queue); /* destroy loop */ #if EV_MULTIPLICITY ev_loop_destroy(lem_loop); #else ev_default_destroy(); #endif lem_debug("Bye %s", exit_status == EXIT_SUCCESS ? "o/" : ":("); return exit_status; error: if (L) lua_close(L); if (rq.queue) free(rq.queue); #if EV_MULTIPLICITY ev_loop_destroy(lem_loop); #else ev_default_destroy(); #endif return EXIT_FAILURE; }
static void runqueue_pop(EV_P_ struct ev_idle *w, int revents) { struct lem_runqueue_slot *slot; lua_State *T; int nargs; (void)revents; if (rq.first == rq.last) { /* queue is empty */ lem_debug("runqueue is empty, collecting.."); #if 0 if (lua_gc(L, LUA_GCSTEP, 0)) { lem_debug("done collecting"); ev_idle_stop(EV_A_ w); } #else ev_idle_stop(EV_A_ w); lua_gc(L, LUA_GCCOLLECT, 0); #endif return; } lem_debug("running thread..."); slot = &rq.queue[rq.first]; T = slot->T; nargs = slot->nargs; rq.first++; rq.first &= rq.mask; /* run Lua thread */ #if LUA_VERSION_NUM >= 502 switch (lua_resume(T, NULL, nargs)) { #else switch (lua_resume(T, nargs)) { #endif case LUA_OK: /* thread finished successfully */ lem_debug("thread finished successfully"); lem_forgetthread(T); return; case LUA_YIELD: /* thread yielded */ lem_debug("thread yielded"); return; case LUA_ERRERR: /* error running error handler */ lem_debug("thread errored while running error handler"); #if LUA_VERSION_NUM >= 502 case LUA_ERRGCMM: lem_debug("error in __gc metamethod"); #endif case LUA_ERRRUN: /* runtime error */ lem_debug("thread errored"); thread_error(T); break; case LUA_ERRMEM: /* out of memory */ oom(); default: /* this shouldn't happen */ lem_debug("lua_resume: unknown error"); lua_pushliteral(L, "unknown error"); break; } lem_exit(EXIT_FAILURE); } #include "pool.c" static int queue_file(int argc, char *argv[], int fidx) { lua_State *T = lem_newthread(); const char *filename; int i; if (fidx < argc) filename = argv[fidx]; else filename = LEM_LDIR "lem/repl.lua"; switch (luaL_loadfile(T, filename)) { case LUA_OK: /* success */ break; case LUA_ERRMEM: oom(); default: lem_log_error("lem: %s", lua_tostring(T, 1)); return -1; } lua_createtable(T, argc, 0); for (i = 0; i < argc; i++) { lua_pushstring(T, argv[i]); lua_rawseti(T, -2, i - fidx); } lua_setglobal(T, "arg"); lem_queue(T, 0); return 0; }