2 * lsignal.h -- Signal Handler Library for Lua
6 * Copyright (C) 2007 Patrick J. Donnelly (batrick@unm.edu)
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.
41 char *name; /* name of the signal */
42 int sig; /* the signal */
47 #define LUA_SIGNAL "lua_signal"
49 static const struct lua_signal lua_signals[] = {
101 {"SIGSTOP", SIGSTOP},
104 {"SIGTTIN", SIGTTIN},
107 {"SIGTTOU", SIGTTOU},
109 /* some BSD signals */
123 {"SIGXCPU", SIGXCPU},
126 {"SIGXFSZ", SIGXFSZ},
129 {"SIGVTALRM", SIGVTALRM},
132 {"SIGPROF", SIGPROF},
135 {"SIGWINCH", SIGWINCH},
138 {"SIGPOLL", SIGPOLL},
143 /* add odd signals */
145 {"SIGSTKFLT", SIGSTKFLT}, /* stack fault */
153 static lua_State *Lsig = NULL;
154 static lua_Hook Hsig = NULL;
155 static int Hmask = 0;
156 static int Hcount = 0;
158 static struct signal_event
161 struct signal_event *next_event;
162 } *signal_queue = NULL;
164 static struct signal_event *last_event = NULL;
166 static void sighook(lua_State *L, lua_Debug *ar)
168 lua_pushstring(L, LUA_SIGNAL);
169 lua_gettable(L, LUA_REGISTRYINDEX);
171 struct signal_event *event;
172 while((event = signal_queue))
174 lua_pushnumber(L, event->Nsig);
177 signal_queue = event->next_event;
181 lua_pop(L, 1); /* pop lua_signal table */
183 /* restore the old hook */
184 lua_sethook(L, Hsig, Hmask, Hcount);
187 static void handle(int sig)
191 /* Store the existing debug hook (if any) and its parameters */
192 Hsig = lua_gethook(Lsig);
193 Hmask = lua_gethookmask(Lsig);
194 Hcount = lua_gethookcount(Lsig);
196 signal_queue = malloc(sizeof(struct signal_event));
197 signal_queue->Nsig = sig;
198 signal_queue->next_event = NULL;
200 last_event = signal_queue;
202 /* Set our new debug hook */
203 lua_sethook(Lsig, sighook, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
207 last_event->next_event = malloc(sizeof(struct signal_event));
208 last_event->next_event->Nsig = sig;
209 last_event->next_event->next_event = NULL;
211 last_event = last_event->next_event;
216 * l_signal == signal(signal [, func [, chook]])
218 * signal = signal number or string
219 * func = Lua function to call
220 * chook = catch within C functions
221 * if caught, Lua function _must_
222 * exit, as the stack is most likely
223 * in an unstable state.
226 static int l_signal(lua_State *L)
228 int args = lua_gettop(L);
229 int t, sig; /* type, signal */
231 /* get type of signal */
234 if (t == LUA_TNUMBER)
235 sig = (int) lua_tonumber(L, 1);
236 else if (t == LUA_TSTRING)
238 lua_pushstring(L, LUA_SIGNAL);
239 lua_gettable(L, LUA_REGISTRYINDEX);
242 if (!lua_isnumber(L, -1))
243 luaL_error(L, "invalid signal string");
244 sig = (int) lua_tonumber(L, -1);
245 lua_pop(L, 1); /* get rid of number we pushed */
247 luaL_checknumber(L, 1); /* will always error, with good error msg */
250 if (args == 1 || lua_isnil(L, 2)) /* clear handler */
252 lua_pushstring(L, LUA_SIGNAL);
253 lua_gettable(L, LUA_REGISTRYINDEX);
254 lua_pushnumber(L, sig);
255 lua_gettable(L, -2); /* return old handler */
256 lua_pushnumber(L, sig);
259 lua_remove(L, -2); /* remove LUA_SIGNAL table */
260 signal(sig, SIG_DFL);
263 luaL_checktype(L, 2, LUA_TFUNCTION);
265 lua_pushstring(L, LUA_SIGNAL);
266 lua_gettable(L, LUA_REGISTRYINDEX);
268 lua_pushnumber(L, sig);
272 /* Set the state for the handler */
275 if (lua_toboolean(L, 3)) /* c hook? */
277 if (signal(sig, handle) == SIG_ERR)
278 lua_pushboolean(L, 0);
280 lua_pushboolean(L, 1);
281 } else /* lua_hook */
283 if (signal(sig, handle) == SIG_ERR)
284 lua_pushboolean(L, 0);
286 lua_pushboolean(L, 1);
293 * l_raise == raise(signal)
295 * signal = signal number or string
298 static int l_raise(lua_State *L)
300 /* int args = lua_gettop(L); */
301 int t = 0; /* type */
307 if (t == LUA_TNUMBER)
309 ret = (lua_Number) raise((int) lua_tonumber(L, 1));
310 lua_pushnumber(L, ret);
311 } else if (t == LUA_TSTRING)
313 lua_pushstring(L, LUA_SIGNAL);
314 lua_gettable(L, LUA_REGISTRYINDEX);
317 if (!lua_isnumber(L, -1))
318 luaL_error(L, "invalid signal string");
319 ret = (lua_Number) raise((int) lua_tonumber(L, -1));
320 lua_pop(L, 1); /* get rid of number we pushed */
321 lua_pushnumber(L, ret);
323 luaL_checknumber(L, 1); /* will always error, with good error msg */
328 #if defined _POSIX_SOURCE || (defined(sun) || defined(__sun))
330 /* define some posix only functions */
333 * l_kill == kill(pid, signal)
336 * signal = signal number or string
339 static int l_kill(lua_State *L)
342 lua_Number ret; /* return value */
344 luaL_checknumber(L, 1); /* must be int for pid */
345 luaL_checkany(L, 2); /* check for a second arg */
348 if (t == LUA_TNUMBER)
350 ret = (lua_Number) kill((int) lua_tonumber(L, 1),
351 (int) lua_tonumber(L, 2));
352 lua_pushnumber(L, ret);
353 } else if (t == LUA_TSTRING)
355 lua_pushstring(L, LUA_SIGNAL);
356 lua_gettable(L, LUA_REGISTRYINDEX);
359 if (!lua_isnumber(L, -1))
360 luaL_error(L, "invalid signal string");
361 ret = (lua_Number) kill((int) lua_tonumber(L, 1),
362 (int) lua_tonumber(L, -1));
363 lua_pop(L, 1); /* get rid of number we pushed */
364 lua_pushnumber(L, ret);
366 luaL_checknumber(L, 2); /* will always error, with good error msg */
372 static const struct luaL_Reg lsignal_lib[] = {
373 {"signal", l_signal},
375 #if defined _POSIX_SOURCE || (defined(sun) || defined(__sun))
381 int luaopen_util_signal(lua_State *L)
385 /* add the library */
386 luaL_register(L, "signal", lsignal_lib);
388 /* push lua_signals table into the registry */
389 /* put the signals inside the library table too,
390 * they are only a reference */
391 lua_pushstring(L, LUA_SIGNAL);
392 lua_createtable(L, 0, 0);
394 while (lua_signals[i].name != NULL)
397 lua_pushstring(L, lua_signals[i].name);
398 lua_pushnumber(L, lua_signals[i].sig);
401 lua_pushstring(L, lua_signals[i].name);
402 lua_pushnumber(L, lua_signals[i].sig);
407 /* add newtable to the registry */
408 lua_settable(L, LUA_REGISTRYINDEX);