在lua 5.2.4中,当在无限循环中使用广泛使用的os.execute('sleep n')
方法时,程序不能被^C
(Ctrl-C)停止。
最小例子:
while true do
print("HELLO!")
os.execute("sleep 3")
end
我的问题是:
这是预期的行为吗?我会猜到程序在从^C
命令返回后收到os.execute
信号。
是否有"内置"睡觉方式有效?
答案 0 :(得分:3)
Control-c最有可能被os.execute
而不是Lua生成的shell捕获。您需要查看os.execute
返回的代码。当命令正常结束时,os.execute
返回true,"退出",rc。否则,它返回nil等。当它被control-c中断时,它会在我的机器中返回nil," signal",2。
底线,试试这段代码:
while true do
print("HELLO!")
if not os.execute("sleep 3") then break end
end
答案 1 :(得分:2)
你的 sleep 孩子被终端的SIGINT杀死,但os.execute
忽略了信号,因此 lua 继续循环。
您的终端驱动程序将 Ctrl + C 转换为为前台进程组生成的SIGINT,其中包括(至少)您的 lua 进程和它的孩子睡眠过程。
(当 lua 脚本位于os.execute
内时,极有可能产生此信号,因为这是脚本花费大部分时间的地方。)
当发生这种情况时, sleep 进程会立即被SIGINT杀死。但是, lua 进程会忽略该信号。
它会忽略SIGINT,因为os.execute
是传统库调用system
的包装器,正如您所见in the source:
static int os_execute (lua_State *L) {
const char *cmd = luaL_optstring(L, 1, NULL);
int stat = system(cmd); /* <<<<<<<<<<<<<<< here <<<<<<<<<<<<< */
if (cmd != NULL)
return luaL_execresult(L, stat);
else {
lua_pushboolean(L, stat); /* true if there is a shell */
return 1;
}
}
此库调用具有非常特定的语义,包括忽略调用者中的SIGINT。