php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #64972 Can't use signal handlers in gearman work loop
Submitted: 2013-06-04 21:18 UTC Modified: 2017-01-10 08:23 UTC
From: gauthierm@php.net Assigned:
Status: Suspended Package: gearman (PECL)
PHP Version: 5.3.25 OS: Linux (CentOS)
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: gauthierm@php.net
New email:
PHP Version: OS:

 

 [2013-06-04 21:18 UTC] gauthierm@php.net
Description:
------------
I'd like to be able to safely shut down gearman workers by sending the SIGTERM 
signal. I want to either re-queueing or finish the current job before exiting. 
Using the PHP process control extension to set up a signal handler doesn't work 
when the gearman work loop is running.

If signal handlers are assigned, they are never called during the work loop and 
the process can not be ended except for SIGKILL.

If no signal handlers are assigned, SIGTERM and SIGINT work as expected during the 
work loop.

Test script:
---------------
<?php

define(ticks = 1);

function handle($signal) {
  // shutdown safely
  exit();
}
pcntl_signal(SIGTERM, 'handle');

$worker = new GearmanWorker();
// set up worker stuff here
while ($worker->work());

Expected result:
----------------
When SIGTERM is sent to the process, the signal handler should be called.

Actual result:
--------------
When SIGTERM is sent to the process, nothing happens. The process runs forever 
until SIGKILL is sent.

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2013-06-20 13:51 UTC] alexis dot peter at cargomedia dot ch
This actually doesn't have anything to do with gearman. The problem is that loops 
block custom signal handlers. The only solution I know of is to call 
pcntl_signal_dispatch(); whithin your loop.
Try replacing your loop with something like this:
---------
while (true) {
  pcntl_signal_dispatch()
  $worker->work();
}
 [2013-06-20 14:48 UTC] gauthierm@php.net
I looked into this further.

Loops in PHP don't block signal handlers when using ticks=1 but the gearman wait 
loop is handled in libgearman instead of PHP code.

See https://bugs.launchpad.net/gearmand/+bug/1083395 and 
https://bugs.php.net/bug.php?id=63647

The workaround is to set a timeout on the GearmanWorker and use pnctl_dispatch() 
inside the PHP loop. It's non optimal because it switches context on every 
timeout, and there is latency receiving the signals in PHP.

Ideally, what would happen is:

 1. set no timeout
 2. PHP calls GearmanWorker::work()
 3. libgearman enters its wait loop
 4. if libgearman receives a signal inside the wait loop, it returns
 5. PHP is able to handle the signal immediately

Unfortunately it doesn't look like libgearman does this.
 [2013-07-26 07:07 UTC] janne dot enberg at lietu dot net
First of all, it's declare(ticks = 1); .. not define();

Secondly, set $worker->addOptions(GEARMAN_WORKER_NON_BLOCKING); and refactor your 
code to work with it (check for return values of $worker->returnCode()).

Thirdly, use register_tick_function() to register a function that calls 
pcntl_signal.

With these changes it should be possible to accomplish what you want.
 [2013-07-26 15:07 UTC] gauthierm@php.net
I can refactor my code to be non-blocking and set the timeout for gearman to be 1 
second. This is not ideal because it means if I hit ctrl+c it can take a second 
for the process to end. If I reduce the timeout then the CPU usage of idle workers 
goes up.
 [2017-01-10 08:23 UTC] kalle@php.net
-Status: Open +Status: Suspended
 [2017-01-10 08:23 UTC] kalle@php.net
The gearman extension have not had much activity in the past few years, so I'm taking the safe bet that this is no longer under active development (as I don't consider the typo fixes on the github repo an active development), besides that it also targets unsupported PHP versions. Please unsuspend this report in case it begins to blossom with life once more
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 13:01:31 2024 UTC