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 == 501)
36 #define luaL_setfuncs(L, R, N) luaL_register(L, NULL, R)
44 char* name; /* name of the signal */
45 int sig; /* the signal */
50 #define LUA_SIGNAL "lua_signal"
52 static const struct lua_signal lua_signals[] = {
101 {"SIGCONT", SIGCONT},
104 {"SIGSTOP", SIGSTOP},
107 {"SIGTTIN", SIGTTIN},
110 {"SIGTTOU", SIGTTOU},
112 /* some BSD signals */
126 {"SIGXCPU", SIGXCPU},
129 {"SIGXFSZ", SIGXFSZ},
132 {"SIGVTALRM", SIGVTALRM},
135 {"SIGPROF", SIGPROF},
138 {"SIGWINCH", SIGWINCH},
141 {"SIGPOLL", SIGPOLL},
146 /* add odd signals */
148 {"SIGSTKFLT", SIGSTKFLT}, /* stack fault */
156 static lua_State* Lsig = NULL;
157 static lua_Hook Hsig = NULL;
158 static int Hmask = 0;
159 static int Hcount = 0;
161 static struct signal_event {
163 struct signal_event* next_event;
164 }* signal_queue = NULL;
166 static struct signal_event* last_event = NULL;
168 static void sighook(lua_State* L, lua_Debug* ar) {
169 struct signal_event* event;
170 /* restore the old hook */
171 lua_sethook(L, Hsig, Hmask, Hcount);
173 lua_pushstring(L, LUA_SIGNAL);
174 lua_gettable(L, LUA_REGISTRYINDEX);
176 while((event = signal_queue)) {
177 lua_pushnumber(L, event->Nsig);
180 signal_queue = event->next_event;
184 lua_pop(L, 1); /* pop lua_signal table */
188 static void handle(int sig) {
190 /* Store the existing debug hook (if any) and its parameters */
191 Hsig = lua_gethook(Lsig);
192 Hmask = lua_gethookmask(Lsig);
193 Hcount = lua_gethookcount(Lsig);
195 signal_queue = malloc(sizeof(struct signal_event));
196 signal_queue->Nsig = sig;
197 signal_queue->next_event = NULL;
199 last_event = signal_queue;
201 /* Set our new debug hook */
202 lua_sethook(Lsig, sighook, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
204 last_event->next_event = malloc(sizeof(struct signal_event));
205 last_event->next_event->Nsig = sig;
206 last_event->next_event->next_event = NULL;
208 last_event = last_event->next_event;
213 * l_signal == signal(signal [, func [, chook]])
215 * signal = signal number or string
216 * func = Lua function to call
217 * chook = catch within C functions
218 * if caught, Lua function _must_
219 * exit, as the stack is most likely
220 * in an unstable state.
223 static int l_signal(lua_State* L) {
224 int args = lua_gettop(L);
225 int t, sig; /* type, signal */
227 /* get type of signal */
231 if(t == LUA_TNUMBER) {
232 sig = (int) lua_tonumber(L, 1);
233 } else if(t == LUA_TSTRING) {
234 lua_pushstring(L, LUA_SIGNAL);
235 lua_gettable(L, LUA_REGISTRYINDEX);
239 if(!lua_isnumber(L, -1)) {
240 return luaL_error(L, "invalid signal string");
243 sig = (int) lua_tonumber(L, -1);
244 lua_pop(L, 1); /* get rid of number we pushed */
246 luaL_checknumber(L, 1); /* will always error, with good error msg */
247 return luaL_error(L, "unreachable: invalid number was accepted");
251 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);
262 luaL_checktype(L, 2, LUA_TFUNCTION);
264 lua_pushstring(L, LUA_SIGNAL);
265 lua_gettable(L, LUA_REGISTRYINDEX);
267 lua_pushnumber(L, sig);
271 /* Set the state for the handler */
274 if(lua_toboolean(L, 3)) { /* c hook? */
275 if(signal(sig, handle) == SIG_ERR) {
276 lua_pushboolean(L, 0);
278 lua_pushboolean(L, 1);
280 } else { /* lua_hook */
281 if(signal(sig, handle) == SIG_ERR) {
282 lua_pushboolean(L, 0);
284 lua_pushboolean(L, 1);
293 * l_raise == raise(signal)
295 * signal = signal number or string
298 static int l_raise(lua_State* L) {
299 /* int args = lua_gettop(L); */
300 int t = 0; /* type */
307 if(t == LUA_TNUMBER) {
308 ret = (lua_Number) raise((int) lua_tonumber(L, 1));
309 lua_pushnumber(L, ret);
310 } else if(t == LUA_TSTRING) {
311 lua_pushstring(L, LUA_SIGNAL);
312 lua_gettable(L, LUA_REGISTRYINDEX);
316 if(!lua_isnumber(L, -1)) {
317 return luaL_error(L, "invalid signal string");
320 ret = (lua_Number) raise((int) lua_tonumber(L, -1));
321 lua_pop(L, 1); /* get rid of number we pushed */
322 lua_pushnumber(L, ret);
324 luaL_checknumber(L, 1); /* will always error, with good error msg */
330 #if defined(__unix__) || defined(__APPLE__)
332 /* define some posix only functions */
335 * l_kill == kill(pid, signal)
338 * signal = signal number or string
341 static int l_kill(lua_State* L) {
343 lua_Number ret; /* return value */
345 luaL_checknumber(L, 1); /* must be int for pid */
346 luaL_checkany(L, 2); /* check for a second arg */
350 if(t == LUA_TNUMBER) {
351 ret = (lua_Number) kill((int) lua_tonumber(L, 1),
352 (int) lua_tonumber(L, 2));
353 lua_pushnumber(L, ret);
354 } else if(t == LUA_TSTRING) {
355 lua_pushstring(L, LUA_SIGNAL);
356 lua_gettable(L, LUA_REGISTRYINDEX);
360 if(!lua_isnumber(L, -1)) {
361 return luaL_error(L, "invalid signal string");
364 ret = (lua_Number) kill((int) lua_tonumber(L, 1),
365 (int) lua_tonumber(L, -1));
366 lua_pop(L, 1); /* get rid of number we pushed */
367 lua_pushnumber(L, ret);
369 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) {
389 /* add the library */
391 luaL_setfuncs(L, lsignal_lib, 0);
393 /* push lua_signals table into the registry */
394 /* put the signals inside the library table too,
395 * they are only a reference */
396 lua_pushstring(L, LUA_SIGNAL);
399 while(lua_signals[i].name != NULL) {
401 lua_pushstring(L, lua_signals[i].name);
402 lua_pushnumber(L, lua_signals[i].sig);
405 lua_pushstring(L, lua_signals[i].name);
406 lua_pushnumber(L, lua_signals[i].sig);
411 /* add newtable to the registry */
412 lua_settable(L, LUA_REGISTRYINDEX);