Skip to content

Commit 6800fbe

Browse files
committed
fix compatibility with phpredis
* implement a fork helper method that closes the connection to redis before forking (instead of resetting after) to work around bugs with phpredis/socket fork handling * phpredis does not automatically typecast to string, so worker name must be typecasted when registering
1 parent f082ec8 commit 6800fbe

File tree

3 files changed

+31
-39
lines changed

3 files changed

+31
-39
lines changed

bin/resque

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ if(!empty($COUNT) && $COUNT > 1) {
6868

6969
if($count > 1) {
7070
for($i = 0; $i < $count; ++$i) {
71-
$pid = pcntl_fork();
71+
$pid = Resque::fork();
7272
if($pid == -1) {
7373
die("Could not fork worker ".$i."\n");
7474
}

lib/Resque.php

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,6 @@ class Resque
2626
*/
2727
protected static $redisDatabase = 0;
2828

29-
/**
30-
* @var int PID of current process. Used to detect changes when forking
31-
* and implement "thread" safety to avoid race conditions.
32-
*/
33-
protected static $pid = null;
34-
3529
/**
3630
* Given a host/port combination separated by a colon, set it as
3731
* the redis server that Resque will talk to.
@@ -54,15 +48,7 @@ public static function setBackend($server, $database = 0)
5448
*/
5549
public static function redis()
5650
{
57-
// Detect when the PID of the current process has changed (from a fork, etc)
58-
// and force a reconnect to redis.
59-
$pid = getmypid();
60-
if (self::$pid !== $pid) {
61-
self::$redis = null;
62-
self::$pid = $pid;
63-
}
64-
65-
if(!is_null(self::$redis)) {
51+
if (self::$redis !== null) {
6652
return self::$redis;
6753
}
6854

@@ -75,6 +61,33 @@ public static function redis()
7561
return self::$redis;
7662
}
7763

64+
/**
65+
* fork() helper method for php-resque that handles issues PHP socket
66+
* and phpredis have with passing around sockets between child/parent
67+
* processes.
68+
*
69+
* Will close connection to Redis before forking.
70+
*
71+
* @return int Return vars as per pcntl_fork()
72+
*/
73+
public static function fork()
74+
{
75+
if(!function_exists('pcntl_fork')) {
76+
return -1;
77+
}
78+
79+
// Close the connection to Redis before forking.
80+
// This is a workaround for issues phpredis has.
81+
self::$redis = null;
82+
83+
$pid = pcntl_fork();
84+
if($pid === -1) {
85+
throw new RuntimeException('Unable to fork child worker.');
86+
}
87+
88+
return $pid;
89+
}
90+
7891
/**
7992
* Push a job to the end of a specific queue. If the queue does not
8093
* exist, then create it as well.

lib/Resque/Worker.php

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ public function work($interval = 5)
184184
Resque_Event::trigger('beforeFork', $job);
185185
$this->workingOn($job);
186186

187-
$this->child = $this->fork();
187+
$this->child = Resque::fork();
188188

189189
// Forked and we're the child. Run the job.
190190
if ($this->child === 0 || $this->child === false) {
@@ -286,27 +286,6 @@ public function queues($fetch = true)
286286
return $queues;
287287
}
288288

289-
/**
290-
* Attempt to fork a child process from the parent to run a job in.
291-
*
292-
* Return values are those of pcntl_fork().
293-
*
294-
* @return int -1 if the fork failed, 0 for the forked child, the PID of the child for the parent.
295-
*/
296-
private function fork()
297-
{
298-
if(!function_exists('pcntl_fork')) {
299-
return false;
300-
}
301-
302-
$pid = pcntl_fork();
303-
if($pid === -1) {
304-
throw new RuntimeException('Unable to fork child worker.');
305-
}
306-
307-
return $pid;
308-
}
309-
310289
/**
311290
* Perform necessary actions to start a worker.
312291
*/
@@ -474,7 +453,7 @@ public function workerPids()
474453
*/
475454
public function registerWorker()
476455
{
477-
Resque::redis()->sadd('workers', $this);
456+
Resque::redis()->sadd('workers', (string)$this);
478457
Resque::redis()->set('worker:' . (string)$this . ':started', strftime('%a %b %d %H:%M:%S %Z %Y'));
479458
}
480459

0 commit comments

Comments
 (0)