Edit report at https://bugs.php.net/bug.php?id=55438&edit=1
ID: 55438
Comment by: phpnet at lostreality dot org
Reported by: xuefer at gmail dot com
Summary: race condition: curlwapper is not sending http
header randomly
Status: Assigned
Type: Bug
Package: cURL related
Operating System: gentoo
PHP Version: 5.3.6
Assigned To: pierrick
Block user comment: N
Private report: N
New Comment:
Great. Any chance this can make it to 5.3.20 also?
Previous Comments:
------------------------------------------------------------------------
[2012-12-19 07:51:36] pierrick@php.net
Ok, I finally reproduced the problem.
I was trying the code snippet on my local network and everything was fine, once
I modified the code to fetch an URL on a slower network I had the problem.
Since curl multi is used, it sometime happen that the resource is freed before
the curl multi really execute the query. The patch looks good, I'll have a
second look tomorrow and will commit it.
Thanks for your help on this one :)
------------------------------------------------------------------------
[2012-12-19 06:01:04] phpnet at lostreality dot org
I have curl-7.15.5-15.el5 according to rpm -q, but I can only locate /usr/lib/libcurl.so.3.0.0 and
/usr/lib64/libcurl.so.3.0.0 on my machine I'm testing on (CentOS 5.8). The binary says:
/usr/bin/curl -V
curl 7.15.5 (x86_64-redhat-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5
Normally, I use the stock RPMs for PHP, but a recent project I was working on failed to run properly
on another machine, where the owners also use CentOS 5.8, but use CPanel/WHM instead of the CentOS
RPMs for PHP. CPanel uses the --with-curlwrappers option, where as the stock CentOS and RHEL RPMs
have never used that option on any of their builds. It took a lot of digging before I realized that
it was the --with-curlwrappers option that caused the scripts to fail on that machine while working
perfectly on mine.
To verify if the headers were actually sent, I used: tcpdump -i eth1 -Als0 host www.example.com
I had two PuTTY windows open, one with tcpdump, the other running the test script I mentioned before
with: ./php-5.4.9/sapi/cli/php ./test.php
It was pretty clear to me that the headers were never sent before the patch, and always sent after
the patch.
------------------------------------------------------------------------
[2012-12-19 05:50:16] pierrick@php.net
I tried to reproduce this bug but wasn't able to do it.
Could you give me more details on the libcurl version used by your PHP instance ?
And also, how do you make sure that the headers are not properly sent ?
------------------------------------------------------------------------
[2012-12-19 04:33:11] phpnet at lostreality dot org
I submitted a patch that moves the slist from a local variable in php_curl_stream_opener() into the
php_curl_stream struct. The headers are no longer cleared and freed at the end of
php_curl_stream_opener(). The code to free the slist is moved into php_curl_stream_close() instead.
I'm not sure if this is the best approach, but it clearly gives me a 100% success rate with
having headers get sent, where as I had a literal 0% success rate before (not sure if there is
really a race condition or not, just that the headers get cleared and the slist freed before they
get used.)
The test code I used was as follows (Actual cookie and URL redacted)
<?php
$opt = array('http' => array('method' => 'GET',
'header' => 'Cookie: foo=bar'));
$ctx = stream_context_create($opt);
$f = fopen('http://www.example.com/',
'r', false, $ctx);
fread($f, 1); //work-around curl-wrappers bug where meta_data doesn't exist until the stream is
read
$data = stream_get_meta_data($f);
fclose($f);
var_dump($data);
?>
I compiled PHP with the following flags (not that I think anything matters to this bug other than
--with-curlwrappers):
--enable-static --with-mcrypt --with-ldap --with-iconv --enable-mbstring --with-gd --enable-mbregex
--with-zlib --with-imap --enable-ftp --with-gettext --enable-sockets --with-mysql=/usr --enable-cgi
--with-imap-ssl --enable-sockets --with-pdo-mysql --with-openssl --with-kerberos --with-curl
--with-curlwrappers --with-tidy --with-pcre-regex --with-bz2 --enable-zip --with-libdir=/lib64
------------------------------------------------------------------------
[2012-12-18 19:29:56] phpnet at lostreality dot org
I think I am seeing this same problem too (On 5.3.10, but nothing has changed in the source in 5.4.9
either).
Can you explain how this is happening, or suggest a work-around? I was digging into the PHP source,
expecting that the --with-curlwrappers option was basically broken and incomplete. I was surprised
to find the line:
curl_easy_setopt(curlstream->curl, CURLOPT_HTTPHEADER, slist);
Because that code all seems to indicate that the headers should be sent, but no matter what I try,
nothing I put in headers ever appears in the actual request. I keep running tcpdump but I never see
the headers I put in http->header.
------------------------------------------------------------------------
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=55438
--
Edit this bug report at https://bugs.php.net/bug.php?id=55438&edit=1