udokmeci/yii2-beanstalk

PHP7 signal handler

rtilte-reol opened this issue · 4 comments

Hi,

Stopping workers with Ctrl+C stopped working with PHP7. It looks like the behavior of declare (ticks = 1); changed a bit. I'm trying to find out what needs to be changed and will PR as soon as I find something, but maybe you already know how to solve the issue.

I still didn't figure out what the issue is with PHP7, but we can use reserve-with-timeout instead of reserve in your code, in BeanstalkController, #307

$job = $bean->reserve(1);

Hi, I have checkout the document but there is nothing about the change of behavior in ticks other than using constants.

So what is the exact issue can you post an output here?
Bests,

Thanks for the reply,

There's actually no output at all, Ctrl+C does not stop the worker at all, it's "frozen" in the reserve() mode and waits for tube to be populated before returning to the script. It looks like the issue is really coming from PHP7 and the way they deal with signals. By adding a timeout to reserve, script goes back into the while loop after the timeout to check what happened and actually "sees" the signal only at that moment.

I cannot really explain more what happens, but I can give steps to reproduce the issue (or similar issue actually):

  1. Get a VM with whatever distro you want and a working PHP7 setup (Ubuntu 16.04 is using PHP7 by default)
  2. Copy / paste the following script:
<?php
declare(ticks = 1);

pcntl_signal(SIGTERM, 'signal_handler');
pcntl_signal(SIGINT, 'signal_handler');


function signal_handler($signal)
{
    switch ($signal) {
        case SIGTERM:
            print "Caught SIGTERM\n";
            exit;
        case SIGKILL:
            print "Caught SIGKILL\n";
            exit;
        case SIGINT:
            print "Caught SIGINT\n";
            exit;
    }
}

while (1) {
    //usleep(100);
}

Try to kill the script with Ctrl+C and see that it does not work, even with ticks declared. Process gets stucked in the while loop forever. To kill it, you have to

ps aux | grep SCRIPT_NAME
kill -9 PROCESS_PID

Note: You need to kill -9, even a single kill PROCESS_PID will not get rid of it.

Now if you uncomment the usleep() portion, Ctrl+C will strop the script because it checks what it has to do before the next loop, and catches the signal at that moment. You can add pretty much anything there ($a = 1) but the script needs to do something in the loop. This behavior does not exists in PHP5.

With reserve(), it just waits for something to come in the tube, and will hang forever in case nothing comes in.

In any case, I think it's fairly easy to setup some params in the config to indicate the default timeout and use reserve with timeout, just in case. If you think this issue is not relevant, I'll just override the function as I see the need, and will appreciate your feedback.

I can confirm this behaviour since the upgrade to PHP7.