Skip to content

Commit 73cd95d

Browse files
committed
Fix bug #76922: FastCGI terminates conn after FCGI_GET_VALUES
1 parent 5df291e commit 73cd95d

File tree

4 files changed

+127
-8
lines changed

4 files changed

+127
-8
lines changed

main/fastcgi.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,7 +1202,7 @@ static int fcgi_read_request(fcgi_request *req)
12021202
req->keep = 0;
12031203
return 0;
12041204
}
1205-
return 0;
1205+
return 2;
12061206
} else {
12071207
return 0;
12081208
}
@@ -1470,7 +1470,8 @@ int fcgi_accept_request(fcgi_request *req)
14701470
return -1;
14711471
}
14721472
req->hook.on_read();
1473-
if (fcgi_read_request(req)) {
1473+
int read_result = fcgi_read_request(req);
1474+
if (read_result == 1) {
14741475
#ifdef _WIN32
14751476
if (is_impersonate && !req->tcp) {
14761477
pipe = (HANDLE)_get_osfhandle(req->fd);
@@ -1481,7 +1482,7 @@ int fcgi_accept_request(fcgi_request *req)
14811482
}
14821483
#endif
14831484
return req->fd;
1484-
} else {
1485+
} else if (read_result == 0) {
14851486
fcgi_close(req, 1, 1);
14861487
}
14871488
}

sapi/fpm/tests/fcgi.inc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,9 @@ class Client
6060
const OVERLOADED = 2;
6161
const UNKNOWN_ROLE = 3;
6262

63-
const MAX_CONNS = 'MAX_CONNS';
64-
const MAX_REQS = 'MAX_REQS';
65-
const MPXS_CONNS = 'MPXS_CONNS';
63+
const MAX_CONNS = 'FCGI_MAX_CONNS';
64+
const MAX_REQS = 'FCGI_MAX_REQS';
65+
const MPXS_CONNS = 'FCGI_MPXS_CONNS';
6666

6767
const HEADER_LEN = 8;
6868

@@ -454,8 +454,8 @@ class Client
454454
fwrite($this->_sock, $this->buildPacket(self::GET_VALUES, $request, 0));
455455

456456
$resp = $this->readPacket();
457-
if ($resp['type'] == self::GET_VALUES_RESULT) {
458-
return $this->readNvpair($resp['content'], $resp['length']);
457+
if (isset($resp['type']) && $resp['type'] == self::GET_VALUES_RESULT) {
458+
return $this->readNvpair($resp['content'], $resp['contentLength']);
459459
} else {
460460
throw new \Exception('Unexpected response type, expecting GET_VALUES_RESULT');
461461
}

sapi/fpm/tests/response.inc

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,3 +434,89 @@ class Response
434434
return false;
435435
}
436436
}
437+
438+
class ValuesResponse
439+
{
440+
/**
441+
* @var array
442+
*/
443+
private array $values;
444+
445+
/**
446+
* @param string|array|null $values
447+
*/
448+
public function __construct($values = null)
449+
{
450+
if ( ! is_array($values)) {
451+
if ( ! is_null($values) ) {
452+
$this->error('Invalid values supplied', true);
453+
}
454+
$this->values = [];
455+
} else {
456+
$this->values = $values;
457+
}
458+
}
459+
460+
/**
461+
* Expect value.
462+
*
463+
* @param string $name
464+
* @param mixed $value
465+
* @return ValuesResponse
466+
*/
467+
public function expectValue(string $name, $value = null)
468+
{
469+
if ( ! isset($this->values[$name])) {
470+
return $this->error("Value $name not found in values");
471+
}
472+
if ( ! is_null($value) && $value !== $this->values[$name]) {
473+
return $this->error("Value $name is {$this->values[$name]} but expected $value");
474+
}
475+
return $this;
476+
}
477+
478+
/**
479+
* Get values.
480+
*
481+
* @return array
482+
*/
483+
public function getValues()
484+
{
485+
return $this->values;
486+
}
487+
488+
/**
489+
* Debug output data.
490+
*
491+
* @return ValuesResponse
492+
*/
493+
public function debugOutput()
494+
{
495+
echo ">>> ValuesResponse\n";
496+
echo "----------------- Values -----------------\n";
497+
var_dump($this->values);
498+
echo "---------------------------------------\n\n";
499+
500+
return $this;
501+
}
502+
503+
/**
504+
* Emit error message
505+
*
506+
* @param string $message
507+
* @param bool $throw
508+
*
509+
* @return ValuesResponse
510+
*/
511+
private function error(string $message, $throw = false): bool
512+
{
513+
$errorMessage = "ERROR: $message\n";
514+
if ($throw) {
515+
throw new \Exception($errorMessage);
516+
}
517+
$this->debugOutput();
518+
echo $errorMessage;
519+
520+
return $this;
521+
}
522+
}

sapi/fpm/tests/tester.inc

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,38 @@ class Tester
858858
}
859859
}
860860

861+
/**
862+
* Execute request for getting FastCGI values.
863+
*
864+
* @param string|null $address
865+
* @param bool $connKeepAlive
866+
*
867+
* @return ValuesResponse
868+
* @throws \Exception
869+
*/
870+
public function requestValues(
871+
string $address = null,
872+
bool $connKeepAlive = false
873+
): ValuesResponse {
874+
if ($this->hasError()) {
875+
return new Response(null, true);
876+
}
877+
878+
try {
879+
$valueResponse = new ValuesResponse(
880+
$this->getClient($address, $connKeepAlive)->getValues(['FCGI_MPXS_CONNS'])
881+
);
882+
if ($this->debug) {
883+
$this->response->debugOutput();
884+
}
885+
} catch (\Exception $exception) {
886+
$this->error("Request for getting values failed", $exception);
887+
$valueResponse = new ValuesResponse();
888+
}
889+
890+
return $valueResponse;
891+
}
892+
861893
/**
862894
* Get client.
863895
*

0 commit comments

Comments
 (0)