Running a PHP process as a daemon while safely killing it from background
daemons, kill-process, php
Solution
I had related problems once too. Let me explain. I had a php 'daemon' that worked like a downloader. It accessed feeds periodically and downloads (laaaarge) content from the net. The daemon had to be stopped at a certain time, lets say 0500 in the morning to prevent it from using the whole bandwith during daytime. I decided to use a cronjob to send SIGTERM to the daemon at 0500.
In the daemon I had the following code:
pcntl_signal(SIGTERM, array($this, 'signal_handler'));
where `signal_handler` looked like this:
public function signal_handler($signal) {
// some cleanup code
exit(1);
}
Unfortunately this did not work :|
It took me a time to find out what's going on. The first thing I figured out was that I'll have to call the method `pcntl_signal_dispatch()` on init to enable signal dispatching at all. Quote from the doc (comments):
If you are running PHP as CLI and as a "daemon" (i.e. in a loop), this function must be called in each loop to check if new signals are waiting dispatching.
Ok, so far, it seemed working. But I realized quickly that under certain conditions even this will not work as expected. Sometimes the daemon could only being stopped by `kill -9` - as before. :|
So what's the problem?.. Answer: My program called `wget` to download the files via `shell_exec`. The problem is, that `shell_exec()` blocking waits until the child process has terminated. During this blocking wait no signal processing is done, the process can only being terminated using SIGKILL - what is hard. Also a problem was that child processes had to be terminated one by one as they became zombie processes after killing the father.
My solution to this was to execute the child process using `proc_open()` and the use `stream_select()` on it's output for non blocking IO.
Now it works like a charm. :) If you need further information don't hesitate to drop a comment.
Note If you are working with PHP < 5.3 then you'll have to use `
declare(ticks=1);
instead of `pcntl_signal_dispatch()`. You can rfer to the the documentation of `pcntl_signal()` for that. But if possible you should upgrade to PHP >= 5.3
Problem
We are running a PHP Daemon which look into a queue, receives worker jobs and spawns the worker to handle it. The workers themselves acquire a lock on a specific location before proceeding. We spawn the Daemon as nohup background processes. This entire architecture seems to work, except when we have to kill the processes, for whatever reason. If we kill them using -9, there is no way to trap it in the worker process and release the locks before dying. If we use anything less than -9 (like TERM or HUP), it doesn't seem to be received by either the daemon or the worker processes. Has anybody solved this problem in a better way? (ps: BTW, Due to other considerations, we may not be able to change our language of implementation, so please only consider PHP based solutions)