X-Git-Url: https://git.enpas.org/?a=blobdiff_plain;f=util-src%2Fsignal.c;h=725555fa58ec7b79b9dd95f029871de2dc3b79dd;hb=f6f011dfbc3d179c77c0431ffacfaaf091f18053;hp=80799e4a782cba339019a7ccf41122892bc94c65;hpb=3949cf751f8d23da101f1bf32e77bc3f9ed61395;p=prosody.git diff --git a/util-src/signal.c b/util-src/signal.c index 80799e4a..725555fa 100644 --- a/util-src/signal.c +++ b/util-src/signal.c @@ -1,9 +1,9 @@ /* - * lsignal.h -- Signal Handler Library for Lua + * signal.c -- Signal Handler Library for Lua * - * Version: 1.000 + * Version: 1.000+changes * - * Copyright (C) 2007 Patrick J. Donnelly (batrick@unm.edu) + * Copyright (C) 2007 Patrick J. Donnelly (batrick@batbytes.com) * * This software is distributed under the same license as Lua 5.0: * @@ -23,22 +23,26 @@ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. + * OTHER DEALINGS IN THE SOFTWARE. */ #include +#include #include "lua.h" #include "lauxlib.h" +#if (LUA_VERSION_NUM == 501) +#define luaL_setfuncs(L, R, N) luaL_register(L, NULL, R) +#endif + #ifndef lsig #define lsig -struct lua_signal -{ - char *name; /* name of the signal */ - int sig; /* the signal */ +struct lua_signal { + char* name; /* name of the signal */ + int sig; /* the signal */ }; #endif @@ -46,146 +50,163 @@ struct lua_signal #define LUA_SIGNAL "lua_signal" static const struct lua_signal lua_signals[] = { - /* ANSI C signals */ + /* ANSI C signals */ #ifdef SIGABRT - {"SIGABRT", SIGABRT}, + {"SIGABRT", SIGABRT}, #endif #ifdef SIGFPE - {"SIGFPE", SIGFPE}, + {"SIGFPE", SIGFPE}, #endif #ifdef SIGILL - {"SIGILL", SIGILL}, + {"SIGILL", SIGILL}, #endif #ifdef SIGINT - {"SIGINT", SIGINT}, + {"SIGINT", SIGINT}, #endif #ifdef SIGSEGV - {"SIGSEGV", SIGSEGV}, + {"SIGSEGV", SIGSEGV}, #endif #ifdef SIGTERM - {"SIGTERM", SIGTERM}, + {"SIGTERM", SIGTERM}, #endif - /* posix signals */ + /* posix signals */ #ifdef SIGHUP - {"SIGHUP", SIGHUP}, + {"SIGHUP", SIGHUP}, #endif #ifdef SIGQUIT - {"SIGQUIT", SIGQUIT}, + {"SIGQUIT", SIGQUIT}, #endif #ifdef SIGTRAP - {"SIGTRAP", SIGTRAP}, + {"SIGTRAP", SIGTRAP}, #endif #ifdef SIGKILL - {"SIGKILL", SIGKILL}, + {"SIGKILL", SIGKILL}, #endif #ifdef SIGUSR1 - {"SIGUSR1", SIGUSR1}, + {"SIGUSR1", SIGUSR1}, #endif #ifdef SIGUSR2 - {"SIGUSR2", SIGUSR2}, + {"SIGUSR2", SIGUSR2}, #endif #ifdef SIGPIPE - {"SIGPIPE", SIGPIPE}, + {"SIGPIPE", SIGPIPE}, #endif #ifdef SIGALRM - {"SIGALRM", SIGALRM}, + {"SIGALRM", SIGALRM}, #endif #ifdef SIGCHLD - {"SIGCHLD", SIGCHLD}, + {"SIGCHLD", SIGCHLD}, #endif #ifdef SIGCONT - {"SIGCONT", SIGCONT}, + {"SIGCONT", SIGCONT}, #endif #ifdef SIGSTOP - {"SIGSTOP", SIGSTOP}, + {"SIGSTOP", SIGSTOP}, #endif #ifdef SIGTTIN - {"SIGTTIN", SIGTTIN}, + {"SIGTTIN", SIGTTIN}, #endif #ifdef SIGTTOU - {"SIGTTOU", SIGTTOU}, + {"SIGTTOU", SIGTTOU}, #endif - /* some BSD signals */ + /* some BSD signals */ #ifdef SIGIOT - {"SIGIOT", SIGIOT}, + {"SIGIOT", SIGIOT}, #endif #ifdef SIGBUS - {"SIGBUS", SIGBUS}, + {"SIGBUS", SIGBUS}, #endif #ifdef SIGCLD - {"SIGCLD", SIGCLD}, + {"SIGCLD", SIGCLD}, #endif #ifdef SIGURG - {"SIGURG", SIGURG}, + {"SIGURG", SIGURG}, #endif #ifdef SIGXCPU - {"SIGXCPU", SIGXCPU}, + {"SIGXCPU", SIGXCPU}, #endif #ifdef SIGXFSZ - {"SIGXFSZ", SIGXFSZ}, + {"SIGXFSZ", SIGXFSZ}, #endif #ifdef SIGVTALRM - {"SIGVTALRM", SIGVTALRM}, + {"SIGVTALRM", SIGVTALRM}, #endif #ifdef SIGPROF - {"SIGPROF", SIGPROF}, + {"SIGPROF", SIGPROF}, #endif #ifdef SIGWINCH - {"SIGWINCH", SIGWINCH}, + {"SIGWINCH", SIGWINCH}, #endif #ifdef SIGPOLL - {"SIGPOLL", SIGPOLL}, + {"SIGPOLL", SIGPOLL}, #endif #ifdef SIGIO - {"SIGIO", SIGIO}, + {"SIGIO", SIGIO}, #endif - /* add odd signals */ + /* add odd signals */ #ifdef SIGSTKFLT - {"SIGSTKFLT", SIGSTKFLT}, /* stack fault */ + {"SIGSTKFLT", SIGSTKFLT}, /* stack fault */ #endif #ifdef SIGSYS - {"SIGSYS", SIGSYS}, + {"SIGSYS", SIGSYS}, #endif - {NULL, 0} + {NULL, 0} }; -static int Nsig = 0; -static lua_State *Lsig = NULL; +static lua_State* Lsig = NULL; static lua_Hook Hsig = NULL; static int Hmask = 0; static int Hcount = 0; -static void sighook(lua_State *L, lua_Debug *ar) -{ - lua_pushstring(L, LUA_SIGNAL); - lua_gettable(L, LUA_REGISTRYINDEX); - lua_pushnumber(L, Nsig); - lua_gettable(L, -2); +static struct signal_event { + int Nsig; + struct signal_event* next_event; +}* signal_queue = NULL; + +static struct signal_event* last_event = NULL; + +static void sighook(lua_State* L, lua_Debug* ar) { + struct signal_event* event; + /* restore the old hook */ + lua_sethook(L, Hsig, Hmask, Hcount); + + lua_pushstring(L, LUA_SIGNAL); + lua_gettable(L, LUA_REGISTRYINDEX); + + while((event = signal_queue)) { + lua_pushnumber(L, event->Nsig); + lua_gettable(L, -2); + lua_call(L, 0, 0); + signal_queue = event->next_event; + free(event); + }; - lua_call(L, 0, 0); + lua_pop(L, 1); /* pop lua_signal table */ - /* set the old hook */ - lua_sethook(L, Hsig, Hmask, Hcount); } -static void handle(int sig) -{ - Hsig = lua_gethook(Lsig); - Hmask = lua_gethookmask(Lsig); - Hcount = lua_gethookcount(Lsig); - Nsig = sig; - - lua_sethook(Lsig, sighook, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); - /* - switch (sig) - { - case SIGABRT: ; - case SIGFPE: ; - case SIGILL: ; - case SIGINT: ; - case SIGSEGV: ; - case SIGTERM: ; - } */ +static void handle(int sig) { + if(!signal_queue) { + /* Store the existing debug hook (if any) and its parameters */ + Hsig = lua_gethook(Lsig); + Hmask = lua_gethookmask(Lsig); + Hcount = lua_gethookcount(Lsig); + + signal_queue = malloc(sizeof(struct signal_event)); + signal_queue->Nsig = sig; + signal_queue->next_event = NULL; + + last_event = signal_queue; + + /* Set our new debug hook */ + lua_sethook(Lsig, sighook, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); + } else { + last_event->next_event = malloc(sizeof(struct signal_event)); + last_event->next_event->Nsig = sig; + last_event->next_event->next_event = NULL; + + last_event = last_event->next_event; + } } /* @@ -197,111 +218,116 @@ static void handle(int sig) * if caught, Lua function _must_ * exit, as the stack is most likely * in an unstable state. -*/ - -static int l_signal(lua_State *L) -{ - int args = lua_gettop(L); - int t, sig; /* type, signal */ - - /* get type of signal */ - luaL_checkany(L, 1); - t = lua_type(L, 1); - if (t == LUA_TNUMBER) - sig = (int) lua_tonumber(L, 1); - else if (t == LUA_TSTRING) - { - lua_pushstring(L, LUA_SIGNAL); - lua_gettable(L, LUA_REGISTRYINDEX); - lua_pushvalue(L, 1); - lua_gettable(L, -2); - if (!lua_isnumber(L, -1)) - luaL_error(L, "invalid signal string"); - sig = (int) lua_tonumber(L, -1); - lua_pop(L, 1); /* get rid of number we pushed */ - } else - luaL_checknumber(L, 1); /* will always error, with good error msg */ - - /* set handler */ - if (args == 1 || lua_isnil(L, 2)) /* clear handler */ - { - lua_pushstring(L, LUA_SIGNAL); - lua_gettable(L, LUA_REGISTRYINDEX); - lua_pushnumber(L, sig); - lua_gettable(L, -2); /* return old handler */ - lua_pushnumber(L, sig); - lua_pushnil(L); - lua_settable(L, -4); - lua_remove(L, -2); /* remove LUA_SIGNAL table */ - signal(sig, SIG_DFL); - } else - { - luaL_checktype(L, 2, LUA_TFUNCTION); - - lua_pushstring(L, LUA_SIGNAL); - lua_gettable(L, LUA_REGISTRYINDEX); - - lua_pushnumber(L, sig); - lua_pushvalue(L, 2); - lua_settable(L, -3); - - /* Set the state for the handler */ - Lsig = L; - - if (lua_toboolean(L, 3)) /* c hook? */ - { - if (signal(sig, handle) == SIG_ERR) - lua_pushboolean(L, 0); - else - lua_pushboolean(L, 1); - } else /* lua_hook */ - { - if (signal(sig, handle) == SIG_ERR) - lua_pushboolean(L, 0); - else - lua_pushboolean(L, 1); - } - } - return 1; +*/ + +static int l_signal(lua_State* L) { + int args = lua_gettop(L); + int t, sig; /* type, signal */ + + /* get type of signal */ + luaL_checkany(L, 1); + t = lua_type(L, 1); + + if(t == LUA_TNUMBER) { + sig = (int) lua_tonumber(L, 1); + } else if(t == LUA_TSTRING) { + lua_pushstring(L, LUA_SIGNAL); + lua_gettable(L, LUA_REGISTRYINDEX); + lua_pushvalue(L, 1); + lua_gettable(L, -2); + + if(!lua_isnumber(L, -1)) { + return luaL_error(L, "invalid signal string"); + } + + sig = (int) lua_tonumber(L, -1); + lua_pop(L, 1); /* get rid of number we pushed */ + } else { + luaL_checknumber(L, 1); /* will always error, with good error msg */ + return luaL_error(L, "unreachable: invalid number was accepted"); + } + + /* set handler */ + if(args == 1 || lua_isnil(L, 2)) { /* clear handler */ + lua_pushstring(L, LUA_SIGNAL); + lua_gettable(L, LUA_REGISTRYINDEX); + lua_pushnumber(L, sig); + lua_gettable(L, -2); /* return old handler */ + lua_pushnumber(L, sig); + lua_pushnil(L); + lua_settable(L, -4); + lua_remove(L, -2); /* remove LUA_SIGNAL table */ + signal(sig, SIG_DFL); + } else { + luaL_checktype(L, 2, LUA_TFUNCTION); + + lua_pushstring(L, LUA_SIGNAL); + lua_gettable(L, LUA_REGISTRYINDEX); + + lua_pushnumber(L, sig); + lua_pushvalue(L, 2); + lua_settable(L, -3); + + /* Set the state for the handler */ + Lsig = L; + + if(lua_toboolean(L, 3)) { /* c hook? */ + if(signal(sig, handle) == SIG_ERR) { + lua_pushboolean(L, 0); + } else { + lua_pushboolean(L, 1); + } + } else { /* lua_hook */ + if(signal(sig, handle) == SIG_ERR) { + lua_pushboolean(L, 0); + } else { + lua_pushboolean(L, 1); + } + } + } + + return 1; } /* * l_raise == raise(signal) * * signal = signal number or string -*/ - -static int l_raise(lua_State *L) -{ - /* int args = lua_gettop(L); */ - int t = 0; /* type */ - lua_Number ret; - - luaL_checkany(L, 1); - - t = lua_type(L, 1); - if (t == LUA_TNUMBER) - { - ret = (lua_Number) raise((int) lua_tonumber(L, 1)); - lua_pushnumber(L, ret); - } else if (t == LUA_TSTRING) - { - lua_pushstring(L, LUA_SIGNAL); - lua_gettable(L, LUA_REGISTRYINDEX); - lua_pushvalue(L, 1); - lua_gettable(L, -2); - if (!lua_isnumber(L, -1)) - luaL_error(L, "invalid signal string"); - ret = (lua_Number) raise((int) lua_tonumber(L, -1)); - lua_pop(L, 1); /* get rid of number we pushed */ - lua_pushnumber(L, ret); - } else - luaL_checknumber(L, 1); /* will always error, with good error msg */ - - return 1; +*/ + +static int l_raise(lua_State* L) { + /* int args = lua_gettop(L); */ + int t = 0; /* type */ + lua_Number ret; + + luaL_checkany(L, 1); + + t = lua_type(L, 1); + + if(t == LUA_TNUMBER) { + ret = (lua_Number) raise((int) lua_tonumber(L, 1)); + lua_pushnumber(L, ret); + } else if(t == LUA_TSTRING) { + lua_pushstring(L, LUA_SIGNAL); + lua_gettable(L, LUA_REGISTRYINDEX); + lua_pushvalue(L, 1); + lua_gettable(L, -2); + + if(!lua_isnumber(L, -1)) { + return luaL_error(L, "invalid signal string"); + } + + ret = (lua_Number) raise((int) lua_tonumber(L, -1)); + lua_pop(L, 1); /* get rid of number we pushed */ + lua_pushnumber(L, ret); + } else { + luaL_checknumber(L, 1); /* will always error, with good error msg */ + } + + return 1; } -#if defined _POSIX_SOURCE || (defined(sun) || defined(__sun)) +#if defined(__unix__) || defined(__APPLE__) /* define some posix only functions */ @@ -310,78 +336,80 @@ static int l_raise(lua_State *L) * * pid = process id * signal = signal number or string -*/ - -static int l_kill(lua_State *L) -{ - int t; /* type */ - lua_Number ret; /* return value */ - - luaL_checknumber(L, 1); /* must be int for pid */ - luaL_checkany(L, 2); /* check for a second arg */ - - t = lua_type(L, 2); - if (t == LUA_TNUMBER) - { - ret = (lua_Number) kill((int) lua_tonumber(L, 1), - (int) lua_tonumber(L, 2)); - lua_pushnumber(L, ret); - } else if (t == LUA_TSTRING) - { - lua_pushstring(L, LUA_SIGNAL); - lua_gettable(L, LUA_REGISTRYINDEX); - lua_pushvalue(L, 2); - lua_gettable(L, -2); - if (!lua_isnumber(L, -1)) - luaL_error(L, "invalid signal string"); - ret = (lua_Number) kill((int) lua_tonumber(L, 1), - (int) lua_tonumber(L, -1)); - lua_pop(L, 1); /* get rid of number we pushed */ - lua_pushnumber(L, ret); - } else - luaL_checknumber(L, 2); /* will always error, with good error msg */ - return 1; +*/ + +static int l_kill(lua_State* L) { + int t; /* type */ + lua_Number ret; /* return value */ + + luaL_checknumber(L, 1); /* must be int for pid */ + luaL_checkany(L, 2); /* check for a second arg */ + + t = lua_type(L, 2); + + if(t == LUA_TNUMBER) { + ret = (lua_Number) kill((int) lua_tonumber(L, 1), + (int) lua_tonumber(L, 2)); + lua_pushnumber(L, ret); + } else if(t == LUA_TSTRING) { + lua_pushstring(L, LUA_SIGNAL); + lua_gettable(L, LUA_REGISTRYINDEX); + lua_pushvalue(L, 2); + lua_gettable(L, -2); + + if(!lua_isnumber(L, -1)) { + return luaL_error(L, "invalid signal string"); + } + + ret = (lua_Number) kill((int) lua_tonumber(L, 1), + (int) lua_tonumber(L, -1)); + lua_pop(L, 1); /* get rid of number we pushed */ + lua_pushnumber(L, ret); + } else { + luaL_checknumber(L, 2); /* will always error, with good error msg */ + } + + return 1; } #endif static const struct luaL_Reg lsignal_lib[] = { - {"signal", l_signal}, - {"raise", l_raise}, -#ifdef _POSIX_SOURCE - {"kill", l_kill}, + {"signal", l_signal}, + {"raise", l_raise}, +#if defined(__unix__) || defined(__APPLE__) + {"kill", l_kill}, #endif - {NULL, NULL} + {NULL, NULL} }; -int luaopen_util_signal(lua_State *L) -{ - int i = 0; - - /* add the library */ - luaL_register(L, "signal", lsignal_lib); - - /* push lua_signals table into the registry */ - /* put the signals inside the library table too, - * they are only a reference */ - lua_pushstring(L, LUA_SIGNAL); - lua_createtable(L, 0, 0); - - while (lua_signals[i].name != NULL) - { - /* registry table */ - lua_pushstring(L, lua_signals[i].name); - lua_pushnumber(L, lua_signals[i].sig); - lua_settable(L, -3); - /* signal table */ - lua_pushstring(L, lua_signals[i].name); - lua_pushnumber(L, lua_signals[i].sig); - lua_settable(L, -5); - i++; - } - - /* add newtable to the registry */ - lua_settable(L, LUA_REGISTRYINDEX); - - return 1; +int luaopen_util_signal(lua_State* L) { + int i = 0; + + /* add the library */ + lua_newtable(L); + luaL_setfuncs(L, lsignal_lib, 0); + + /* push lua_signals table into the registry */ + /* put the signals inside the library table too, + * they are only a reference */ + lua_pushstring(L, LUA_SIGNAL); + lua_newtable(L); + + while(lua_signals[i].name != NULL) { + /* registry table */ + lua_pushstring(L, lua_signals[i].name); + lua_pushnumber(L, lua_signals[i].sig); + lua_settable(L, -3); + /* signal table */ + lua_pushstring(L, lua_signals[i].name); + lua_pushnumber(L, lua_signals[i].sig); + lua_settable(L, -5); + i++; + } + + /* add newtable to the registry */ + lua_settable(L, LUA_REGISTRYINDEX); + + return 1; }