diff --git a/3rd/lua/lua.h b/3rd/lua/lua.h index 579a5e17..747a372a 100644 --- a/3rd/lua/lua.h +++ b/3rd/lua/lua.h @@ -458,6 +458,11 @@ struct lua_Debug { /* }====================================================================== */ +/* Add by skynet */ + +extern lua_State * skynet_sig_L; +LUA_API void (lua_checksig_)(lua_State *L); +#define lua_checksig(L) if (skynet_sig_L) { lua_checksig_(L); } /****************************************************************************** * Copyright (C) 1994-2015 Lua.org, PUC-Rio. diff --git a/3rd/lua/lvm.c b/3rd/lua/lvm.c index e7348d8b..8a51550c 100644 --- a/3rd/lua/lvm.c +++ b/3rd/lua/lvm.c @@ -43,6 +43,17 @@ /* limit for table tag-method chains (to avoid loops) */ #define MAXTAGLOOP 2000 +/* Add by skynet */ +lua_State * skynet_sig_L = NULL; + +LUA_API void +lua_checksig_(lua_State *L) { + if (skynet_sig_L == G(L)->mainthread) { + skynet_sig_L = NULL; + lua_pushnil(L); + lua_error(L); + } +} /* ** Similar to 'tonumber', but does not attempt to convert strings and @@ -935,6 +946,7 @@ void luaV_execute (lua_State *L) { vmbreak; } vmcase(OP_JMP) { + lua_checksig(L); dojump(ci, i, 0); vmbreak; } @@ -987,6 +999,7 @@ void luaV_execute (lua_State *L) { vmcase(OP_CALL) { int b = GETARG_B(i); int nresults = GETARG_C(i) - 1; + lua_checksig(L); if (b != 0) L->top = ra+b; /* else previous instruction set top */ if (luaD_precall(L, ra, nresults)) { /* C function? */ if (nresults >= 0) L->top = ci->top; /* adjust results */ @@ -1001,6 +1014,7 @@ void luaV_execute (lua_State *L) { } vmcase(OP_TAILCALL) { int b = GETARG_B(i); + lua_checksig(L); if (b != 0) L->top = ra+b; /* else previous instruction set top */ lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); if (luaD_precall(L, ra, LUA_MULTRET)) /* C function? */ @@ -1111,6 +1125,7 @@ void luaV_execute (lua_State *L) { } vmcase(OP_TFORLOOP) { l_tforloop: + lua_checksig(L); if (!ttisnil(ra + 1)) { /* continue loop? */ setobjs2s(L, ra, ra + 1); /* save control variable */ ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ diff --git a/service-src/service_snlua.c b/service-src/service_snlua.c index 0063c8c6..1ab533a2 100644 --- a/service-src/service_snlua.c +++ b/service-src/service_snlua.c @@ -156,3 +156,9 @@ snlua_release(struct snlua *l) { lua_close(l->L); skynet_free(l); } + +void +snlua_signal(struct snlua *l, int signal) { + skynet_error(l->ctx, "recv a signal %d", signal); + skynet_sig_L = l->L; +} diff --git a/service/debug_console.lua b/service/debug_console.lua index 0133d293..142cf601 100644 --- a/service/debug_console.lua +++ b/service/debug_console.lua @@ -50,8 +50,11 @@ end local function docmd(cmdline, print, fd) local split = split_cmdline(cmdline) - table.insert(split, fd) - local cmd = COMMAND[split[1]] + local command = split[1] + if command == "debug" then + table.insert(split, fd) + end + local cmd = COMMAND[command] local ok, list if cmd then ok, list = pcall(cmd, select(2,table.unpack(split))) @@ -126,6 +129,7 @@ function COMMAND.help() logoff = "logoff address", log = "launch a new lua service with log", debug = "debug address : debug a lua service", + signal = "signal address sig", } end @@ -244,3 +248,12 @@ function COMMAND.logoff(address) address = adjust_address(address) core.command("LOGOFF", skynet.address(address)) end + +function COMMAND.signal(address, sig) + address = skynet.address(adjust_address(address)) + if sig then + core.command("SIGNAL", string.format("%s %d",address,sig)) + else + core.command("SIGNAL", address) + end +end diff --git a/skynet-src/skynet_module.c b/skynet-src/skynet_module.c index 66dd4629..2da34629 100644 --- a/skynet-src/skynet_module.c +++ b/skynet-src/skynet_module.c @@ -75,7 +75,7 @@ _query(const char * name) { static int _open_sym(struct skynet_module *mod) { size_t name_size = strlen(mod->name); - char tmp[name_size + 9]; // create/init/release , longest name is release (7) + char tmp[name_size + 9]; // create/init/release/signal , longest name is release (7) memcpy(tmp, mod->name, name_size); strcpy(tmp+name_size, "_create"); mod->create = dlsym(mod->module, tmp); @@ -83,6 +83,8 @@ _open_sym(struct skynet_module *mod) { mod->init = dlsym(mod->module, tmp); strcpy(tmp+name_size, "_release"); mod->release = dlsym(mod->module, tmp); + strcpy(tmp+name_size, "_signal"); + mod->signal = dlsym(mod->module, tmp); return mod->init == NULL; } @@ -150,6 +152,13 @@ skynet_module_instance_release(struct skynet_module *m, void *inst) { } } +void +skynet_module_instance_signal(struct skynet_module *m, void *inst, int signal) { + if (m->signal) { + m->signal(inst, signal); + } +} + void skynet_module_init(const char *path) { struct modules *m = skynet_malloc(sizeof(*m)); diff --git a/skynet-src/skynet_module.h b/skynet-src/skynet_module.h index a2d96306..52b5e181 100644 --- a/skynet-src/skynet_module.h +++ b/skynet-src/skynet_module.h @@ -6,6 +6,7 @@ struct skynet_context; typedef void * (*skynet_dl_create)(void); typedef int (*skynet_dl_init)(void * inst, struct skynet_context *, const char * parm); typedef void (*skynet_dl_release)(void * inst); +typedef void (*skynet_dl_signal)(void * inst, int signal); struct skynet_module { const char * name; @@ -13,6 +14,7 @@ struct skynet_module { skynet_dl_create create; skynet_dl_init init; skynet_dl_release release; + skynet_dl_signal signal; }; void skynet_module_insert(struct skynet_module *mod); @@ -20,6 +22,7 @@ struct skynet_module * skynet_module_query(const char * name); void * skynet_module_instance_create(struct skynet_module *); int skynet_module_instance_init(struct skynet_module *, void * inst, struct skynet_context *ctx, const char * parm); void skynet_module_instance_release(struct skynet_module *, void *inst); +void skynet_module_instance_signal(struct skynet_module *, void *inst, int signal); void skynet_module_init(const char *path); diff --git a/skynet-src/skynet_server.c b/skynet-src/skynet_server.c index a1961f13..4527529e 100644 --- a/skynet-src/skynet_server.c +++ b/skynet-src/skynet_server.c @@ -589,6 +589,26 @@ cmd_logoff(struct skynet_context * context, const char * param) { return NULL; } +static const char * +cmd_signal(struct skynet_context * context, const char * param) { + uint32_t handle = tohandle(context, param); + if (handle == 0) + return NULL; + struct skynet_context * ctx = skynet_handle_grab(handle); + if (ctx == NULL) + return NULL; + param = strchr(param, ' '); + int sig = 0; + if (param) { + sig = strtol(param, NULL, 0); + } + // NOTICE: the signal function should be thread safe. + skynet_module_instance_signal(ctx->mod, ctx->instance, sig); + + skynet_context_release(ctx); + return NULL; +} + static struct command_func cmd_funcs[] = { { "TIMEOUT", cmd_timeout }, { "REG", cmd_reg }, @@ -607,6 +627,7 @@ static struct command_func cmd_funcs[] = { { "MQLEN", cmd_mqlen }, { "LOGON", cmd_logon }, { "LOGOFF", cmd_logoff }, + { "SIGNAL", cmd_signal }, { NULL, NULL }, };