Mic*_*ook 6 php parallel-processing signals daemon upstart
我有一个用PHP编写的守护进程(不是最好的语言,但与我合作),它可以从队列中接收作业,并在需要完成任务时处理它们.对于每个新作业,我使用pcntl_fork()将作业分成一个子进程.在这个子进程中,然后我使用proc_open()来执行长时间运行的系统命令,用于音频转码,完成后直接返回给子进程.完成作业后,子进程将退出并由父进程清理.
为了让这个守护进程始终运行,我使用了暴发.这是我的upstart配置文件:
description "Audio Transcoding Daemon"
start on startup
stop on shutdown
# kill signal SIGCHLD
kill timeout 1200 # Don't force kill the process until it runs over 20 minutes
respawn
exec audio-daemon.php
Run Code Online (Sandbox Code Playgroud)
因为我想在分布式环境中使用这个守护进程,所以我希望能够在不中断任何正在运行的作业的情况下随时关闭服务器.为此,我已经在父进程上使用pcntl_signal()为SIGTERM,SIGHUP和SIGINT 实现了信号处理程序,它等待所有子进程在退出之前正常退出.孩子们也有信号处理程序,但他们会忽略所有杀戮信号.
问题是,根据文件 ......
kill信号节指定的信号被发送到主进程的进程组.(这样就可以杀死属于作业主进程的所有进程).默认情况下,此信号为SIGTERM.
这是令人担忧的,因为在我的子进程中,我通过proc_open()运行系统命令,它也生成新的子进程.因此,每当我运行时sudo stop audio-daemon,这个子进程(恰好是sox)会立即被终止,并且作业返回时会返回错误.显然,sox服从SIGTERM并按照它所说的去做......
最初,我想,"好吧.我只是改变kill signal发送一些本来就被忽略的东西,我只会在主流程中把它拿起来." 但根据手册,默认情况下只有两个信号被忽略:SIGCHLD和SIGURG(可能还有SIGWINCH).但我害怕得到假旗,因为这些也可以通过其他方式触发.
有一些方法可以使用手动调用"实时信号" 来创建自定义信号,但它也说明......
未处理的实时信号的默认操作是终止接收过程.
所以这没有帮助......
您是否可以想到任何方式可以让我的所有子流程在完成之前保持开放状态?我真的不想去挖掘sox的源代码来修改它的信号处理程序,虽然我可以设置SIGCHLD,SIGURG或SIGWINCH作为我的暴发终止信号并祈祷没有别的东西发送给我,我忍不住认为有更好的方法来做到这一点......任何想法?
感谢你的帮助!:)
由于我没有收到任何其他关于如何更好地做到这一点的答案,这就是我最终做的,我希望它可以帮助那里的人......
为了在守护进程完成之前停止系统的关闭/重新启动,我更改了我的start on和stop on新贵配置。为了防止暴发户杀死我的孩子,我使用 SIGURG 作为我的kill signal,然后我只在我的主守护进程中将其作为终止信号捕获。
这是我的最终新贵配置:
description "Audio Transcoding Daemon"
start on runlevel [2345]
stop on starting rc RUNLEVEL=[016] # Block shutdown/reboot until the daemon ends
kill signal SIGURG # Kill the process group with SIGURG instead of SIGTERM so only the main process will pick it up (since SIGURG will be ignored by all children by default)
kill timeout 1200 # Don't force kill the process until it runs over 20 minutes
respawn
exec audio-daemon.php
Run Code Online (Sandbox Code Playgroud)
请注意,需要使用stop on starting rc RUNLEVEL=[016]来停止关机/重启。stop on runlevel [016]不管用。
另请注意,如果出于任何其他原因在应用程序中使用 SIGURG,将其用作终止信号可能会导致问题。就我而言,我不是,所以据我所知,这很好用。
理想情况下,如果 POSIX 标准提供一个用户定义的信号,如 SIGUSR1 和 SIGUSR2,默认情况下会被忽略,那就太好了。但现在,它似乎不存在。
如果您有更好的答案,请随时加入,但就目前而言,我希望这可以帮助其他遇到此问题的人。