Andrea Rossi
Andrea Rossi

Reputation: 1071

PHP 5.6 signal handling: declare(ticks=1) vs pcntl_signal_dispatch()

I'm writing a daemon in PHP 5.6. So far, it is basically a Daemon class with a mainLoop() method that has an infinite loop. In each iteration, the mainLoop executes a series of steps.

I need it to implement a "graceful kill" mechanism: if a SIGINT or SIGTERM arrive, the daemon must complete the current step of the current iteration before dying.

My idea is to use a static variable Daemon::CONTINUE TRUE by default; when a SIGINT or SIGTERM arrives, it is set to FALSE. In each iteration, before passing to the next step the daemon checks if self::CONTINUE has switched to FALSE and, if it has, it returns.

I know that the way to do this is to use pcntl_signal. It seems that I can either use it with declare(ticks=1) or with pcntl_signal_dispatch(), but I'm not sure about the difference.

Does declare(ticks=1) make the process check for the arrival of signals after each tick, whereas pcntl_signal_dispatch() explicitly checks the signals only when I call it?

These are snippets of the two ways I described before. Are they both correct? Which one should I use?

Way 1

<?php
declare(ticks=1) {
   pcntl_signal(SIGINT, function($signo) {Daemon::CONTINUE = FALSE;});
   pcntl_signal(SIGTERM, function($signo) {Daemon::CONTINUE = FALSE;});
}

public class Daemon {
   public static $CONTINUE = TRUE;

   function mainLoop() {
      ...
      if (self::CONTINUE === FALSE)
        return;
      ...
   }
}

Way 2

<?php

pcntl_signal(SIGINT, function($signo) {Daemon::CONTINUE = FALSE;});
pcntl_signal(SIGTERM, function($signo) {Daemon::CONTINUE = FALSE;});

public class Daemon {
   public static $CONTINUE = TRUE;

   function mainLoop() {
      ...
      pcntl_signal_dispatch();
      if (self::CONTINUE === FALSE)
        return;
      ...
   }
}

Thanks for your support.

Upvotes: 2

Views: 930

Answers (1)

Andrea Rossi
Andrea Rossi

Reputation: 1071

Ok, after some testing and debugging I tried both solutions. I'll leave here my observations in case somebody encounters my same issues.

It seems that the way 1 with declare(ticks=1) does not work; I can not understand why.
The way 2 with pcntl_signal_dispatch(), on the contrary, seems to work nice.

After deeper research, I think that the way 2 is the best one for my case anyway.
In fact, declare(tick=1), if it worked, would run the pcntl_signal on each tick, roughly corresponding to the execution of each code line. This can potentially degradate the performances.

On the contrary, apparently pcntl_signal_dispatch) just handles pending signals when it is called, so it should be lighter on performances.

Upvotes: 2

Related Questions