Skip to content

Commit

Permalink
Fix deadlock when issueing a blocking command on a connection that ha…
Browse files Browse the repository at this point in the history
…d a failed blocking command before
  • Loading branch information
brstgt committed Jan 16, 2018
1 parent 08f442d commit 48123ef
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 11 deletions.
19 changes: 8 additions & 11 deletions src/Protocol/Participant.php
Original file line number Diff line number Diff line change
Expand Up @@ -186,18 +186,15 @@ private function sendDeferred(CommandInterface $command, Deferred $deferred, Pro
// - install an error-handler to communicate the failure
if ($lock) {
$this->sendLocked = true;
$lock->then(
function () {
$this->sendLocked = false;
if (!empty($this->sendQueue)) {
list($command, $deferred, $lock) = array_shift($this->sendQueue);
$this->sendDeferred($command, $deferred, $lock);
}
},
function () {
throw new ProtocolException("Blocking operation failed. Protocol is in invalid state");
$doUnlock = function () {
$this->sendLocked = false;
if (!empty($this->sendQueue)) {
list($command, $deferred, $lock) = array_shift($this->sendQueue);
$this->sendDeferred($command, $deferred, $lock);
}
);
};
// Also unlock if previous command failed, otherwise there is a deadlock when issueing a blocked command after a failure
$lock->then($doUnlock, $doUnlock);
}

// write the command
Expand Down
22 changes: 22 additions & 0 deletions tests/ClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,28 @@ public function testSubmitWithLostConnectionAfterWrite()
$this->assertInstanceOf(\Zikarsky\React\Gearman\ConnectionLostException::class, $exception);
}

public function testSubmitAfterLostConnection()
{
$this->connection->expects($this->exactly(2))->method('send')->will($this->returnValue(new FulfilledPromise()));

$this->client->submit('func', 'data');
$this->connection->emit('close');

// Second action must also produce a send call on the connection
$this->client->submit('func', 'data');
}

public function testSubmitAfterLostConnection2()
{
$this->connection->expects($this->exactly(2))->method('send')->will($this->returnValue(new FulfilledPromise()));

$this->client->submit('func', 'data');
// Second action must also produce a send call on the connection
$this->client->submit('func', 'data');

$this->connection->emit('close');
}

public function testSetOption()
{
$confirmed = false;
Expand Down

0 comments on commit 48123ef

Please sign in to comment.