Bug #80931 [Com]: file_get_contents() hangs on PHP 8

From: Date: Thu, 08 Apr 2021 12:57:23 +0000
Subject: Bug #80931 [Com]: file_get_contents() hangs on PHP 8
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-233313@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=80931&edit=1

 ID:                 80931
 Comment by:         danack@php.net
 Reported by:        gilperon at gmail dot com
 Summary:            file_get_contents() hangs on PHP 8
 Status:             Verified
 Type:               Bug
 Package:            Streams related
 Operating System:   any
 PHP Version:        7.4
 Block user comment: N
 Private report:     N

 New Comment:

Okay, so looking at the packets, what is happening, from the response on is:

# http 1_0 protocol
6. server sends response.
7. php acks 6.
8. server sends finack.
9. php sends finack.
10. servers acks 9.


# http 1_1 protocol
6. server sends response.
7. php acks 10.
8. php sends finack.
9. server acks 8.
10. server sends finack.
11. php acks 10.

That all looks correct, but the difference is that for http 1.1 the client is initiating the
connection close. In http 1.0 the server is intiating the connection close.

All the packets look okay, according to https://gitlab.com/wireshark/wireshark/-/wikis/TCP-4-times-close

The problem seems to be that for whatever reason, after sending the last ack, PHP is sitting around
doing nothing. btw it does time out after 2 * 60 seconds, which probably confirms the socket is in
the appropriate TIME-WAIT status.


Previous Comments:
------------------------------------------------------------------------
[2021-04-08 12:23:56] cmb@php.net

First, this is not a regression in PHP 8.0, but rather a general
issue with HTTP/1.1.  It seems to me the problem is that the
server does *not* close the connection right away after having
sent the response under HTTP/1.1, what appears to be legit
behavior.  After having received the full response, our HTTP stream
implementation still tries to select(2) the sole readfd, but the
server won't send more data, so the timeout occurs.

FWIW, if I add a Connection:keep-alive header to the context
options, I can reproduce the behavior of the server locally.

------------------------------------------------------------------------
[2021-04-07 20:43:12] gilperon at gmail dot com

danack@php.net Respectfully, setting manually the protocol to 1.0 is more like a hack to me than
anything else. Devs 99% of the time, don't have control over the API response, they cannot fix
server's misconfiguration only so their code works. Devs expect file_get_contents to simply
work. Curl works just fine with this URL while file_get_contents is buggy. I don't expect Curl
to have lots of hacks and I am pretty sure Curl has a nice workaround about server not closing
connection - and so PHP should do. No hacks, I agree with you, hacks are terrible and probably will
break something in the future.

------------------------------------------------------------------------
[2021-04-07 20:11:49] danack@php.net

Setting the protocol back to 1.0 with the protocol version option appears to make it work on 8.
I'll need to actually inspect the packets to have a deeper look.


> But I am pretty sure it will start bothering many other devs as they
> update their PHP to 8.x and start seeing their code breaking.

To set your expectation, if this is a bug on the remote server, then it's unlikely we would
write a hack around it. People can either use a workaround in their code, stay on PHP7, or ask the
person who owns that site to fix it. It's not feasible to put work arounds in php core for all
buggy servers out there.



<?php

$context = stream_context_create(array(
    "http" => array(
        "protocol_version" => "1.0"
    )
));

$response = file_get_contents("http://ws.correios.com.br/calculador/CalcPrecoPrazo.aspx?nCdEmpresa=&sDsSenha=&sCepOrigem=11661690&sCepDestino=88070-480&nVlPeso=1&nCdFormato=1&nVlComprimento=25&nVlAltura=3&nVlLargura=25&sCdMaoPropria=N&nVlValorDeclarado=0&sCdAvisoRecebimento=N&nCdServico=04014&nVlDiametro=0&StrRetorno=xml",
0, $context);

echo "response length is " . strlen($response) . "\n";

------------------------------------------------------------------------
[2021-04-07 17:21:45] gilperon at gmail dot com

I just want to point that Correios (http://correios.com.br/), whose API I am using and which is the
one that makes file_get_contents dont work as expected, is the largest shipping
organization in Brazil (96% marketshare), and it's owned by the brazilian goverment. I am
pretty sure many many devs use this API with PHP and I am probably one of the few to face this
problem because, probably, many devs are still using older versions of PHP here in brazil. But I am
pretty sure it will start bothering many other devs as they update their PHP to 8.x and start seeing
their code breaking. Just a side note in case you think I am using a "special URL" only
created to make this problem happen (the URL I provided you is the official goverment end point of
their webhook).

------------------------------------------------------------------------
[2021-04-07 16:59:05] danack@php.net

Oh, the difference is PHP 7 set HTTP/1.0, PHP 8 does HTTP/1.1
 
"GET
/calculador/CalcPrecoPrazo.aspx?nCdEmpresa=&sDsSenha=&sCepOrigem=11661690&sCepDestino=88070-480&nVlPeso=1&nCdFormato=1&nVlComprimento=25&nVlAltura=3&nVlLargura=25&sCdMaoPropria=N&nVlValorDeclarado=0&sCdAvisoRecebimento=N&nCdServico=04014&nVlDiametro=0&StrRetorno=xml
HTTP/1.0\r\nHost: ws.correios.com.br\r\nConnection: close\r\n\r\n"

"GET
/calculador/CalcPrecoPrazo.aspx?nCdEmpresa=&sDsSenha=&sCepOrigem=11661690&sCepDestino=88070-480&nVlPeso=1&nCdFormato=1&nVlComprimento=25&nVlAltura=3&nVlLargura=25&sCdMaoPropria=N&nVlValorDeclarado=0&sCdAvisoRecebimento=N&nCdServico=04014&nVlDiametro=0&StrRetorno=xml
HTTP/1.1\r\nHost: ws.correios.com.br\r\nConnection: close\r\n\r\n"

------------------------------------------------------------------------


The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at

    https://bugs.php.net/bug.php?id=80931


--
Edit this bug report at https://bugs.php.net/bug.php?id=80931&edit=1


Thread (35 messages)

« previous php.bugs (#233313) next »