2 * signal.c -- Signal Handler Library for Lua
4 * Version: 1.000+changes
6 * Copyright (C) 2007 Patrick J. Donnelly (batrick@batbytes.com)
8 * This software is distributed under the same license as Lua 5.0:
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
24 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26 * OTHER DEALINGS IN THE SOFTWARE.
35 #if (LUA_VERSION_NUM == 502)
36 #define luaL_register(L, N, R) luaL_setfuncs(L, R, 0)
45 char *name; /* name of the signal */
46 int sig; /* the signal */
51 #define LUA_SIGNAL "lua_signal"
53 static const struct lua_signal lua_signals[] = {
102 {"SIGCONT", SIGCONT},
105 {"SIGSTOP", SIGSTOP},
108 {"SIGTTIN", SIGTTIN},
111 {"SIGTTOU", SIGTTOU},
113 /* some BSD signals */
127 {"SIGXCPU", SIGXCPU},
130 {"SIGXFSZ", SIGXFSZ},
133 {"SIGVTALRM", SIGVTALRM},
136 {"SIGPROF", SIGPROF},
139 {"SIGWINCH", SIGWINCH},
142 {"SIGPOLL", SIGPOLL},
147 /* add odd signals */
149 {"SIGSTKFLT", SIGSTKFLT}, /* stack fault */
157 static lua_State *Lsig = NULL;
158 static lua_Hook Hsig = NULL;
159 static int Hmask = 0;
160 static int Hcount = 0;
162 static struct signal_event
165 struct signal_event *next_event;
166 } *signal_queue = NULL;
168 static struct signal_event *last_event = NULL;
170 static void sighook(lua_State *L, lua_Debug *ar)
172 struct signal_event *event;
173 /* restore the old hook */
174 lua_sethook(L, Hsig, Hmask, Hcount);
176 lua_pushstring(L, LUA_SIGNAL);
177 lua_gettable(L, LUA_REGISTRYINDEX);
179 while((event = signal_queue))
181 lua_pushnumber(L, event->Nsig);
184 signal_queue = event->next_event;
188 lua_pop(L, 1); /* pop lua_signal table */
192 static void handle(int sig)
196 /* Store the existing debug hook (if any) and its parameters */
197 Hsig = lua_gethook(Lsig);
198 Hmask = lua_gethookmask(Lsig);
199 Hcount = lua_gethookcount(Lsig);
201 signal_queue = malloc(sizeof(struct signal_event));
202 signal_queue->Nsig = sig;
203 signal_queue->next_event = NULL;
205 last_event = signal_queue;
207 /* Set our new debug hook */
208 lua_sethook(Lsig, sighook, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
212 last_event->next_event = malloc(sizeof(struct signal_event));
213 last_event->next_event->Nsig = sig;
214 last_event->next_event->next_event = NULL;
216 last_event = last_event->next_event;
221 * l_signal == signal(signal [, func [, chook]])
223 * signal = signal number or string
224 * func = Lua function to call
225 * chook = catch within C functions
226 * if caught, Lua function _must_
227 * exit, as the stack is most likely
228 * in an unstable state.
231 static int l_signal(lua_State *L)
233 int args = lua_gettop(L);
234 int t, sig; /* type, signal */
236 /* get type of signal */
239 if (t == LUA_TNUMBER)
240 sig = (int) lua_tonumber(L, 1);
241 else if (t == LUA_TSTRING)
243 lua_pushstring(L, LUA_SIGNAL);
244 lua_gettable(L, LUA_REGISTRYINDEX);
247 if (!lua_isnumber(L, -1))
248 luaL_error(L, "invalid signal string");
249 sig = (int) lua_tonumber(L, -1);
250 lua_pop(L, 1); /* get rid of number we pushed */
252 luaL_checknumber(L, 1); /* will always error, with good error msg */
255 if (args == 1 || lua_isnil(L, 2)) /* clear handler */
257 lua_pushstring(L, LUA_SIGNAL);
258 lua_gettable(L, LUA_REGISTRYINDEX);
259 lua_pushnumber(L, sig);
260 lua_gettable(L, -2); /* return old handler */
261 lua_pushnumber(L, sig);
264 lua_remove(L, -2); /* remove LUA_SIGNAL table */
265 signal(sig, SIG_DFL);
268 luaL_checktype(L, 2, LUA_TFUNCTION);
270 lua_pushstring(L, LUA_SIGNAL);
271 lua_gettable(L, LUA_REGISTRYINDEX);
273 lua_pushnumber(L, sig);
277 /* Set the state for the handler */
280 if (lua_toboolean(L, 3)) /* c hook? */
282 if (signal(sig, handle) == SIG_ERR)
283 lua_pushboolean(L, 0);
285 lua_pushboolean(L, 1);
286 } else /* lua_hook */
288 if (signal(sig, handle) == SIG_ERR)
289 lua_pushboolean(L, 0);
291 lua_pushboolean(L, 1);
298 * l_raise == raise(signal)
300 * signal = signal number or string
303 static int l_raise(lua_State *L)
305 /* int args = lua_gettop(L); */
306 int t = 0; /* type */
312 if (t == LUA_TNUMBER)
314 ret = (lua_Number) raise((int) lua_tonumber(L, 1));
315 lua_pushnumber(L, ret);
316 } else if (t == LUA_TSTRING)
318 lua_pushstring(L, LUA_SIGNAL);
319 lua_gettable(L, LUA_REGISTRYINDEX);
322 if (!lua_isnumber(L, -1))
323 luaL_error(L, "invalid signal string");
324 ret = (lua_Number) raise((int) lua_tonumber(L, -1));
325 lua_pop(L, 1); /* get rid of number we pushed */
326 lua_pushnumber(L, ret);
328 luaL_checknumber(L, 1); /* will always error, with good error msg */
333 #if defined(__unix__) || defined(__APPLE__)
335 /* define some posix only functions */
338 * l_kill == kill(pid, signal)
341 * signal = signal number or string
344 static int l_kill(lua_State *L)
347 lua_Number ret; /* return value */
349 luaL_checknumber(L, 1); /* must be int for pid */
350 luaL_checkany(L, 2); /* check for a second arg */
353 if (t == LUA_TNUMBER)
355 ret = (lua_Number) kill((int) lua_tonumber(L, 1),
356 (int) lua_tonumber(L, 2));
357 lua_pushnumber(L, ret);
358 } else if (t == LUA_TSTRING)
360 lua_pushstring(L, LUA_SIGNAL);
361 lua_gettable(L, LUA_REGISTRYINDEX);
364 if (!lua_isnumber(L, -1))
365 luaL_error(L, "invalid signal string");
366 ret = (lua_Number) kill((int) lua_tonumber(L, 1),
367 (int) lua_tonumber(L, -1));
368 lua_pop(L, 1); /* get rid of number we pushed */
369 lua_pushnumber(L, ret);
371 luaL_checknumber(L, 2); /* will always error, with good error msg */
377 static const struct luaL_Reg lsignal_lib[] = {
378 {"signal", l_signal},
380 #if defined(__unix__) || defined(__APPLE__)
386 int luaopen_util_signal(lua_State *L)
390 /* add the library */
392 luaL_register(L, NULL, lsignal_lib);
394 /* push lua_signals table into the registry */
395 /* put the signals inside the library table too,
396 * they are only a reference */
397 lua_pushstring(L, LUA_SIGNAL);
400 while (lua_signals[i].name != NULL)
403 lua_pushstring(L, lua_signals[i].name);
404 lua_pushnumber(L, lua_signals[i].sig);
407 lua_pushstring(L, lua_signals[i].name);
408 lua_pushnumber(L, lua_signals[i].sig);
413 /* add newtable to the registry */
414 lua_settable(L, LUA_REGISTRYINDEX);