sysutils/check_reload_status: Handle socket closure correctly. Fixes #14386

In adverse conditions it is possible that php-fpm can actually close a
connection from an instance of fcgi-cli and not send a respone at all. This was
not handled correctly by the recv loops, which did not recognize the return
value 0 on the blocking socket as a closed socket condition. If php-fpm closes
the socket prematurely because it is out of resources or hits some other error
condition while fcgicli is trying to read a response, this can make it loop
indefinitely.

Additionally, if read_packet returns a buffer but the header type is not
identifiable, the program goes back into another iteration of the reading loop
where again the socket may be closed and read_packet loops trying to read the
eight byte header.

To remedy the problem, the header and body loops are changed to recognize a recv
result of 0 as an error condition and drop out returning an NULL buffer
pointer. Additionally, the main program loop is changed to bail out if it
receives a packet with a header type that is not recognized.
This commit is contained in:
Reid Linnemann
2024-02-08 11:16:35 -07:00
parent 968c267ae8
commit c0a12f594b
2 changed files with 9 additions and 6 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
# $FreeBSD$
PORTNAME= check_reload_status
PORTVERSION= 0.0.15
PORTVERSION= 0.0.16
CATEGORIES?= sysutils
MASTER_SITES= # empty
DISTFILES= # none
+8 -5
View File
@@ -90,9 +90,9 @@ read_packet(FCGI_Header *header, int sockfd)
while (read < len) {
ssize_t r_read = recv(sockfd, header + read, len - read, 0);
if (r_read >= 0) {
if (r_read > 0) {
read += r_read;
} else if (errno != EINTR){
} else if (errno != EINTR || r_read == 0){
printf("Failed to read %zd header bytes: %s\n",
(ssize_t)len - read, strerror(errno));
goto out;
@@ -119,9 +119,9 @@ read_packet(FCGI_Header *header, int sockfd)
read = 0;
while (read < len) {
ssize_t r_read = recv(sockfd, buf + read, len - read, 0);
if (r_read >= 0) {
if (r_read > 0) {
read += r_read;
} else if (errno != EINTR){
} else if (errno != EINTR || r_read == 0){
printf("Failed to read %zd payload bytes: %s\n",
(ssize_t)len - read, strerror(errno));
free(buf);
@@ -358,7 +358,10 @@ main(int argc, char **argv)
goto endprog;
break;
default:
; /*nop*/
printf("Received unexpected header type %u, exiting",
rHeader.type);
goto endprog;
break;
}
} while (rHeader.type != FCGI_END_REQUEST);