Running a PHP process as a daemon that safely kills it from the background

We run PHP-Daemon, which looks in line, receives work orders and spawns a worker to process it. Workers themselves acquire a castle in a specific place before proceeding.

We create Daemon as nohup background processes.

All this architecture works, unless we have to kill processes for any reason. If we kill them with -9, there is no way to lure him into a workflow and release the locks before they die.

If we use anything less than -9 (for example, TERM or HUP), it does not seem to be accepted by either daemons or workflows.

Has anyone better solved this problem?

(ps: BTW. Due to other considerations, we will not be able to change our implementation language, so please consider only PHP-based solutions)

+4
source share
3 answers

I had related problems too. Let me explain. I had php 'daemon' that worked as a bootloader. He periodically accessed the channels and downloaded (laaaarge) content from the network. The demon had to be stopped at a specific time, say 0500 in the morning, so that it would not use the entire tape in the daytime. I decided to use cronjob to send the SIGTERM daemon to 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 while to find out what was going on. The first thing I realized was that I would need to call the pcntl_signal_dispatch() method in init to generally allow sending signals. Quote from the doc doc ( comments ):

If you use PHP as a CLI and as a "daemon" (that is, in a loop), this function should be called in each loop to check if new send signals are waiting.

Ok, so long as it worked. But I quickly realized that under certain conditions even this would not work as expected. Sometimes the daemon could only be stopped by kill -9 - as before .: |

So what's the problem? .. Answer: My program called wget for downloading files via shell_exec . The problem is that the shell_exec() lock is waiting for the child process to complete. During this blocking wait, signal processing is not performed, the process can only be stopped using SIGKILL - which is difficult. Also, the problem was that the child processes had to be stopped one after another, as they became zombie processes after the murder of the father.

My solution was to execute the child process using proc_open() and use stream_select() to output for non-blocking I / O.

Now it works like a charm. :) If you need more information, feel free to leave a comment.


Note. If you are working with PHP <5.3, you will have to use `

 declare(ticks=1); 

instead of pcntl_signal_dispatch() . For this, you can refer to the pcntl_signal() documentation. But if possible, you should upgrade to PHP> = 5.3

+3
source

The problem was solved only by adding ticks:

 // tick use required as of PHP 4.3.0 declare(ticks = 1); 

Leaving this alone, my code did not work.

* (Unfortunately, the pcntl_signal documentation does not mention this in much greater attention.) *

+1
source

You need to catch the signal (SIGTERM). This can be achieved using the pcntl_signal function. This will give you the opportunity to perform any necessary functions before calling exit.

0
source

All Articles