diff options
Diffstat (limited to 'lua/uloop.c')
-rw-r--r-- | lua/uloop.c | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/lua/uloop.c b/lua/uloop.c index 45c9bc7..7a73f16 100644 --- a/lua/uloop.c +++ b/lua/uloop.c @@ -46,6 +46,11 @@ struct lua_uloop_interval { int r; }; +struct lua_uloop_signal { + struct uloop_signal s; + int r; +}; + static lua_State *state; static void * @@ -493,6 +498,83 @@ static int ul_interval(lua_State *L) return 1; } +static void ul_signal_cb(struct uloop_signal *s) +{ + struct lua_uloop_signal *sig = container_of(s, struct lua_uloop_signal, s); + + lua_getglobal(state, "__uloop_cb"); + lua_rawgeti(state, -1, sig->r); + lua_remove(state, -2); + lua_pushinteger(state, sig->s.signo); + + lua_call(state, 1, 0); +} + +static int ul_signal_signo(lua_State *L) +{ + struct lua_uloop_signal *sig = lua_touserdata(L, 1); + + lua_pushinteger(L, sig->s.signo); + + return 1; +} + +static int ul_signal_free(lua_State *L) +{ + struct lua_uloop_signal *sig = lua_touserdata(L, 1); + + uloop_signal_delete(&sig->s); + + /* obj.__index.__gc = nil , make sure executing only once*/ + lua_getfield(L, -1, "__index"); + lua_pushstring(L, "__gc"); + lua_pushnil(L); + lua_settable(L, -3); + + lua_getglobal(state, "__uloop_cb"); + luaL_unref(state, -1, sig->r); + + return 1; +} + +static const luaL_Reg signal_m[] = { + { "signo", ul_signal_signo }, + { "delete", ul_signal_free }, + { NULL, NULL } +}; + +static int ul_signal(lua_State *L) +{ + struct lua_uloop_signal *sig; + int signo = -1; + int ref; + + if (lua_isnumber(L, -1)) { + signo = lua_tointeger(L, -1); + lua_pop(L, 1); + } + + if (!lua_isfunction(L, -1) || signo <= 0 || signo > NSIG) { + lua_pushstring(L, "invalid arg list"); + lua_error(L); + + return 0; + } + + lua_getglobal(L, "__uloop_cb"); + lua_pushvalue(L, -2); + ref = luaL_ref(L, -2); + + sig = ul_create_userdata(L, sizeof(*sig), signal_m, ul_signal_free); + sig->r = ref; + sig->s.cb = ul_signal_cb; + sig->s.signo = signo; + + uloop_signal_add(&sig->s); + + return 1; +} + static int ul_init(lua_State *L) { uloop_init(); @@ -522,6 +604,7 @@ static luaL_reg uloop_func[] = { {"process", ul_process}, {"fd_add", ul_ufd_add}, {"interval", ul_interval}, + {"signal", ul_signal}, {"cancel", ul_end}, {NULL, NULL}, }; @@ -561,6 +644,103 @@ int luaopen_uloop(lua_State *L) lua_pushinteger(L, ULOOP_BLOCKING); lua_rawset(L, -3); +#define SIGNAME_CONST(signame) do { \ + lua_pushstring(L, #signame); \ + lua_pushinteger(L, signame); \ + lua_rawset(L, -3); \ +} while(0) + +#if defined(SIGINT) + SIGNAME_CONST(SIGINT); +#endif +#if defined(SIGILL) + SIGNAME_CONST(SIGILL); +#endif +#if defined(SIGABRT) + SIGNAME_CONST(SIGABRT); +#endif +#if defined(SIGFPE) + SIGNAME_CONST(SIGFPE); +#endif +#if defined(SIGSEGV) + SIGNAME_CONST(SIGSEGV); +#endif +#if defined(SIGTERM) + SIGNAME_CONST(SIGTERM); +#endif +#if defined(SIGHUP) + SIGNAME_CONST(SIGHUP); +#endif +#if defined(SIGQUIT) + SIGNAME_CONST(SIGQUIT); +#endif +#if defined(SIGTRAP) + SIGNAME_CONST(SIGTRAP); +#endif +#if defined(SIGKILL) + SIGNAME_CONST(SIGKILL); +#endif +#if defined(SIGPIPE) + SIGNAME_CONST(SIGPIPE); +#endif +#if defined(SIGALRM) + SIGNAME_CONST(SIGALRM); +#endif +#if defined(SIGSTKFLT) + SIGNAME_CONST(SIGSTKFLT); +#endif +#if defined(SIGPWR) + SIGNAME_CONST(SIGPWR); +#endif +#if defined(SIGBUS) + SIGNAME_CONST(SIGBUS); +#endif +#if defined(SIGSYS) + SIGNAME_CONST(SIGSYS); +#endif +#if defined(SIGURG) + SIGNAME_CONST(SIGURG); +#endif +#if defined(SIGSTOP) + SIGNAME_CONST(SIGSTOP); +#endif +#if defined(SIGTSTP) + SIGNAME_CONST(SIGTSTP); +#endif +#if defined(SIGCONT) + SIGNAME_CONST(SIGCONT); +#endif +#if defined(SIGCHLD) + SIGNAME_CONST(SIGCHLD); +#endif +#if defined(SIGTTIN) + SIGNAME_CONST(SIGTTIN); +#endif +#if defined(SIGTTOU) + SIGNAME_CONST(SIGTTOU); +#endif +#if defined(SIGPOLL) + SIGNAME_CONST(SIGPOLL); +#endif +#if defined(SIGXFSZ) + SIGNAME_CONST(SIGXFSZ); +#endif +#if defined(SIGXCPU) + SIGNAME_CONST(SIGXCPU); +#endif +#if defined(SIGVTALRM) + SIGNAME_CONST(SIGVTALRM); +#endif +#if defined(SIGPROF) + SIGNAME_CONST(SIGPROF); +#endif +#if defined(SIGUSR1) + SIGNAME_CONST(SIGUSR1); +#endif +#if defined(SIGUSR2) + SIGNAME_CONST(SIGUSR2); +#endif + return 1; } |