diff --git a/examples/config b/examples/config index 1dcb7014..9dafc939 100644 --- a/examples/config +++ b/examples/config @@ -6,8 +6,8 @@ address = "127.0.0.1:2526" master = "127.0.0.1:2013" start = "main" -- main script bootstrap = "snlua bootstrap" -- The service for bootstrap --- preload = "preload example" -- run preload.lua helloworld before every lua service start standalone = "0.0.0.0:2013" luaservice = root.."service/?.lua;"..root.."test/?.lua;"..root.."examples/?.lua" +lualoader = "lualib/loader.lua" snax = root.."examples/?.lua;"..root.."test/?.lua" cpath = root.."cservice/?.so" diff --git a/lualib-src/lua-skynet.c b/lualib-src/lua-skynet.c index cca9d768..0025dd52 100644 --- a/lualib-src/lua-skynet.c +++ b/lualib-src/lua-skynet.c @@ -16,18 +16,30 @@ struct snlua { const char * preload; }; +static int +traceback (lua_State *L) { + const char *msg = lua_tostring(L, 1); + if (msg) + luaL_traceback(L, L, msg, 1); + else { + lua_pushliteral(L, "(no error message)"); + } + return 1; +} + static int _cb(struct skynet_context * context, void * ud, int type, int session, uint32_t source, const void * msg, size_t sz) { lua_State *L = ud; int trace = 1; int r; int top = lua_gettop(L); - if (top == 1) { + if (top == 0) { + lua_pushcfunction(L, traceback); lua_rawgetp(L, LUA_REGISTRYINDEX, _cb); } else { assert(top == 2); - lua_pushvalue(L,2); } + lua_pushvalue(L,2); lua_pushinteger(L, type); lua_pushlightuserdata(L, (void *)msg); diff --git a/lualib/loader.lua b/lualib/loader.lua new file mode 100644 index 00000000..712cf7f1 --- /dev/null +++ b/lualib/loader.lua @@ -0,0 +1,40 @@ +local args = {} +for word in string.gmatch(..., "%S+") do + table.insert(args, word) +end + +local main, pattern + +local err = {} +for pat in string.gmatch(LUA_SERVICE, "([^;]+);*") do + local filename = string.gsub(pat, "?", args[1]) + local f, msg = loadfile(filename) + if not f then + table.insert(err, msg) + else + pattern = pat + main = f + break + end +end + +if not main then + error(table.concat(err, "\n")) +end + +LUA_SERVICE = nil +package.path , LUA_PATH = LUA_PATH +package.cpath , LUA_CPATH = LUA_CPATH + +local service_path = string.match(pattern, "(.*/)[^/?]+$") +if service_path then + package.path = service_path .. ";" .. package.path +end + +if LUA_PRELOAD then + local f = assert(loadfile(LUA_PRELOAD)) + f(table.unpack(args)) + LUA_PRELOAD = nil +end + +main(select(2, table.unpack(args))) diff --git a/service-src/service_snlua.c b/service-src/service_snlua.c index 07fb830b..d30b9078 100644 --- a/service-src/service_snlua.c +++ b/service-src/service_snlua.c @@ -13,7 +13,6 @@ struct snlua { lua_State * L; struct skynet_context * ctx; - const char * preload; }; // LUA_CACHELIB may defined in patched lua for shared proto @@ -35,85 +34,13 @@ codecache(lua_State *L) { { NULL, NULL }, }; luaL_newlib(L,l); - lua_getglobal(L, "loadfile"); - lua_setfield(L, -2, "loadfile"); + lua_getglobal(L, "loadfile"); + lua_setfield(L, -2, "loadfile"); return 1; } #endif -static int -_try_load(lua_State *L, const char * path, int pathlen, const char * name) { - int namelen = strlen(name); - char tmp[pathlen + namelen]; - int i; - for (i=0;i=0;i--) { - if (tmp[i] == '/') { - lua_pushlstring(L,tmp,i+1); - lua_setglobal(L,"SERVICE_PATH"); - break; - } - } - if (i<0) { - return 0; - } - lua_getglobal(L,"package"); - lua_getfield(L,-1,"path"); - luaL_Buffer b; - luaL_buffinit(L, &b); - luaL_addlstring(&b, tmp, i+1); - luaL_addstring(&b, "?.lua;"); - luaL_addvalue(&b); - luaL_pushresult(&b); - lua_setfield(L,-2,"path"); - lua_pop(L,1); - return 0; - } else if (r == LUA_ERRFILE) { - lua_pop(L,1); - return -1; - } - return 1; -} - -static int -_load(lua_State *L, char ** filename) { - const char * name = strsep(filename, " \r\n"); - const char * path = skynet_command(NULL, "GETENV", "luaservice"); - while (path[0]) { - int pathlen; - char * pathend = strchr(path,';'); - if (pathend) { - pathlen = pathend - path; - } else { - pathlen = strlen(path); - } - int r = _try_load(L, path, pathlen, name); - if (r >=0) { - return r; - } - path+=pathlen; - if (path[0]==';') - ++path; - } - return -1; -} - static int traceback (lua_State *L) { const char *msg = lua_tostring(L, 1); @@ -125,95 +52,65 @@ traceback (lua_State *L) { return 1; } -static void -_report_error(lua_State *L, struct skynet_context *ctx, const char *filename, int err) { - switch (err) { - case LUA_ERRRUN: - skynet_error(ctx, "lua do [%s] error : %s", filename, lua_tostring(L,-1)); - break; - case LUA_ERRMEM: - skynet_error(ctx, "lua memory error : %s",filename); - break; - case LUA_ERRERR: - skynet_error(ctx, "lua message error : %s",filename); - break; - case LUA_ERRGCMM: - skynet_error(ctx, "lua gc error : %s",filename); - break; - }; - lua_pop(L,1); -} - static void _report_launcher_error(struct skynet_context *ctx) { // sizeof "ERROR" == 5 skynet_sendname(ctx, ".launcher", PTYPE_TEXT, 0, "ERROR", 5); } -static int -dofile(lua_State *L, struct skynet_context *ctx, const char * args) { - int traceback_index = 1; - char tmp[strlen(args)+1]; - char *parm = tmp; - strcpy(parm,args); - - const char * filename = parm; - int r = _load(L, &parm); - if (r != 0) { - if (r<0) { - skynet_error(ctx, "lua parser [%s] load error", filename); - } else { - skynet_error(ctx, "lua parser [%s] error : %s", filename, lua_tostring(L,-1)); - } - _report_launcher_error(ctx); - return 1; +static const char * +optstring(struct skynet_context *ctx, const char *key, const char * str) { + const char * ret = skynet_command(ctx, "GETENV", key); + if (ret == NULL) { + return str; } - int n=0; - while(parm) { - const char * arg = strsep(&parm, " \r\n"); - if (arg && arg[0]!='\0') { - lua_pushstring(L, arg); - ++n; - } - } - r = lua_pcall(L,n,0,traceback_index); - if (r == LUA_OK) { - r = lua_gc(L, LUA_GCCOLLECT, 0); - if (r == LUA_OK) { - return 0; - } - } - _report_error(L, ctx, filename, r); - _report_launcher_error(ctx); - return 1; + return ret; } static int -_init(struct snlua *l, struct skynet_context *ctx, const char * args) { +_init(struct snlua *l, struct skynet_context *ctx, const char * args, size_t sz) { lua_State *L = l->L; l->ctx = ctx; lua_gc(L, LUA_GCSTOP, 0); + lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */ + lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); luaL_openlibs(L); lua_pushlightuserdata(L, ctx); lua_setfield(L, LUA_REGISTRYINDEX, "skynet_context"); luaL_requiref(L, "skynet.codecache", codecache , 0); lua_pop(L,1); + const char *path = optstring(ctx, "lua_path","./lualib/?.lua;./lualib/?/init.lua"); + lua_pushstring(L, path); + lua_setglobal(L, "LUA_PATH"); + const char *cpath = optstring(ctx, "lua_cpath","./luaclib/?.so"); + lua_pushstring(L, cpath); + lua_setglobal(L, "LUA_CPATH"); + const char *service = optstring(ctx, "luaservice", "./service/?.lua"); + lua_pushstring(L, service); + lua_setglobal(L, "LUA_SERVICE"); + const char *preload = skynet_command(ctx, "preload"); + lua_setglobal(L, "LUA_PRELOAD"); + lua_pushcfunction(L, traceback); assert(lua_gettop(L) == 1); - if (l->preload) { - size_t l1 = strlen(l->preload); - size_t l2 = strlen(args); - char tmp[l1 + l2 + 2]; - sprintf(tmp, "%s %s", l->preload, args); - if (dofile(L, ctx, tmp)) { - return 1; - } - } - if (dofile(L, ctx, args)) { + const char * loader = optstring(ctx, "lualoader", "./lualib/loader.lua"); + + int r = luaL_loadfile(L,loader); + if (r != LUA_OK) { + skynet_error(ctx, "Can't load %s : %s", loader, lua_tostring(L, -1)); + _report_launcher_error(ctx); return 1; } + lua_pushlstring(L, args, sz); + r = lua_pcall(L,1,0,1); + if (r != LUA_OK) { + skynet_error(ctx, "lua loader error : %s", lua_tostring(L, -1)); + _report_launcher_error(ctx); + return 1; + } + lua_settop(L,0); lua_gc(L, LUA_GCRESTART, 0); @@ -225,7 +122,7 @@ _launch(struct skynet_context * context, void *ud, int type, int session, uint32 assert(type == 0 && session == 0); struct snlua *l = ud; skynet_callback(context, NULL, NULL); - int err = _init(l, context, msg); + int err = _init(l, context, msg, sz); if (err) { skynet_command(context, "EXIT", NULL); } @@ -235,18 +132,14 @@ _launch(struct skynet_context * context, void *ud, int type, int session, uint32 int snlua_init(struct snlua *l, struct skynet_context *ctx, const char * args) { - const char * preload = skynet_command(ctx, "GETENV", "preload"); - if (preload && preload[0]) { - l->preload = skynet_strdup(preload); - } int sz = strlen(args); - char * tmp = skynet_malloc(sz+1); - memcpy(tmp, args, sz+1); + char * tmp = skynet_malloc(sz); + memcpy(tmp, args, sz); skynet_callback(ctx, l , _launch); const char * self = skynet_command(ctx, "REG", NULL); uint32_t handle_id = strtoul(self+1, NULL, 16); // it must be first message - skynet_send(ctx, 0, handle_id, PTYPE_TAG_DONTCOPY,0, tmp, sz+1); + skynet_send(ctx, 0, handle_id, PTYPE_TAG_DONTCOPY,0, tmp, sz); return 0; } @@ -255,13 +148,11 @@ snlua_create(void) { struct snlua * l = skynet_malloc(sizeof(*l)); memset(l,0,sizeof(*l)); l->L = lua_newstate(skynet_lalloc, NULL); - l->preload = NULL; return l; } void snlua_release(struct snlua *l) { lua_close(l->L); - skynet_free((void*)l->preload); skynet_free(l); } diff --git a/service/bootstrap.lua b/service/bootstrap.lua index 9e6ff58a..c928b90a 100644 --- a/service/bootstrap.lua +++ b/service/bootstrap.lua @@ -5,10 +5,11 @@ skynet.start(function() skynet.name(".launcher", launcher) if skynet.getenv "standalone" then - local datacenter = assert(skynet.newservice "datacenter") + local datacenter = assert(skynet.newservice "datacenterd") skynet.name("DATACENTER", datacenter) local smgr = assert(skynet.newservice "service_mgr") end + skynet.uniqueservice("multicastd") assert(skynet.newservice(skynet.getenv "start" or "main")) skynet.exit() end) diff --git a/service/datacenter.lua b/service/datacenterd.lua similarity index 100% rename from service/datacenter.lua rename to service/datacenterd.lua diff --git a/service/multicastd.lua b/service/multicastd.lua index 02b8ef89..2afce758 100644 --- a/service/multicastd.lua +++ b/service/multicastd.lua @@ -1,5 +1,6 @@ local skynet = require "skynet" local mc = require "multicast.c" +local datacenter = require "datacenter" local command = {} local channel = {} @@ -49,4 +50,8 @@ skynet.start(function() local f = assert(command[cmd]) skynet.ret(skynet.pack(f(source, ...))) end) + local self = skynet.self() + local id = skynet.harbor(self) + assert(datacenter.set("multicast", id, self) == nil) end) + diff --git a/skynet-src/skynet_main.c b/skynet-src/skynet_main.c index 15c29bce..b4b898d7 100644 --- a/skynet-src/skynet_main.c +++ b/skynet-src/skynet_main.c @@ -113,12 +113,6 @@ main(int argc, char *argv[]) { printf("Skynet lua code cache enable\n"); #endif - const char *path = optstring("lua_path","./lualib/?.lua;./lualib/?/init.lua"); - setenv("LUA_PATH",path,1); - const char *cpath = optstring("lua_cpath","./luaclib/?.so"); - setenv("LUA_CPATH",cpath,1); - optstring("luaservice","./service/?.lua"); - config.thread = optint("thread",8); config.module_path = optstring("cpath","./cservice/?.so"); config.logger = optstring("logger",NULL); diff --git a/test/testsocket.lua b/test/testsocket.lua index 3794fefb..c465079c 100644 --- a/test/testsocket.lua +++ b/test/testsocket.lua @@ -37,7 +37,8 @@ else end skynet.start(function() - local id = socket.listen("127.0.0.1", 8000) + local id = socket.listen("127.0.0.1", 8001) + print("Listen socket :", "127.0.0.1", 8001) socket.start(id , function(id, addr) print("connect from " .. addr .. " " .. id)