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.
37 #if (LUA_VERSION_NUM == 501)
38 #define luaL_setfuncs(L, R, N) luaL_register(L, NULL, R)
46 char *name
; /* name of the signal */
47 int sig
; /* the signal */
52 #define LUA_SIGNAL "lua_signal"
54 static const struct lua_signal lua_signals
[] = {
100 {"SIGCHLD", SIGCHLD
},
103 {"SIGCONT", SIGCONT
},
106 {"SIGSTOP", SIGSTOP
},
109 {"SIGTTIN", SIGTTIN
},
112 {"SIGTTOU", SIGTTOU
},
114 /* some BSD signals */
128 {"SIGXCPU", SIGXCPU
},
131 {"SIGXFSZ", SIGXFSZ
},
134 {"SIGVTALRM", SIGVTALRM
},
137 {"SIGPROF", SIGPROF
},
140 {"SIGWINCH", SIGWINCH
},
143 {"SIGPOLL", SIGPOLL
},
148 /* add odd signals */
150 {"SIGSTKFLT", SIGSTKFLT
}, /* stack fault */
158 static lua_State
*Lsig
= NULL
;
159 static lua_Hook Hsig
= NULL
;
160 static int Hmask
= 0;
161 static int Hcount
= 0;
163 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
) {
171 struct signal_event
*event
;
172 /* restore the old hook */
173 lua_sethook(L
, Hsig
, Hmask
, Hcount
);
175 lua_pushstring(L
, LUA_SIGNAL
);
176 lua_gettable(L
, LUA_REGISTRYINDEX
);
178 while((event
= signal_queue
)) {
179 lua_pushnumber(L
, event
->Nsig
);
182 signal_queue
= event
->next_event
;
186 lua_pop(L
, 1); /* pop lua_signal table */
190 static void handle(int sig
) {
192 /* Store the existing debug hook (if any) and its parameters */
193 Hsig
= lua_gethook(Lsig
);
194 Hmask
= lua_gethookmask(Lsig
);
195 Hcount
= lua_gethookcount(Lsig
);
197 signal_queue
= malloc(sizeof(struct signal_event
));
198 signal_queue
->Nsig
= sig
;
199 signal_queue
->next_event
= NULL
;
201 last_event
= signal_queue
;
203 /* Set our new debug hook */
204 lua_sethook(Lsig
, sighook
, LUA_MASKCALL
| LUA_MASKRET
| LUA_MASKCOUNT
, 1);
206 last_event
->next_event
= malloc(sizeof(struct signal_event
));
207 last_event
->next_event
->Nsig
= sig
;
208 last_event
->next_event
->next_event
= NULL
;
210 last_event
= last_event
->next_event
;
215 * l_signal == signal(signal [, func [, chook]])
217 * signal = signal number or string
218 * func = Lua function to call
219 * chook = catch within C functions
220 * if caught, Lua function _must_
221 * exit, as the stack is most likely
222 * in an unstable state.
225 static int l_signal(lua_State
*L
) {
226 int args
= lua_gettop(L
);
227 int t
, sig
; /* type, signal */
229 /* get type of signal */
233 if(t
== LUA_TNUMBER
) {
234 sig
= (int) lua_tonumber(L
, 1);
235 } else if(t
== LUA_TSTRING
) {
236 lua_pushstring(L
, LUA_SIGNAL
);
237 lua_gettable(L
, LUA_REGISTRYINDEX
);
241 if(!lua_isnumber(L
, -1)) {
242 return luaL_error(L
, "invalid signal string");
245 sig
= (int) lua_tonumber(L
, -1);
246 lua_pop(L
, 1); /* get rid of number we pushed */
248 luaL_checknumber(L
, 1); /* will always error, with good error msg */
249 return luaL_error(L
, "unreachable: invalid number was accepted");
253 if(args
== 1 || lua_isnil(L
, 2)) { /* clear handler */
254 lua_pushstring(L
, LUA_SIGNAL
);
255 lua_gettable(L
, LUA_REGISTRYINDEX
);
256 lua_pushnumber(L
, sig
);
257 lua_gettable(L
, -2); /* return old handler */
258 lua_pushnumber(L
, sig
);
261 lua_remove(L
, -2); /* remove LUA_SIGNAL table */
262 signal(sig
, SIG_DFL
);
264 luaL_checktype(L
, 2, LUA_TFUNCTION
);
266 lua_pushstring(L
, LUA_SIGNAL
);
267 lua_gettable(L
, LUA_REGISTRYINDEX
);
269 lua_pushnumber(L
, sig
);
273 /* Set the state for the handler */
276 if(lua_toboolean(L
, 3)) { /* c hook? */
277 if(signal(sig
, handle
) == SIG_ERR
) {
278 lua_pushboolean(L
, 0);
280 lua_pushboolean(L
, 1);
282 } else { /* lua_hook */
283 if(signal(sig
, handle
) == SIG_ERR
) {
284 lua_pushboolean(L
, 0);
286 lua_pushboolean(L
, 1);
295 * l_raise == raise(signal)
297 * signal = signal number or string
300 static int l_raise(lua_State
*L
) {
301 /* int args = lua_gettop(L); */
302 int t
= 0; /* type */
309 if(t
== LUA_TNUMBER
) {
310 ret
= (lua_Number
) raise((int) lua_tonumber(L
, 1));
311 lua_pushnumber(L
, ret
);
312 } else if(t
== LUA_TSTRING
) {
313 lua_pushstring(L
, LUA_SIGNAL
);
314 lua_gettable(L
, LUA_REGISTRYINDEX
);
318 if(!lua_isnumber(L
, -1)) {
319 return luaL_error(L
, "invalid signal string");
322 ret
= (lua_Number
) raise((int) lua_tonumber(L
, -1));
323 lua_pop(L
, 1); /* get rid of number we pushed */
324 lua_pushnumber(L
, ret
);
326 luaL_checknumber(L
, 1); /* will always error, with good error msg */
332 #if defined(__unix__) || defined(__APPLE__)
334 /* define some posix only functions */
337 * l_kill == kill(pid, signal)
340 * signal = signal number or string
343 static int l_kill(lua_State
*L
) {
345 lua_Number ret
; /* return value */
347 luaL_checknumber(L
, 1); /* must be int for pid */
348 luaL_checkany(L
, 2); /* check for a second arg */
352 if(t
== LUA_TNUMBER
) {
353 ret
= (lua_Number
) kill((int) lua_tonumber(L
, 1),
354 (int) lua_tonumber(L
, 2));
355 lua_pushnumber(L
, ret
);
356 } else if(t
== LUA_TSTRING
) {
357 lua_pushstring(L
, LUA_SIGNAL
);
358 lua_gettable(L
, LUA_REGISTRYINDEX
);
362 if(!lua_isnumber(L
, -1)) {
363 return 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 */
379 static const struct luaL_Reg lsignal_lib
[] = {
380 {"signal", l_signal
},
382 #if defined(__unix__) || defined(__APPLE__)
388 int luaopen_util_signal(lua_State
*L
) {
389 #if (LUA_VERSION_NUM > 501)
390 luaL_checkversion(L
);
394 /* add the library */
396 luaL_setfuncs(L
, lsignal_lib
, 0);
398 /* push lua_signals table into the registry */
399 /* put the signals inside the library table too,
400 * they are only a reference */
401 lua_pushstring(L
, LUA_SIGNAL
);
404 while(lua_signals
[i
].name
!= NULL
) {
406 lua_pushstring(L
, lua_signals
[i
].name
);
407 lua_pushnumber(L
, lua_signals
[i
].sig
);
410 lua_pushstring(L
, lua_signals
[i
].name
);
411 lua_pushnumber(L
, lua_signals
[i
].sig
);
416 /* add newtable to the registry */
417 lua_settable(L
, LUA_REGISTRYINDEX
);