This is a tricky feature to implement because of the fact that the popular lua consoles (lua 5.3-5.1 & luajit) implement SIGINTs poorly
For example, lets take the reference implementation lua 5.3.
here is the SIGINT handler:
static void laction (int i) {
signal(i, SIG_DFL); /* if another SIGINT happens, terminate process */
lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
}
The handler sets the default handler (which crashes) upon activation.
Because we run in script mode (to execute ilua's interp.lua) that handler is only installed once. Because of that, If the same session will handle two SIGINTs, it will crash.
A secondary problem is that there are many lua consoles who are not even handling SIGINTs, and crash upon the signal.
There are couple of solutions I could think of:
- Run in console mode
Pipe the interp.script into the host lua stdin in interactive mode (after getting rid of the prompts)
e.g.
lua -i -e "_PROMPT='' _PROMPT2=''" < interp.lua
This way the lua-error-throwing SIGINT handler is installed after every evaluation, and multiple signals could be caught
The down side is that we should not allow the user to read from stdin (io.input:read) because that will mess things up.
- Serialize the session
We could track every evaluation request, serialize a state in the python kernel, and on SIGINT kill the lua host, launch a new one and dump the state back. Not sure this is possible though.
- Proxy lua host's signal()
If we could replace signal() with a function that NO-OPs on SIG_DFL, we could use the lua-error-throwing handler multiple times
i.e. Inject the lua host some library like this
void *__real_signal(int sig, void *func);
void *__wrap_signal(int sig, void *func)
{
void *old_handler = __real_signal(sig, SIG_DFL);
__real_signal(sig, old_handler);
if (SIGINT == sig && SIG_DFL == func)
{
return old_handler;
}
else
{
return __real_signal(sig, func);
}
}
The down-side of course is that implementing DLL injection for every platform (Windows especially) is hell.
- Not implementing Ctrl-C at all
We could call this a known issue, and stop bothering about it.
If we were to offer a solution anyway, we could distribute a patched lua.c (that won't reinstall default interrupt upon signal)
This is a tricky feature to implement because of the fact that the popular lua consoles (lua 5.3-5.1 &
luajit) implement SIGINTs poorlyFor example, lets take the reference implementation lua 5.3.
here is the SIGINT handler:
The handler sets the default handler (which crashes) upon activation.
Because we run in script mode (to execute ilua's interp.lua) that handler is only installed once. Because of that, If the same session will handle two SIGINTs, it will crash.
A secondary problem is that there are many lua consoles who are not even handling SIGINTs, and crash upon the signal.
There are couple of solutions I could think of:
Pipe the interp.script into the host lua stdin in interactive mode (after getting rid of the prompts)
e.g.
This way the lua-error-throwing SIGINT handler is installed after every evaluation, and multiple signals could be caught
The down side is that we should not allow the user to read from stdin (io.input:read) because that will mess things up.
We could track every evaluation request, serialize a state in the python kernel, and on SIGINT kill the lua host, launch a new one and dump the state back. Not sure this is possible though.
If we could replace signal() with a function that NO-OPs on SIG_DFL, we could use the lua-error-throwing handler multiple times
i.e. Inject the lua host some library like this
The down-side of course is that implementing DLL injection for every platform (Windows especially) is hell.
We could call this a known issue, and stop bothering about it.
If we were to offer a solution anyway, we could distribute a patched lua.c (that won't reinstall default interrupt upon signal)