Skip to content

Commit c6b5c0c

Browse files
committed
Fix race condition during server shutdown + server restart
1 parent a5b3a18 commit c6b5c0c

File tree

4 files changed

+20
-3
lines changed

4 files changed

+20
-3
lines changed

lib/CommandClient.php

+4
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ public function stop(): Promise {
9898
return $this->send(["action" => "stop"]);
9999
}
100100

101+
public function started(): Promise {
102+
return $this->send(["action" => "started"]);
103+
}
104+
101105
public function importServerSockets($addrCtxMap): Promise {
102106
return call(function () use ($addrCtxMap) {
103107
$reply = yield $this->send(["action" => "import-sockets", "addrCtxMap" => array_map(function ($context) { return $context["socket"]; }, $addrCtxMap)]);

lib/Server.php

+6
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,12 @@ private function doStop(): \Generator {
417417
assert($this->logDebug("stopping"));
418418
$this->state = self::STOPPING;
419419

420+
// Unbind server sockets, otherwise connections are still sent to bound sockets but never accepted
421+
// In restart situation that can lead to unnecessary request errors
422+
foreach ($this->boundServers as $server) {
423+
fclose($server);
424+
}
425+
420426
foreach ($this->acceptWatcherIds as $watcherId) {
421427
Loop::cancel($watcherId);
422428
}

lib/WatcherProcess.php

+8-3
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,13 @@ private function readCommand(Socket $client): \Generator {
207207
case "import-sockets":
208208
yield from $this->parseWorkerAddrCtx($client, $message["addrCtxMap"]);
209209
break;
210+
211+
case "started":
212+
$this->logger->info("Worker started");
213+
yield $this->replyCommand($client, []);
214+
assert(!empty($this->spawnDeferreds));
215+
array_shift($this->spawnDeferreds)->resolve();
216+
break;
210217
}
211218
}
212219
}
@@ -396,9 +403,6 @@ private function accept(): \Generator {
396403

397404
$this->ipcClients[\spl_object_hash($client)] = $client;
398405

399-
assert(!empty($this->spawnDeferreds));
400-
array_shift($this->spawnDeferreds)->resolve();
401-
402406
Promise\rethrow(new Coroutine($this->read($client)));
403407
}
404408
}
@@ -496,6 +500,7 @@ public function restart() {
496500
for ($i = 0; $i < $this->workerCount; $i++) {
497501
$spawnPromise = $this->spawn();
498502
$spawnPromise->onResolve(function () {
503+
$this->logger->info("Spawned new worker, stop old worker");
499504
$client = current($this->ipcClients);
500505
next($this->ipcClients);
501506
$client->end(self::STOP_SEQUENCE);

lib/WorkerProcess.php

+2
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,11 @@ protected function doStart(Console $console): \Generator {
6262
}
6363
$this->server = $server;
6464
Loop::unreference(Loop::onReadable($this->ipcSock, function ($watcherId) {
65+
$this->logger->info("Received stop command");
6566
Loop::cancel($watcherId);
6667
yield from $this->stop();
6768
}));
69+
yield (new CommandClient($console->getArg("config")))->started();
6870
}
6971

7072
protected function doStop(): \Generator {

0 commit comments

Comments
 (0)