我在用Perl编写的Ubuntu上运行一个守护进程,它现在是单线程的。当它启动时,它会执行常见的Proc :: Daemon之类的东西,然后进入一个由布尔值限制的while循环。守护进程启动正常,服务守护进程启动"。但是当我想用"服务守护程序停止"它不会停止。
应该通过使用信号处理程序翻转布尔值来停止:
$SIG{INT} = $SIG{TERM} = $SIG{HUP} = \&signalHandler;
sub signalHandler {
$continue = 0;
}
不幸的是,主循环也有睡眠。所以守护进程在睡眠结束之前不会结束。我希望守护进程立即结束。但我不想设置非常低的睡眠时间。事实上,我希望能够将睡眠时间设置为几个小时,如果它确定应该这样做的话。
这样做的最佳方式是什么?
我在考虑在主循环中调用某种阻塞函数而不是睡眠。在某个线程死亡之前,此阻塞函数不会返回。然后在信号处理程序中,我会简单地杀死那个睡眠线程。这是一个好方法吗?我怎么做到这一点,我以前从未在Perl中做过多线程。
感谢您的帮助
答案 0 :(得分:3)
以下是针对这种情况的解决方法:
1.
在软件开始运行时创建命名管道,例如mkfifo
2.
使用select
系统调用替换sleep
来电(作为替代方案,您可以使用perl包IO::Select
代替select系统调用)。
设置选择以在管道准备好输入时进行监控。
select
允许指定超时,就像睡眠一样。
当超时超时或满足文件条件时,select
调用返回。
3.
如果发生超时,请运行循环的正文代码。如果数据出现在管道上,则终止。
4.
要终止,请将数据发送到命名管道。
答案 1 :(得分:1)
您可以将任何与关机相关的清理移动到它自己的子例程(如果您还没有这样做),并让signalHandler()
调用该清理子,然后只调用exit
。
然后编辑您的开始/停止脚本以发送SIGALRM。 SIGALRM将中断睡眠。如果您的脚本被编辑以捕获它,那么一切都将立即停止。
进一步阅读:sleep()
答案 2 :(得分:1)
除非你做了一些奇怪的改变,否则sleep()
函数应该提前唤醒并在收到信号时立即返回。然后,您可以在每次睡眠后更改循环以检查$continue
标志,以查看是否收到了关机信号。