From 58c7700bae2c12a56d789c8496c4bc6558d145cb Mon Sep 17 00:00:00 2001 From: Justin Persaud Date: Mon, 20 Oct 2025 15:13:24 -0400 Subject: [PATCH 1/7] Log local port being used to open socket --- src/Client.php | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/src/Client.php b/src/Client.php index f01679a..574db12 100644 --- a/src/Client.php +++ b/src/Client.php @@ -595,12 +595,49 @@ private function sendRawRequest(string $host, int $port, string $rawRequest) if ($selectResult === false) { $socketError = socket_strerror(socket_last_error($this->socket)); + // Attempt to get local socket information for debugging + $localAddress = ''; + $localPort = 0; + if (socket_getsockname($this->socket, $localAddress, $localPort)) { + $this->logger->error('Bedrock\Client - socket_select failed', [ + 'localAddress' => $localAddress, + 'localPort' => $localPort, + 'remoteHost' => $host, + 'remotePort' => $port, + 'error' => $socketError, + ]); + } throw new ConnectionFailure("socket_select failed after EINPROGRESS for $host:$port. Error: $socketError"); } elseif ($selectResult === 0) { + // Attempt to get local socket information for debugging + $localAddress = ''; + $localPort = 0; + if (socket_getsockname($this->socket, $localAddress, $localPort)) { + $this->logger->error('Bedrock\Client - Socket timeout after EINPROGRESS', [ + 'localAddress' => $localAddress, + 'localPort' => $localPort, + 'remoteHost' => $host, + 'remotePort' => $port, + 'timeoutSeconds' => $this->connectionTimeout, + ]); + } throw new ConnectionFailure("Socket not ready for writing within timeout after EINPROGRESS for $host:$port"); } elseif (empty($write)) { $socketErrorCode = socket_last_error($this->socket); $socketError = socket_strerror($socketErrorCode); + // Attempt to get local socket information for debugging + $localAddress = ''; + $localPort = 0; + if (socket_getsockname($this->socket, $localAddress, $localPort)) { + $this->logger->error('Bedrock\Client - Socket error after EINPROGRESS', [ + 'localAddress' => $localAddress, + 'localPort' => $localPort, + 'remoteHost' => $host, + 'remotePort' => $port, + 'errorCode' => $socketErrorCode, + 'error' => $socketError, + ]); + } throw new ConnectionFailure("Socket had error after EINPROGRESS for $host:$port. Error: $socketErrorCode $socketError"); } @@ -617,8 +654,33 @@ private function sendRawRequest(string $host, int $port, string $rawRequest) ]); } elseif ($socketErrorCode) { $socketError = socket_strerror($socketErrorCode); + // Attempt to get local socket information for debugging + $localAddress = ''; + $localPort = 0; + if (socket_getsockname($this->socket, $localAddress, $localPort)) { + $this->logger->error('Bedrock\Client - Connection failed', [ + 'localAddress' => $localAddress, + 'localPort' => $localPort, + 'remoteHost' => $host, + 'remotePort' => $port, + 'errorCode' => $socketErrorCode, + 'error' => $socketError, + ]); + } throw new ConnectionFailure("Could not connect to Bedrock host $host:$port. Error: $socketErrorCode $socketError"); } + + // Log the local port assigned to this socket connection + $localAddress = ''; + $localPort = 0; + if (socket_getsockname($this->socket, $localAddress, $localPort)) { + $this->logger->info('Bedrock\Client - Socket connection established', [ + 'localAddress' => $localAddress, + 'localPort' => $localPort, + 'remoteHost' => $host, + 'remotePort' => $port, + ]); + } } else { $this->logger->info('Bedrock\Client - Reusing socket', ['host' => $host, 'cluster' => $this->clusterName, 'pid' => $pid]); } From ce30879ade2c334b8766bca04bc1a732e9e953e7 Mon Sep 17 00:00:00 2001 From: Justin Persaud Date: Mon, 20 Oct 2025 16:05:07 -0400 Subject: [PATCH 2/7] Only log where necessary --- src/Client.php | 74 ++++++++------------------------------------------ 1 file changed, 12 insertions(+), 62 deletions(-) diff --git a/src/Client.php b/src/Client.php index 574db12..9b4911d 100644 --- a/src/Client.php +++ b/src/Client.php @@ -577,6 +577,12 @@ private function sendRawRequest(string $host, int $port, string $rawRequest) @socket_connect($this->socket, $host, $port); $connectTime = (microtime(true) - $connectStart) * 1000; $socketErrorCode = socket_last_error($this->socket); + + // Get local socket information for logging (available after socket_connect call) + $localAddress = ''; + $localPort = 0; + socket_getsockname($this->socket, $localAddress, $localPort); + if ($socketErrorCode === 115) { $this->logger->info('Bedrock\Client - socket_connect returned error 115, waiting for connection to complete.', [ 'host' => $host, @@ -595,49 +601,18 @@ private function sendRawRequest(string $host, int $port, string $rawRequest) if ($selectResult === false) { $socketError = socket_strerror(socket_last_error($this->socket)); - // Attempt to get local socket information for debugging - $localAddress = ''; - $localPort = 0; - if (socket_getsockname($this->socket, $localAddress, $localPort)) { - $this->logger->error('Bedrock\Client - socket_select failed', [ - 'localAddress' => $localAddress, - 'localPort' => $localPort, - 'remoteHost' => $host, - 'remotePort' => $port, - 'error' => $socketError, - ]); - } throw new ConnectionFailure("socket_select failed after EINPROGRESS for $host:$port. Error: $socketError"); } elseif ($selectResult === 0) { - // Attempt to get local socket information for debugging - $localAddress = ''; - $localPort = 0; - if (socket_getsockname($this->socket, $localAddress, $localPort)) { - $this->logger->error('Bedrock\Client - Socket timeout after EINPROGRESS', [ - 'localAddress' => $localAddress, - 'localPort' => $localPort, - 'remoteHost' => $host, - 'remotePort' => $port, - 'timeoutSeconds' => $this->connectionTimeout, - ]); - } + $this->logger->error('Bedrock\Client - Socket timeout after EINPROGRESS', [ + 'localAddress' => $localAddress, + 'localPort' => $localPort, + 'remoteHost' => $host, + 'remotePort' => $port, + ]); throw new ConnectionFailure("Socket not ready for writing within timeout after EINPROGRESS for $host:$port"); } elseif (empty($write)) { $socketErrorCode = socket_last_error($this->socket); $socketError = socket_strerror($socketErrorCode); - // Attempt to get local socket information for debugging - $localAddress = ''; - $localPort = 0; - if (socket_getsockname($this->socket, $localAddress, $localPort)) { - $this->logger->error('Bedrock\Client - Socket error after EINPROGRESS', [ - 'localAddress' => $localAddress, - 'localPort' => $localPort, - 'remoteHost' => $host, - 'remotePort' => $port, - 'errorCode' => $socketErrorCode, - 'error' => $socketError, - ]); - } throw new ConnectionFailure("Socket had error after EINPROGRESS for $host:$port. Error: $socketErrorCode $socketError"); } @@ -654,33 +629,8 @@ private function sendRawRequest(string $host, int $port, string $rawRequest) ]); } elseif ($socketErrorCode) { $socketError = socket_strerror($socketErrorCode); - // Attempt to get local socket information for debugging - $localAddress = ''; - $localPort = 0; - if (socket_getsockname($this->socket, $localAddress, $localPort)) { - $this->logger->error('Bedrock\Client - Connection failed', [ - 'localAddress' => $localAddress, - 'localPort' => $localPort, - 'remoteHost' => $host, - 'remotePort' => $port, - 'errorCode' => $socketErrorCode, - 'error' => $socketError, - ]); - } throw new ConnectionFailure("Could not connect to Bedrock host $host:$port. Error: $socketErrorCode $socketError"); } - - // Log the local port assigned to this socket connection - $localAddress = ''; - $localPort = 0; - if (socket_getsockname($this->socket, $localAddress, $localPort)) { - $this->logger->info('Bedrock\Client - Socket connection established', [ - 'localAddress' => $localAddress, - 'localPort' => $localPort, - 'remoteHost' => $host, - 'remotePort' => $port, - ]); - } } else { $this->logger->info('Bedrock\Client - Reusing socket', ['host' => $host, 'cluster' => $this->clusterName, 'pid' => $pid]); } From 278debe123a72127e0b372a8cd20df50447e38fb Mon Sep 17 00:00:00 2001 From: Justin Persaud Date: Mon, 20 Oct 2025 16:07:57 -0400 Subject: [PATCH 3/7] log pending error --- src/Client.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Client.php b/src/Client.php index 9b4911d..c0bd0d8 100644 --- a/src/Client.php +++ b/src/Client.php @@ -603,11 +603,17 @@ private function sendRawRequest(string $host, int $port, string $rawRequest) $socketError = socket_strerror(socket_last_error($this->socket)); throw new ConnectionFailure("socket_select failed after EINPROGRESS for $host:$port. Error: $socketError"); } elseif ($selectResult === 0) { + // Check if there's a pending error on the socket that might explain the timeout + $pendingError = socket_get_option($this->socket, SOL_SOCKET, SO_ERROR); + $pendingErrorStr = $pendingError ? socket_strerror($pendingError) : 'none'; + $this->logger->error('Bedrock\Client - Socket timeout after EINPROGRESS', [ 'localAddress' => $localAddress, 'localPort' => $localPort, 'remoteHost' => $host, 'remotePort' => $port, + 'pendingErrorCode' => $pendingError, + 'pendingError' => $pendingErrorStr, ]); throw new ConnectionFailure("Socket not ready for writing within timeout after EINPROGRESS for $host:$port"); } elseif (empty($write)) { From 0db31a1c71db2249d3f429a583841d3df2e648f9 Mon Sep 17 00:00:00 2001 From: Justin Persaud Date: Mon, 20 Oct 2025 16:10:10 -0400 Subject: [PATCH 4/7] lock socket buffer info --- src/Client.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Client.php b/src/Client.php index c0bd0d8..cf88c96 100644 --- a/src/Client.php +++ b/src/Client.php @@ -607,6 +607,10 @@ private function sendRawRequest(string $host, int $port, string $rawRequest) $pendingError = socket_get_option($this->socket, SOL_SOCKET, SO_ERROR); $pendingErrorStr = $pendingError ? socket_strerror($pendingError) : 'none'; + // Get socket buffer sizes to check for misconfigurations + $sendBufferSize = socket_get_option($this->socket, SOL_SOCKET, SO_SNDBUF); + $receiveBufferSize = socket_get_option($this->socket, SOL_SOCKET, SO_RCVBUF); + $this->logger->error('Bedrock\Client - Socket timeout after EINPROGRESS', [ 'localAddress' => $localAddress, 'localPort' => $localPort, @@ -614,6 +618,8 @@ private function sendRawRequest(string $host, int $port, string $rawRequest) 'remotePort' => $port, 'pendingErrorCode' => $pendingError, 'pendingError' => $pendingErrorStr, + 'sendBufferSize' => $sendBufferSize, + 'receiveBufferSize' => $receiveBufferSize, ]); throw new ConnectionFailure("Socket not ready for writing within timeout after EINPROGRESS for $host:$port"); } elseif (empty($write)) { From 97de988fac4809ef0a1d62864e265efe449cd7b6 Mon Sep 17 00:00:00 2001 From: Justin Persaud Date: Mon, 20 Oct 2025 16:11:07 -0400 Subject: [PATCH 5/7] tag with 2.2.7 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 2cbc0f1..9937145 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "expensify/bedrock-php", "description": "Bedrock PHP Library", "type": "library", - "version": "2.2.6", + "version": "2.2.7", "authors": [ { "name": "Expensify", From a2e7171851d46697d2eb7d5fb2b7e8d99ebd3e9d Mon Sep 17 00:00:00 2001 From: Justin Persaud Date: Mon, 20 Oct 2025 16:17:05 -0400 Subject: [PATCH 6/7] remove whitespace --- src/Client.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Client.php b/src/Client.php index cf88c96..51d7b15 100644 --- a/src/Client.php +++ b/src/Client.php @@ -577,12 +577,12 @@ private function sendRawRequest(string $host, int $port, string $rawRequest) @socket_connect($this->socket, $host, $port); $connectTime = (microtime(true) - $connectStart) * 1000; $socketErrorCode = socket_last_error($this->socket); - + // Get local socket information for logging (available after socket_connect call) $localAddress = ''; $localPort = 0; socket_getsockname($this->socket, $localAddress, $localPort); - + if ($socketErrorCode === 115) { $this->logger->info('Bedrock\Client - socket_connect returned error 115, waiting for connection to complete.', [ 'host' => $host, @@ -606,11 +606,11 @@ private function sendRawRequest(string $host, int $port, string $rawRequest) // Check if there's a pending error on the socket that might explain the timeout $pendingError = socket_get_option($this->socket, SOL_SOCKET, SO_ERROR); $pendingErrorStr = $pendingError ? socket_strerror($pendingError) : 'none'; - + // Get socket buffer sizes to check for misconfigurations $sendBufferSize = socket_get_option($this->socket, SOL_SOCKET, SO_SNDBUF); $receiveBufferSize = socket_get_option($this->socket, SOL_SOCKET, SO_RCVBUF); - + $this->logger->error('Bedrock\Client - Socket timeout after EINPROGRESS', [ 'localAddress' => $localAddress, 'localPort' => $localPort, From a016010624aab535abd3f3484539d58c8d2e6e26 Mon Sep 17 00:00:00 2001 From: Justin Persaud Date: Mon, 20 Oct 2025 16:23:02 -0400 Subject: [PATCH 7/7] change to info --- src/Client.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Client.php b/src/Client.php index 51d7b15..6182162 100644 --- a/src/Client.php +++ b/src/Client.php @@ -611,7 +611,7 @@ private function sendRawRequest(string $host, int $port, string $rawRequest) $sendBufferSize = socket_get_option($this->socket, SOL_SOCKET, SO_SNDBUF); $receiveBufferSize = socket_get_option($this->socket, SOL_SOCKET, SO_RCVBUF); - $this->logger->error('Bedrock\Client - Socket timeout after EINPROGRESS', [ + $this->logger->info('Bedrock\Client - Socket timeout after EINPROGRESS', [ 'localAddress' => $localAddress, 'localPort' => $localPort, 'remoteHost' => $host,