diff --git a/include/lighttpd/config_lua.h b/include/lighttpd/config_lua.h index 86854e7..9f84a95 100644 --- a/include/lighttpd/config_lua.h +++ b/include/lighttpd/config_lua.h @@ -3,6 +3,8 @@ #include -LI_API gboolean li_config_lua_load(liServer *srv, const gchar *filename, liAction **pact); +#include + +LI_API gboolean li_config_lua_load(lua_State *L, liServer *srv, const gchar *filename, liAction **pact, gboolean allow_setup); #endif diff --git a/include/lighttpd/core_lua.h b/include/lighttpd/core_lua.h index ea1bf1b..a583148 100644 --- a/include/lighttpd/core_lua.h +++ b/include/lighttpd/core_lua.h @@ -53,7 +53,7 @@ LI_API int li_lua_push_vrequest(lua_State *L, liVRequest *vr); */ LI_API int li_lua_metatable_index(lua_State *L); -LI_API void li_lua_init(liServer *srv, lua_State *L); +LI_API void li_lua_init(lua_State* L, liServer* srv, liWorker* wrk); LI_API int li_lua_push_traceback(lua_State *L, int narg); diff --git a/include/lighttpd/worker.h b/include/lighttpd/worker.h index 717c990..ce52bbe 100644 --- a/include/lighttpd/worker.h +++ b/include/lighttpd/worker.h @@ -5,6 +5,8 @@ #error Please include instead of this file #endif +struct lua_State; + typedef struct liStatistics liStatistics; struct liStatistics { guint64 bytes_out; /** bytes transfered, outgoing */ @@ -51,6 +53,8 @@ struct liWorker { GThread *thread; /* managed by server.c */ guint ndx; /* worker index */ + struct lua_State *L; /** NULL if compiled without Lua */ + struct ev_loop *loop; ev_prepare loop_prepare; ev_check loop_check; diff --git a/src/main/config_lua.c b/src/main/config_lua.c index 58b6387..78b4860 100644 --- a/src/main/config_lua.c +++ b/src/main/config_lua.c @@ -4,7 +4,7 @@ #include #include -# include +#include #include #include @@ -183,14 +183,14 @@ static int handle_server_setup(liServer *srv, lua_State *L, gpointer _ss) { return 0; } -gboolean li_config_lua_load(liServer *srv, const gchar *filename, liAction **pact) { - lua_State *L = srv->L; +gboolean li_config_lua_load(lua_State *L, liServer *srv, const gchar *filename, liAction **pact, gboolean allow_setup) { int errfunc; int lua_stack_top; + gboolean dolock = (L == srv->L); *pact = NULL; - li_lua_lock(srv); + if (dolock) li_lua_lock(srv); lua_stack_top = lua_gettop(L); @@ -203,8 +203,10 @@ gboolean li_config_lua_load(liServer *srv, const gchar *filename, liAction **pac DEBUG(srv, "Loaded config script '%s'", filename); - publish_str_hash(srv, L, srv->setups, handle_server_setup); - lua_setfield(L, LUA_GLOBALSINDEX, "setup"); + if (allow_setup) { + publish_str_hash(srv, L, srv->setups, handle_server_setup); + lua_setfield(L, LUA_GLOBALSINDEX, "setup"); + } publish_str_hash(srv, L, srv->actions, handle_server_action); lua_setfield(L, LUA_GLOBALSINDEX, "action"); @@ -214,6 +216,16 @@ gboolean li_config_lua_load(liServer *srv, const gchar *filename, liAction **pac errfunc = li_lua_push_traceback(L, 0); if (lua_pcall(L, 0, 1, errfunc)) { ERROR(srv, "lua_pcall(): %s", lua_tostring(L, -1)); + + /* cleanup stack */ + if (lua_stack_top > lua_gettop(L)) { + lua_pop(L, lua_gettop(L) - lua_stack_top); + } + + li_lua_restore_globals(L); + + if (dolock) li_lua_unlock(srv); + return FALSE; } lua_remove(L, errfunc); @@ -239,7 +251,7 @@ gboolean li_config_lua_load(liServer *srv, const gchar *filename, liAction **pac li_lua_restore_globals(L); - li_lua_unlock(srv); + if (dolock) li_lua_unlock(srv); return TRUE; } diff --git a/src/main/config_parser.rl b/src/main/config_parser.rl index d071d4a..c992e43 100644 --- a/src/main/config_parser.rl +++ b/src/main/config_parser.rl @@ -746,7 +746,7 @@ return FALSE; } - if (!li_config_lua_load(srv, val->data.string->str, &a)) { + if (!li_config_lua_load(srv->L, srv, val->data.string->str, &a, TRUE)) { ERROR(srv, "include_lua '%s' failed", val->data.string->str); li_value_free(name); li_value_free(val); diff --git a/src/main/core_lua.c b/src/main/core_lua.c index f54db3a..9228ec7 100644 --- a/src/main/core_lua.c +++ b/src/main/core_lua.c @@ -137,7 +137,7 @@ static void lua_push_constants(lua_State *L, int ndx) { lua_setfield(L, ndx, "HANDLER_ERROR"); } -void li_lua_init(liServer *srv, lua_State *L) { +void li_lua_init(lua_State *L, liServer *srv, liWorker *wrk) { li_lua_init_chunk_mt(L); li_lua_init_connection_mt(L); li_lua_init_environment_mt(L); @@ -151,6 +151,10 @@ void li_lua_init(liServer *srv, lua_State *L) { /* prefer closure, but just in case */ lua_pushlightuserdata(L, srv); lua_setfield(L, LUA_REGISTRYINDEX, "lighty.srv"); + if (NULL != wrk) { + lua_pushlightuserdata(L, wrk); + lua_setfield(L, LUA_REGISTRYINDEX, "lighty.wrk"); + } lua_newtable(L); /* lighty. */ diff --git a/src/main/lighttpd.c b/src/main/lighttpd.c index d51ccb2..de4721f 100644 --- a/src/main/lighttpd.c +++ b/src/main/lighttpd.c @@ -132,7 +132,7 @@ int main(int argc, char *argv[]) { } else { #ifdef HAVE_LUA_H - li_config_lua_load(srv, config_path, &srv->mainaction); + li_config_lua_load(srv->L, srv, config_path, &srv->mainaction, TRUE); /* lua config frontend */ #else g_print("lua config frontend not available\n"); diff --git a/src/main/server.c b/src/main/server.c index bf8e529..46a8280 100644 --- a/src/main/server.c +++ b/src/main/server.c @@ -93,7 +93,7 @@ liServer* li_server_new(const gchar *module_dir) { #ifdef HAVE_LUA_H srv->L = luaL_newstate(); luaL_openlibs(srv->L); - li_lua_init(srv, srv->L); + li_lua_init(srv->L, srv, NULL); srv->lualock = g_mutex_new(); #else diff --git a/src/main/worker.c b/src/main/worker.c index 041ecd5..02af434 100644 --- a/src/main/worker.c +++ b/src/main/worker.c @@ -3,6 +3,12 @@ #include +#ifdef HAVE_LUA_H +# include +# include +# include +#endif + #include static liConnection* worker_con_get(liWorker *wrk); @@ -365,6 +371,14 @@ liWorker* li_worker_new(liServer *srv, struct ev_loop *loop) { wrk->srv = srv; wrk->loop = loop; +#ifdef HAVE_LUA_H + wrk->L = luaL_newstate(); + luaL_openlibs(wrk->L); + li_lua_init(wrk->L, srv, wrk); +#else + wrk->L = NULL; +#endif + g_queue_init(&wrk->keep_alive_queue); ev_init(&wrk->keep_alive_timer, worker_keepalive_cb); wrk->keep_alive_timer.data = wrk; @@ -508,6 +522,11 @@ void li_worker_free(liWorker *wrk) { li_stat_cache_free(wrk->stat_cache); +#ifdef HAVE_LUA_H + lua_close(wrk->L); + wrk->L = NULL; +#endif + g_slice_free(liWorker, wrk); }