[lua] add per lua_State lock
This commit is contained in:
parent
c1851a6cea
commit
0d85a068c8
|
@ -24,12 +24,12 @@ local basepath = filename:gsub("(.*/)(.*)", "%1")
|
|||
-- the basic CGI protocol)
|
||||
--
|
||||
-- Usage:
|
||||
-- core.wsgi ( <url-prefix>, ${ <backend-actions>; } );
|
||||
-- core.wsgi ( <url-prefix>, { <backend-actions>; } );
|
||||
--
|
||||
-- Example: Trac in "/trac", listening via FastCGI on unix:/tmp/trac.socket
|
||||
-- You oviously have to load mod_fastcgi for this.
|
||||
--
|
||||
-- core.wsgi ( "/trac", ${ fastcgi "unix:/tmp/trac.socket"; } );
|
||||
-- core.wsgi ( "/trac", { fastcgi "unix:/tmp/trac.socket"; } );
|
||||
|
||||
local function wsgi(uri_prefix, act)
|
||||
if type(uri_prefix) ~= "string" then
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include <lighttpd/waitqueue.h>
|
||||
#include <lighttpd/radix.h>
|
||||
|
||||
#include <lighttpd/base_lua.h>
|
||||
#include <lighttpd/log.h>
|
||||
#include <lighttpd/server.h>
|
||||
#include <lighttpd/worker.h>
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef _LIGHTTPD_BASE_LUA_H_
|
||||
#define _LIGHTTPD_BASE_LUA_H_
|
||||
|
||||
#ifndef _LIGHTTPD_BASE_H_
|
||||
#error Please include <lighttpd/base.h> instead of this file
|
||||
#endif
|
||||
|
||||
/* this file defines lighttpd <-> lua glue which is always active, even if compiled without lua */
|
||||
|
||||
struct lua_State;
|
||||
|
||||
struct liLuaState {
|
||||
struct lua_State* L; /** NULL if compiled without Lua */
|
||||
GStaticRecMutex lualock;
|
||||
};
|
||||
|
||||
LI_API void li_lua_init(liLuaState* LL, liServer* srv, liWorker* wrk);
|
||||
LI_API void li_lua_clear(liLuaState* LL);
|
||||
|
||||
#endif
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
#include <lualib.h>
|
||||
|
||||
LI_API gboolean li_config_lua_load(lua_State *L, liServer *srv, liWorker *wrk, const gchar *filename, liAction **pact, gboolean allow_setup, liValue *args);
|
||||
LI_API gboolean li_config_lua_load(liLuaState *LL, liServer *srv, liWorker *wrk, const gchar *filename, liAction **pact, gboolean allow_setup, liValue *args);
|
||||
|
||||
LI_API gboolean li_lua_config_publish_str_hash(liServer *srv, liWorker *wrk, lua_State *L, GHashTable *ht, int (*wrapper)(liServer *srv, liWorker *wrk, lua_State *L, gpointer data));
|
||||
LI_API int li_lua_config_handle_server_action(liServer *srv, liWorker *wrk, lua_State *L, gpointer _sa);
|
||||
|
|
|
@ -4,8 +4,15 @@
|
|||
#include <lighttpd/base.h>
|
||||
#include <lua.h>
|
||||
|
||||
#define li_lua_lock(srv) g_static_rec_mutex_lock(&(srv)->lualock);
|
||||
#define li_lua_unlock(srv) g_static_rec_mutex_unlock(&(srv)->lualock);
|
||||
#define LI_LUA_REGISTRY_STATE "lighttpd.state"
|
||||
#define LI_LUA_REGISTRY_SERVER "lighttpd.server"
|
||||
#define LI_LUA_REGISTRY_WORKER "lighttpd.worker"
|
||||
#define LI_LUA_REGISTRY_GLOBALS "lighttpd.globals"
|
||||
|
||||
LI_API liLuaState *li_lua_state_get(lua_State *L);
|
||||
|
||||
INLINE void li_lua_lock(liLuaState *LL);
|
||||
INLINE void li_lua_unlock(liLuaState *LL);
|
||||
|
||||
LI_API void li_lua_init_chunk_mt(lua_State *L);
|
||||
LI_API liChunk* li_lua_get_chunk(lua_State *L, int ndx);
|
||||
|
@ -69,7 +76,7 @@ LI_API int li_lua_fixindex(lua_State *L, int ndx);
|
|||
*/
|
||||
LI_API int li_lua_metatable_index(lua_State *L);
|
||||
|
||||
LI_API void li_lua_init(lua_State* L, liServer* srv, liWorker* wrk);
|
||||
LI_API void li_lua_init2(liLuaState* LL, liServer* srv, liWorker* wrk);
|
||||
|
||||
LI_API int li_lua_push_traceback(lua_State *L, int nargs);
|
||||
|
||||
|
@ -100,4 +107,18 @@ LI_API int li_lua_ghashtable_gstring_pairs(lua_State *L, GHashTable *ht);
|
|||
/* internal: subrequests (vrequest metamethod) */
|
||||
LI_API int li_lua_vrequest_subrequest(lua_State *L);
|
||||
|
||||
|
||||
/* inline implementations */
|
||||
|
||||
INLINE void li_lua_lock(liLuaState *LL) {
|
||||
gboolean b;
|
||||
g_static_rec_mutex_lock(&LL->lualock);
|
||||
b = lua_checkstack(LL->L, LUA_MINSTACK);
|
||||
assert(b);
|
||||
}
|
||||
|
||||
INLINE void li_lua_unlock(liLuaState *LL) {
|
||||
g_static_rec_mutex_unlock(&LL->lualock);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -24,8 +24,7 @@ typedef void (*liPluginHandleCloseCB) (liConnection *con, liPlugin *p);
|
|||
typedef liHandlerResult(*liPluginHandleVRequestCB)(liVRequest *vr, liPlugin *p);
|
||||
typedef void (*liPluginHandleVRCloseCB) (liVRequest *vr, liPlugin *p);
|
||||
|
||||
struct lua_State;
|
||||
typedef void (*liPluginInitLua)(struct lua_State *L, liServer *srv, liWorker *wrk, liPlugin *p);
|
||||
typedef void (*liPluginInitLua)(liLuaState *LL, liServer *srv, liWorker *wrk, liPlugin *p);
|
||||
|
||||
|
||||
struct liPlugin {
|
||||
|
@ -195,7 +194,7 @@ LI_API gboolean li_call_setup(liServer *srv, const char *name, liValue *val);
|
|||
/** free val after call */
|
||||
LI_API gboolean li_plugin_set_default_option(liServer *srv, const gchar* name, liValue *val);
|
||||
|
||||
LI_API void li_plugins_init_lua(struct lua_State *L, liServer *srv, liWorker *wrk);
|
||||
LI_API void li_plugins_init_lua(liLuaState *LL, liServer *srv, liWorker *wrk);
|
||||
|
||||
extern liOptionPtrValue li_option_ptr_zero;
|
||||
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
#error Please include <lighttpd/base.h> instead of this file
|
||||
#endif
|
||||
|
||||
struct lua_State;
|
||||
|
||||
#ifndef LIGHTTPD_SERVER_MAGIC
|
||||
# define LIGHTTPD_SERVER_MAGIC ((guint)0x12AB34CD)
|
||||
#endif
|
||||
|
@ -66,8 +64,7 @@ struct liServer {
|
|||
liServerState state_wait_for;
|
||||
ev_async state_ready_watcher;
|
||||
|
||||
GStaticRecMutex lualock;
|
||||
struct lua_State *L; /** NULL if compiled without Lua */
|
||||
liLuaState LL;
|
||||
|
||||
liWorker *main_worker;
|
||||
guint worker_count;
|
||||
|
|
|
@ -46,6 +46,10 @@ typedef enum {
|
|||
LI_BACKEND_DEAD
|
||||
} liBackendError;
|
||||
|
||||
/* base_lua.h */
|
||||
|
||||
typedef struct liLuaState liLuaState;
|
||||
|
||||
/* chunk.h */
|
||||
|
||||
typedef struct liChunkFile liChunkFile;
|
||||
|
|
|
@ -64,7 +64,7 @@ struct liWorker {
|
|||
GThread *thread; /* managed by server.c */
|
||||
guint ndx; /* worker index */
|
||||
|
||||
struct lua_State *L; /** NULL if compiled without Lua */
|
||||
liLuaState LL;
|
||||
|
||||
struct ev_loop *loop;
|
||||
ev_prepare loop_prepare;
|
||||
|
|
|
@ -204,6 +204,7 @@ SET(LIGHTTPD_SHARED_SRC
|
|||
angel.c
|
||||
angel_fake.c
|
||||
actions.c
|
||||
base_lua.c
|
||||
chunk.c
|
||||
chunk_parser.c
|
||||
collect.c
|
||||
|
|
|
@ -8,6 +8,7 @@ lighttpd_shared_src= \
|
|||
angel.c \
|
||||
angel_fake.c \
|
||||
actions.c \
|
||||
base_lua.c \
|
||||
chunk.c \
|
||||
chunk_parser.c \
|
||||
collect.c \
|
||||
|
|
|
@ -22,11 +22,16 @@ liAction* li_lua_get_action(lua_State *L, int ndx) {
|
|||
|
||||
static int lua_action_gc(lua_State *L) {
|
||||
liServer *srv;
|
||||
liLuaState *LL = li_lua_state_get(L);
|
||||
liAction **a = (liAction**) luaL_checkudata(L, 1, LUA_ACTION);
|
||||
if (!a || !*a) return 0;
|
||||
|
||||
srv = (liServer*) lua_touserdata(L, lua_upvalueindex(1));
|
||||
|
||||
li_lua_unlock(LL);
|
||||
li_action_release(srv, *a);
|
||||
li_lua_lock(LL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -49,7 +54,7 @@ int li_lua_push_action(liServer *srv, lua_State *L, liAction *a) {
|
|||
typedef struct lua_action_param lua_action_param;
|
||||
struct lua_action_param {
|
||||
int func_ref;
|
||||
lua_State *L;
|
||||
liLuaState *LL;
|
||||
};
|
||||
|
||||
typedef struct lua_action_ctx lua_action_ctx;
|
||||
|
@ -61,12 +66,11 @@ static liHandlerResult lua_action_func(liVRequest *vr, gpointer param, gpointer
|
|||
lua_action_param *par = param;
|
||||
lua_action_ctx *ctx = *context;
|
||||
liServer *srv = vr->wrk->srv;
|
||||
lua_State *L = par->L;
|
||||
gboolean dolock = (L == srv->L);
|
||||
lua_State *L = par->LL->L;
|
||||
liHandlerResult res = LI_HANDLER_GO_ON;
|
||||
int errfunc;
|
||||
|
||||
if (dolock) li_lua_lock(srv);
|
||||
li_lua_lock(par->LL);
|
||||
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, par->func_ref);
|
||||
lua_pushvalue(L, -1);
|
||||
|
@ -113,7 +117,7 @@ static liHandlerResult lua_action_func(liVRequest *vr, gpointer param, gpointer
|
|||
lua_setfield(L, -2, "_G");
|
||||
lua_pop(L, 2);
|
||||
|
||||
if (dolock) li_lua_unlock(srv);
|
||||
li_lua_unlock(par->LL);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -121,13 +125,12 @@ static liHandlerResult lua_action_func(liVRequest *vr, gpointer param, gpointer
|
|||
static liHandlerResult lua_action_cleanup(liVRequest *vr, gpointer param, gpointer context) {
|
||||
lua_action_param *par = param;
|
||||
lua_action_ctx *ctx = context;
|
||||
liServer *srv = vr->wrk->srv;
|
||||
lua_State *L = par->L;
|
||||
gboolean dolock = (L == srv->L);
|
||||
lua_State *L = par->LL->L;
|
||||
UNUSED(vr);
|
||||
|
||||
if (dolock) li_lua_lock(srv);
|
||||
li_lua_lock(par->LL);
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, ctx->g_ref);
|
||||
if (dolock) li_lua_unlock(srv);
|
||||
li_lua_unlock(par->LL);
|
||||
|
||||
g_slice_free(lua_action_ctx, ctx);
|
||||
|
||||
|
@ -137,16 +140,16 @@ static liHandlerResult lua_action_cleanup(liVRequest *vr, gpointer param, gpoint
|
|||
static void lua_action_free(liServer *srv, gpointer param) {
|
||||
lua_action_param *par = param;
|
||||
lua_State *L;
|
||||
gboolean dolock;
|
||||
UNUSED(srv);
|
||||
|
||||
if (!param) return;
|
||||
|
||||
L = par->L;
|
||||
dolock = (L == srv->L);
|
||||
L = par->LL->L;
|
||||
|
||||
if (dolock) li_lua_lock(srv);
|
||||
li_lua_lock(par->LL);
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, par->func_ref);
|
||||
if (dolock) li_lua_unlock(srv);
|
||||
lua_gc(L, LUA_GCCOLLECT, 0);
|
||||
li_lua_unlock(par->LL);
|
||||
|
||||
g_slice_free(lua_action_param, par);
|
||||
}
|
||||
|
@ -155,20 +158,20 @@ liAction* li_lua_make_action(lua_State *L, int ndx) {
|
|||
lua_action_param *par = g_slice_new0(lua_action_param);
|
||||
liWorker *wrk;
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "lighty.wrk");
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, LI_LUA_REGISTRY_WORKER);
|
||||
wrk = lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_pushvalue(L, ndx); /* +1 */
|
||||
par->func_ref = luaL_ref(L, LUA_REGISTRYINDEX); /* -1 */
|
||||
par->L = L;
|
||||
par->LL = li_lua_state_get(L);
|
||||
|
||||
/* new environment for function */
|
||||
lua_pushvalue(L, ndx); /* +1 */
|
||||
lua_newtable(L); /* +1 */
|
||||
/* new mt */
|
||||
lua_newtable(L); /* +1 */
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "li_globals"); /* +1 */
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, LI_LUA_REGISTRY_GLOBALS); /* +1 */
|
||||
lua_setfield(L, -2, "__index"); /* -1 */
|
||||
lua_setmetatable(L, -2); /* -1 */
|
||||
if (NULL != wrk) {
|
||||
|
|
|
@ -142,18 +142,18 @@ int li_lua_config_handle_server_action(liServer *srv, liWorker *wrk, lua_State *
|
|||
liServerAction *sa = (liServerAction*) _sa;
|
||||
liValue *val;
|
||||
liAction *a;
|
||||
gboolean dolock = (L == srv->L);
|
||||
liLuaState *LL = li_lua_state_get(L);
|
||||
|
||||
lua_checkstack(L, 16);
|
||||
val = lua_params_to_value(srv, L);
|
||||
|
||||
if (dolock) li_lua_unlock(srv);
|
||||
li_lua_unlock(LL);
|
||||
|
||||
/* TRACE(srv, "%s", "Creating action"); */
|
||||
a = sa->create_action(srv, wrk, sa->p, val, sa->userdata);
|
||||
li_value_free(val);
|
||||
|
||||
if (dolock) li_lua_lock(srv);
|
||||
li_lua_lock(LL);
|
||||
|
||||
if (NULL == a) {
|
||||
lua_pushstring(L, "creating action failed");
|
||||
|
@ -167,16 +167,16 @@ int li_lua_config_handle_server_setup(liServer *srv, liWorker *wrk, lua_State *L
|
|||
liServerSetup *ss = (liServerSetup*) _ss;
|
||||
liValue *val;
|
||||
gboolean res;
|
||||
gboolean dolock = (L == srv->L);
|
||||
liLuaState *LL = li_lua_state_get(L);
|
||||
UNUSED(wrk);
|
||||
|
||||
lua_checkstack(L, 16);
|
||||
val = lua_params_to_value(srv, L);
|
||||
|
||||
if (dolock) li_lua_unlock(srv);
|
||||
li_lua_unlock(LL);
|
||||
/* TRACE(srv, "%s", "Calling setup"); */
|
||||
res = ss->setup(srv, ss->p, val, ss->userdata);
|
||||
if (dolock) li_lua_lock(srv);
|
||||
li_lua_lock(LL);
|
||||
|
||||
if (!res) {
|
||||
li_value_free(val);
|
||||
|
@ -188,14 +188,14 @@ int li_lua_config_handle_server_setup(liServer *srv, liWorker *wrk, lua_State *L
|
|||
return 0;
|
||||
}
|
||||
|
||||
gboolean li_config_lua_load(lua_State *L, liServer *srv, liWorker *wrk, const gchar *filename, liAction **pact, gboolean allow_setup, liValue *args) {
|
||||
gboolean li_config_lua_load(liLuaState *LL, liServer *srv, liWorker *wrk, const gchar *filename, liAction **pact, gboolean allow_setup, liValue *args) {
|
||||
int errfunc;
|
||||
int lua_stack_top;
|
||||
gboolean dolock = (L == srv->L);
|
||||
lua_State *L = LL->L;
|
||||
|
||||
*pact = NULL;
|
||||
|
||||
if (dolock) li_lua_lock(srv);
|
||||
li_lua_lock(LL);
|
||||
|
||||
lua_stack_top = lua_gettop(L);
|
||||
|
||||
|
@ -235,7 +235,7 @@ gboolean li_config_lua_load(lua_State *L, liServer *srv, liWorker *wrk, const gc
|
|||
|
||||
li_lua_restore_globals(L);
|
||||
|
||||
if (dolock) li_lua_unlock(srv);
|
||||
li_lua_unlock(LL);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -251,7 +251,7 @@ gboolean li_config_lua_load(lua_State *L, liServer *srv, liWorker *wrk, const gc
|
|||
|
||||
lua_gc(L, LUA_GCCOLLECT, 0);
|
||||
|
||||
if (dolock) li_lua_unlock(srv);
|
||||
li_lua_unlock(LL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -623,7 +623,7 @@ static gboolean config_parser_include(liServer *srv, GList *ctx_stack, gchar *pa
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (!li_config_lua_load(srv->L, srv, srv->main_worker, val->data.string->str, &a, TRUE, NULL)) {
|
||||
if (!li_config_lua_load(&srv->LL, srv, srv->main_worker, val->data.string->str, &a, TRUE, NULL)) {
|
||||
ERROR(srv, "include_lua '%s' failed", val->data.string->str);
|
||||
li_value_free(val);
|
||||
return FALSE;
|
||||
|
|
|
@ -4,6 +4,18 @@
|
|||
#include <lualib.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
liLuaState *li_lua_state_get(lua_State *L) {
|
||||
liLuaState *LL;
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, LI_LUA_REGISTRY_STATE); /* +1 */
|
||||
LL = lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
assert(LL != NULL && LL->L == L);
|
||||
|
||||
return LL;
|
||||
}
|
||||
|
||||
/* replace a negative stack index with a positive one,
|
||||
* so that you don't need to care about push/pop
|
||||
*/
|
||||
|
@ -87,7 +99,7 @@ int li_lua_metatable_index(lua_State *L) {
|
|||
static void li_lua_store_globals(lua_State *L) {
|
||||
/* backup global table reference */
|
||||
lua_pushvalue(L, LUA_GLOBALSINDEX); /* +1 */
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, "li_globals"); /* -1 */
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, LI_LUA_REGISTRY_GLOBALS); /* -1 */
|
||||
}
|
||||
|
||||
GString* li_lua_print_get_string(lua_State *L, int from, int to) {
|
||||
|
@ -245,7 +257,9 @@ static void lua_push_constants(lua_State *L, int ndx) {
|
|||
lua_setfield(L, ndx, "HANDLER_ERROR");
|
||||
}
|
||||
|
||||
void li_lua_init(lua_State *L, liServer *srv, liWorker *wrk) {
|
||||
void li_lua_init2(liLuaState *LL, liServer *srv, liWorker *wrk) {
|
||||
lua_State *L = LL->L;
|
||||
|
||||
li_lua_init_chunk_mt(L);
|
||||
li_lua_init_coninfo_mt(L);
|
||||
li_lua_init_environment_mt(L);
|
||||
|
@ -259,10 +273,10 @@ void li_lua_init(lua_State *L, liServer *srv, liWorker *wrk) {
|
|||
|
||||
/* prefer closure, but just in case */
|
||||
lua_pushlightuserdata(L, srv);
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, "lighty.srv");
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, LI_LUA_REGISTRY_SERVER);
|
||||
if (NULL != wrk) {
|
||||
lua_pushlightuserdata(L, wrk);
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, "lighty.wrk");
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, LI_LUA_REGISTRY_WORKER);
|
||||
}
|
||||
|
||||
lua_newtable(L); /* lighty. */
|
||||
|
@ -306,11 +320,11 @@ void li_lua_init(lua_State *L, liServer *srv, liWorker *wrk) {
|
|||
|
||||
li_lua_store_globals(L);
|
||||
|
||||
li_plugins_init_lua(L, srv, wrk);
|
||||
li_plugins_init_lua(LL, srv, wrk);
|
||||
}
|
||||
|
||||
void li_lua_restore_globals(lua_State *L) {
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "li_globals"); /* +1 */
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, LI_LUA_REGISTRY_GLOBALS); /* +1 */
|
||||
lua_replace(L, LUA_GLOBALSINDEX); /* -1 */
|
||||
}
|
||||
|
||||
|
|
|
@ -152,23 +152,22 @@ int li_lua_push_filter(lua_State *L, liFilter *f) {
|
|||
|
||||
typedef struct filter_lua_config filter_lua_config;
|
||||
struct filter_lua_config {
|
||||
lua_State *L;
|
||||
liLuaState *LL;
|
||||
int class_ref;
|
||||
};
|
||||
|
||||
typedef struct filter_lua_state filter_lua_state;
|
||||
struct filter_lua_state {
|
||||
lua_State *L;
|
||||
liLuaState *LL;
|
||||
int object_ref;
|
||||
};
|
||||
|
||||
static filter_lua_state* filter_lua_state_new(liVRequest *vr, filter_lua_config *config) {
|
||||
int object_ref = LUA_NOREF;
|
||||
liServer *srv = vr->wrk->srv;
|
||||
lua_State *L = config->L;
|
||||
gboolean dolock = (L == srv->L);
|
||||
lua_State *L = config->LL->L;
|
||||
|
||||
if (dolock) li_lua_lock(srv);
|
||||
li_lua_lock(config->LL);
|
||||
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, config->class_ref); /* +1 */
|
||||
li_lua_push_vrequest(L, vr); /* +1 */
|
||||
|
@ -184,11 +183,11 @@ static filter_lua_state* filter_lua_state_new(liVRequest *vr, filter_lua_config
|
|||
li_vrequest_error(vr);
|
||||
}
|
||||
|
||||
if (dolock) li_lua_unlock(srv);
|
||||
li_lua_unlock(config->LL);
|
||||
|
||||
if (LUA_NOREF != object_ref) {
|
||||
filter_lua_state *state = g_slice_new0(filter_lua_state);
|
||||
state->L = L;
|
||||
state->LL = config->LL;
|
||||
state->object_ref = object_ref;
|
||||
|
||||
return state;
|
||||
|
@ -199,10 +198,9 @@ static filter_lua_state* filter_lua_state_new(liVRequest *vr, filter_lua_config
|
|||
|
||||
static void filter_lua_state_free(liVRequest *vr, filter_lua_state *state) {
|
||||
liServer *srv = vr->wrk->srv;
|
||||
lua_State *L = state->L;
|
||||
gboolean dolock = (L == srv->L);
|
||||
lua_State *L = state->LL->L;
|
||||
|
||||
if (dolock) li_lua_lock(srv);
|
||||
li_lua_lock(state->LL);
|
||||
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, state->object_ref); /* +1 */
|
||||
li_lua_push_vrequest(L, vr); /* +1 */
|
||||
|
@ -210,7 +208,7 @@ static void filter_lua_state_free(liVRequest *vr, filter_lua_state *state) {
|
|||
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, state->object_ref);
|
||||
|
||||
if (dolock) li_lua_unlock(srv);
|
||||
li_lua_unlock(state->LL);
|
||||
|
||||
g_slice_free(filter_lua_state, state);
|
||||
}
|
||||
|
@ -223,12 +221,10 @@ static void filter_lua_free(liVRequest *vr, liFilter *f) {
|
|||
|
||||
static liHandlerResult filter_lua_handle(liVRequest *vr, liFilter *f) {
|
||||
filter_lua_state *state = (filter_lua_state*) f->param;
|
||||
liServer *srv = vr->wrk->srv;
|
||||
lua_State *L = state->L;
|
||||
gboolean dolock = (L == srv->L);
|
||||
lua_State *L = state->LL->L;
|
||||
liHandlerResult res;
|
||||
|
||||
if (dolock) li_lua_lock(srv);
|
||||
li_lua_lock(state->LL);
|
||||
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, state->object_ref); /* +1 */
|
||||
li_lua_push_vrequest(L, vr); /* +1 */
|
||||
|
@ -255,7 +251,7 @@ static liHandlerResult filter_lua_handle(liVRequest *vr, liFilter *f) {
|
|||
res = LI_HANDLER_ERROR;
|
||||
}
|
||||
|
||||
if (dolock) li_lua_unlock(srv);
|
||||
li_lua_unlock(state->LL);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -286,17 +282,18 @@ static liHandlerResult filter_lua_out(liVRequest *vr, gpointer param, gpointer *
|
|||
|
||||
static void filter_lua_action_free(liServer *srv, gpointer param) {
|
||||
filter_lua_config *config = param;
|
||||
lua_State *L = config->L;
|
||||
gboolean dolock = (L == srv->L);
|
||||
lua_State *L = config->LL->L;
|
||||
UNUSED(srv);
|
||||
|
||||
if (dolock) li_lua_lock(srv);
|
||||
li_lua_lock(config->LL);
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, config->class_ref);
|
||||
if (dolock) li_lua_unlock(srv);
|
||||
li_lua_unlock(config->LL);
|
||||
|
||||
g_slice_free(filter_lua_config, config);
|
||||
}
|
||||
|
||||
static int filter_lua_action_create(lua_State *L, liActionFuncCB act_cb) {
|
||||
liLuaState *LL = li_lua_state_get(L);
|
||||
liServer *srv = lua_touserdata(L, lua_upvalueindex(1));
|
||||
liAction *act;
|
||||
filter_lua_config *config;
|
||||
|
@ -310,7 +307,7 @@ static int filter_lua_action_create(lua_State *L, liActionFuncCB act_cb) {
|
|||
}
|
||||
|
||||
config = g_slice_new0(filter_lua_config);
|
||||
config->L = L;
|
||||
config->LL = LL;
|
||||
config->class_ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
|
||||
act = li_action_new_function(act_cb, NULL, filter_lua_action_free, config);
|
||||
|
@ -337,11 +334,12 @@ void li_lua_init_filters(lua_State *L, liServer* srv) {
|
|||
|
||||
liFilter* li_lua_vrequest_add_filter_in(lua_State *L, liVRequest *vr, int state_ndx) {
|
||||
filter_lua_state *state;
|
||||
liLuaState *LL = li_lua_state_get(L);
|
||||
|
||||
lua_pushvalue(L, state_ndx);
|
||||
|
||||
state = g_slice_new0(filter_lua_state);
|
||||
state->L = L;
|
||||
state->LL = LL;
|
||||
state->object_ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
|
||||
return li_vrequest_add_filter_in(vr, filter_lua_handle, filter_lua_free, state);
|
||||
|
@ -349,11 +347,12 @@ liFilter* li_lua_vrequest_add_filter_in(lua_State *L, liVRequest *vr, int state_
|
|||
|
||||
liFilter* li_lua_vrequest_add_filter_out(lua_State *L, liVRequest *vr, int state_ndx) {
|
||||
filter_lua_state *state;
|
||||
liLuaState *LL = li_lua_state_get(L);
|
||||
|
||||
lua_pushvalue(L, state_ndx);
|
||||
|
||||
state = g_slice_new0(filter_lua_state);
|
||||
state->L = L;
|
||||
state->LL = LL;
|
||||
state->object_ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
|
||||
return li_vrequest_add_filter_out(vr, filter_lua_handle, filter_lua_free, state);
|
||||
|
|
|
@ -115,7 +115,7 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
else {
|
||||
#ifdef HAVE_LUA_H
|
||||
li_config_lua_load(srv->L, srv, srv->main_worker, config_path, &srv->mainaction, TRUE, NULL);
|
||||
li_config_lua_load(&srv->LL, srv, srv->main_worker, config_path, &srv->mainaction, TRUE, NULL);
|
||||
/* lua config frontend */
|
||||
#else
|
||||
g_print("lua config frontend not available\n");
|
||||
|
|
|
@ -688,7 +688,7 @@ void li_plugins_stop_log(liServer *srv) { /* "suspend now" */
|
|||
}
|
||||
}
|
||||
|
||||
void li_plugins_init_lua(struct lua_State *L, liServer *srv, liWorker *wrk) {
|
||||
void li_plugins_init_lua(liLuaState *LL, liServer *srv, liWorker *wrk) {
|
||||
GHashTableIter iter;
|
||||
liPlugin *p;
|
||||
gpointer v;
|
||||
|
@ -699,7 +699,7 @@ void li_plugins_init_lua(struct lua_State *L, liServer *srv, liWorker *wrk) {
|
|||
while (g_hash_table_iter_next(&iter, NULL, &v)) {
|
||||
p = (liPlugin*) v;
|
||||
if (p->handle_init_lua) {
|
||||
p->handle_init_lua(L, srv, wrk, p);
|
||||
p->handle_init_lua(LL, srv, wrk, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,12 +2,6 @@
|
|||
#include <lighttpd/base.h>
|
||||
#include <lighttpd/plugin_core.h>
|
||||
|
||||
#ifdef HAVE_LUA_H
|
||||
# include <lighttpd/core_lua.h>
|
||||
# include <lualib.h>
|
||||
# include <lauxlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
# include <sys/resource.h>
|
||||
#endif
|
||||
|
@ -105,15 +99,7 @@ liServer* li_server_new(const gchar *module_dir, gboolean module_resident) {
|
|||
ev_init(&srv->state_ready_watcher, state_ready_cb);
|
||||
srv->state_ready_watcher.data = srv;
|
||||
|
||||
#ifdef HAVE_LUA_H
|
||||
srv->L = luaL_newstate();
|
||||
luaL_openlibs(srv->L);
|
||||
li_lua_init(srv->L, srv, NULL);
|
||||
|
||||
g_static_rec_mutex_free(&srv->lualock);
|
||||
#else
|
||||
srv->L = NULL;
|
||||
#endif
|
||||
li_lua_init(&srv->LL, srv, NULL);
|
||||
|
||||
srv->workers = g_array_new(FALSE, TRUE, sizeof(liWorker*));
|
||||
srv->worker_count = 0;
|
||||
|
@ -213,11 +199,7 @@ void li_server_free(liServer* srv) {
|
|||
li_ev_safe_ref_and_stop(ev_async_stop, srv->loop, &srv->state_ready_watcher);
|
||||
g_mutex_free(srv->statelock);
|
||||
|
||||
#ifdef HAVE_LUA_H
|
||||
lua_close(srv->L);
|
||||
srv->L = NULL;
|
||||
g_static_rec_mutex_free(&srv->lualock);
|
||||
#endif
|
||||
li_lua_clear(&srv->LL);
|
||||
|
||||
/* free throttle pools */
|
||||
{
|
||||
|
@ -363,10 +345,8 @@ static gboolean li_server_worker_init(liServer *srv) {
|
|||
ev_timer_start(loop, &srv->srv_1sec_timer);
|
||||
ev_unref(loop); /* don't keep loop alive */
|
||||
|
||||
#ifdef HAVE_LUA_H
|
||||
li_plugins_init_lua(srv->L, srv, NULL);
|
||||
li_plugins_init_lua(srv->main_worker->L, srv, srv->main_worker);
|
||||
#endif
|
||||
li_plugins_init_lua(&srv->LL, srv, NULL);
|
||||
li_plugins_init_lua(&srv->main_worker->LL, srv, srv->main_worker);
|
||||
|
||||
if (srv->worker_count < 1) srv->worker_count = 1;
|
||||
g_array_set_size(srv->workers, srv->worker_count);
|
||||
|
@ -380,9 +360,7 @@ static gboolean li_server_worker_init(liServer *srv) {
|
|||
wrk = g_array_index(srv->workers, liWorker*, i) = li_worker_new(srv, loop);
|
||||
wrk->ndx = i;
|
||||
|
||||
#ifdef HAVE_LUA_H
|
||||
li_plugins_init_lua(wrk->L, srv, wrk);
|
||||
#endif
|
||||
li_plugins_init_lua(&wrk->LL, srv, wrk);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
|
|
@ -9,7 +9,7 @@ typedef struct liSubrequest liSubrequest;
|
|||
struct liSubrequest {
|
||||
liWorker *wrk;
|
||||
|
||||
lua_State *L;
|
||||
liLuaState *LL;
|
||||
int func_notify_ref, func_error_ref;
|
||||
|
||||
liVRequest *vr;
|
||||
|
@ -197,13 +197,12 @@ static int li_lua_push_subrequest(lua_State *L, liSubrequest *sr) {
|
|||
|
||||
static void subvr_run_lua(liSubrequest *sr, int func_ref) {
|
||||
liServer *srv = sr->wrk->srv;
|
||||
lua_State *L = sr->L;
|
||||
gboolean dolock = (L == srv->L);
|
||||
lua_State *L = sr->LL->L;
|
||||
int errfunc;
|
||||
|
||||
if (NULL == L || LUA_REFNIL == func_ref) return;
|
||||
|
||||
if (dolock) li_lua_lock(srv);
|
||||
li_lua_lock(sr->LL);
|
||||
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, func_ref);
|
||||
|
||||
|
@ -216,28 +215,29 @@ static void subvr_run_lua(liSubrequest *sr, int func_ref) {
|
|||
}
|
||||
lua_remove(L, errfunc);
|
||||
|
||||
if (dolock) li_lua_unlock(srv);
|
||||
li_lua_unlock(sr->LL);
|
||||
}
|
||||
|
||||
static void subvr_release_lua(liSubrequest *sr) {
|
||||
liServer *srv = sr->wrk->srv;
|
||||
lua_State *L = sr->L;
|
||||
gboolean dolock = (L == srv->L);
|
||||
lua_State *L;
|
||||
liLuaState *LL = sr->LL;
|
||||
|
||||
if (NULL == L) return;
|
||||
if (NULL == LL) return;
|
||||
|
||||
sr->L = NULL;
|
||||
L = LL->L;
|
||||
sr->LL = NULL;
|
||||
|
||||
if (dolock) li_lua_lock(srv);
|
||||
li_lua_lock(LL);
|
||||
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, sr->func_notify_ref);
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, sr->func_error_ref);
|
||||
|
||||
if (dolock) li_lua_unlock(srv);
|
||||
li_lua_unlock(LL);
|
||||
}
|
||||
|
||||
static void subvr_bind_lua(liSubrequest *sr, lua_State *L, int notify_ndx, int error_ndx) {
|
||||
sr->L = L;
|
||||
static void subvr_bind_lua(liSubrequest *sr, liLuaState *LL, int notify_ndx, int error_ndx) {
|
||||
lua_State *L = LL->L;
|
||||
sr->LL = LL;
|
||||
|
||||
lua_pushvalue(L, notify_ndx); /* +1 */
|
||||
sr->func_notify_ref = luaL_ref(L, LUA_REGISTRYINDEX); /* -1 */
|
||||
|
@ -341,13 +341,14 @@ static liSubrequest* subrequest_new(liVRequest *vr) {
|
|||
|
||||
static int lua_subrequest_gc(lua_State *L) {
|
||||
liSubrequest *sr = li_lua_get_subrequest(L, 1);
|
||||
liServer *srv = sr->wrk->srv;
|
||||
gboolean dolock = (L == srv->L);
|
||||
|
||||
sr->L = NULL;
|
||||
liLuaState *LL;
|
||||
|
||||
if (NULL == sr) return 0;
|
||||
if (dolock) li_lua_unlock(srv); /* "pause" lua */
|
||||
|
||||
LL = sr->LL;
|
||||
sr->LL = NULL;
|
||||
|
||||
li_lua_unlock(LL); /* "pause" lua */
|
||||
|
||||
if (sr->vr) {
|
||||
li_vrequest_free(sr->vr);
|
||||
|
@ -364,7 +365,7 @@ static int lua_subrequest_gc(lua_State *L) {
|
|||
li_job_async(sr->parentvr_ref);
|
||||
li_job_ref_release(sr->parentvr_ref);
|
||||
|
||||
if (dolock) li_lua_lock(srv);
|
||||
li_lua_lock(LL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -383,7 +384,7 @@ int li_lua_vrequest_subrequest(lua_State *L) {
|
|||
sr = subrequest_new(vr);
|
||||
if (NULL == sr) return 0;
|
||||
|
||||
subvr_bind_lua(sr, L, 3, 4);
|
||||
subvr_bind_lua(sr, li_lua_state_get(L), 3, 4);
|
||||
|
||||
li_action_enter(sr->vr, a);
|
||||
li_vrequest_handle_request_headers(sr->vr);
|
||||
|
|
|
@ -3,12 +3,6 @@
|
|||
|
||||
#include <lighttpd/plugin_core.h>
|
||||
|
||||
#ifdef HAVE_LUA_H
|
||||
# include <lighttpd/core_lua.h>
|
||||
# include <lualib.h>
|
||||
# include <lauxlib.h>
|
||||
#endif
|
||||
|
||||
static liConnection* worker_con_get(liWorker *wrk);
|
||||
|
||||
/* closing sockets - wait for proper shutdown */
|
||||
|
@ -346,13 +340,7 @@ 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
|
||||
li_lua_init(&wrk->LL, srv, wrk);
|
||||
|
||||
g_queue_init(&wrk->keep_alive_queue);
|
||||
ev_init(&wrk->keep_alive_timer, worker_keepalive_cb);
|
||||
|
@ -487,10 +475,7 @@ void li_worker_free(liWorker *wrk) {
|
|||
|
||||
li_tasklet_pool_free(wrk->tasklets);
|
||||
|
||||
#ifdef HAVE_LUA_H
|
||||
lua_close(wrk->L);
|
||||
wrk->L = NULL;
|
||||
#endif
|
||||
li_lua_clear(&wrk->LL);
|
||||
|
||||
li_buffer_release(wrk->network_read_buf);
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ def build(bld):
|
|||
actions.c
|
||||
angel.c
|
||||
angel_fake.c
|
||||
base_lua.c
|
||||
chunk.c
|
||||
chunk_parser.c
|
||||
collect.c
|
||||
|
|
|
@ -136,7 +136,7 @@ static liHandlerResult lua_handle(liVRequest *vr, gpointer param, gpointer *cont
|
|||
|
||||
li_action_release(vr->wrk->srv, wc->act);
|
||||
wc->act = NULL;
|
||||
if (!li_config_lua_load(vr->wrk->L, vr->wrk->srv, vr->wrk, conf->filename->str, &wc->act, FALSE, conf->args) || !wc->act) {
|
||||
if (!li_config_lua_load(&vr->wrk->LL, vr->wrk->srv, vr->wrk, conf->filename->str, &wc->act, FALSE, conf->args) || !wc->act) {
|
||||
VR_ERROR(vr, "lua.handler: couldn't load '%s'", conf->filename->str);
|
||||
return LI_HANDLER_ERROR;
|
||||
}
|
||||
|
@ -291,14 +291,14 @@ static int push_args(lua_State *L, liValue *val) {
|
|||
}
|
||||
|
||||
static gboolean lua_plugin_handle_setup(liServer *srv, liPlugin *p, liValue *val, gpointer userdata) {
|
||||
lua_State *L = srv->L;
|
||||
lua_State *L = srv->LL.L;
|
||||
int lua_ref = GPOINTER_TO_INT(userdata);
|
||||
int nargs, errfunc;
|
||||
gboolean res;
|
||||
|
||||
UNUSED(p);
|
||||
|
||||
li_lua_lock(srv);
|
||||
li_lua_lock(&srv->LL);
|
||||
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, lua_ref);
|
||||
nargs = push_args(L, val);
|
||||
|
@ -319,20 +319,20 @@ static gboolean lua_plugin_handle_setup(liServer *srv, liPlugin *p, liValue *val
|
|||
lua_remove(L, errfunc);
|
||||
|
||||
lua_gc(L, LUA_GCCOLLECT, 0);
|
||||
li_lua_unlock(srv);
|
||||
li_lua_unlock(&srv->LL);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static liAction* lua_plugin_handle_action(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) {
|
||||
lua_State *L = srv->L;
|
||||
lua_State *L = srv->LL.L;
|
||||
int lua_ref = GPOINTER_TO_INT(userdata);
|
||||
int nargs, errfunc;
|
||||
liAction *res = NULL;
|
||||
|
||||
UNUSED(wrk); UNUSED(p);
|
||||
|
||||
li_lua_lock(srv);
|
||||
li_lua_lock(&srv->LL);
|
||||
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, lua_ref);
|
||||
nargs = push_args(L, val);
|
||||
|
@ -351,16 +351,16 @@ static liAction* lua_plugin_handle_action(liServer *srv, liWorker *wrk, liPlugin
|
|||
lua_remove(L, errfunc);
|
||||
|
||||
lua_gc(L, LUA_GCCOLLECT, 0);
|
||||
li_lua_unlock(srv);
|
||||
li_lua_unlock(&srv->LL);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void lua_plugin_free_data(liServer *srv, luaPlugin *lp) {
|
||||
lua_State *L = srv->L;
|
||||
lua_State *L = srv->LL.L;
|
||||
guint i;
|
||||
|
||||
if (L) li_lua_lock(srv);
|
||||
if (L) li_lua_lock(&srv->LL);
|
||||
|
||||
for (i = 0; i < lp->actions->len; i++) {
|
||||
liPluginAction *pa = &g_array_index(lp->actions, liPluginAction, i);
|
||||
|
@ -377,7 +377,7 @@ static void lua_plugin_free_data(liServer *srv, luaPlugin *lp) {
|
|||
}
|
||||
g_array_free(lp->setups, TRUE);
|
||||
|
||||
if (L) li_lua_unlock(srv);
|
||||
if (L) li_lua_unlock(&srv->LL);
|
||||
|
||||
if (lp->filename)
|
||||
g_string_free(lp->filename, TRUE);
|
||||
|
@ -472,12 +472,12 @@ static void lua_plugin_init(liServer *srv, liPlugin *p, gpointer userdata) {
|
|||
static gboolean lua_plugin_load(liServer *srv, liPlugin *p, GString *filename, liValue* args) {
|
||||
int errfunc;
|
||||
int lua_stack_top;
|
||||
lua_State *L = srv->L;
|
||||
lua_State *L = srv->LL.L;
|
||||
luaPlugin *lp;
|
||||
module_config *mc = p->data;
|
||||
liPlugin *newp;
|
||||
|
||||
li_lua_lock(srv);
|
||||
li_lua_lock(&srv->LL);
|
||||
|
||||
lua_stack_top = lua_gettop(L);
|
||||
|
||||
|
@ -527,7 +527,7 @@ static gboolean lua_plugin_load(liServer *srv, liPlugin *p, GString *filename, l
|
|||
|
||||
li_lua_restore_globals(L);
|
||||
lua_gc(L, LUA_GCCOLLECT, 0);
|
||||
li_lua_unlock(srv);
|
||||
li_lua_unlock(&srv->LL);
|
||||
|
||||
lp->filename = filename;
|
||||
|
||||
|
@ -537,7 +537,7 @@ failed_unlock_lua:
|
|||
lua_pop(L, lua_gettop(L) - lua_stack_top);
|
||||
li_lua_restore_globals(L);
|
||||
lua_gc(L, LUA_GCCOLLECT, 0);
|
||||
li_lua_unlock(srv);
|
||||
li_lua_unlock(&srv->LL);
|
||||
|
||||
g_string_free(filename, TRUE);
|
||||
|
||||
|
|
|
@ -681,7 +681,7 @@ static void lua_memcache_callback(liMemcachedRequest *request, liMemcachedResult
|
|||
liServer *srv;
|
||||
int errfunc;
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "lighty.srv");
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, LI_LUA_REGISTRY_SERVER);
|
||||
srv = lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
|
@ -1089,11 +1089,13 @@ static int mc_lua_new(lua_State *L) {
|
|||
return li_lua_push_memcached_con(L, con);
|
||||
}
|
||||
|
||||
static void mod_memcached_lua_init(lua_State *L, liServer *srv, liWorker *wrk, liPlugin *p) {
|
||||
static void mod_memcached_lua_init(liLuaState *LL, liServer *srv, liWorker *wrk, liPlugin *p) {
|
||||
lua_State *L = LL->L;
|
||||
UNUSED(srv);
|
||||
UNUSED(p);
|
||||
|
||||
if (wrk) {
|
||||
li_lua_lock(LL);
|
||||
lua_newtable(L); /* { } */
|
||||
|
||||
lua_pushlightuserdata(L, wrk);
|
||||
|
@ -1101,6 +1103,7 @@ static void mod_memcached_lua_init(lua_State *L, liServer *srv, liWorker *wrk, l
|
|||
lua_setfield(L, -2, "new");
|
||||
|
||||
lua_setfield(L, LUA_GLOBALSINDEX, "memcached");
|
||||
li_lua_unlock(LL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue