I have two servers both running drupal 6.14 on php 5.2.11. One is able to "ping" an apache solr installation while the other one is not.
So I debugged the code and ended up at this loop:
function drupal_http_request($url, $headers = array(), $method = 'GET', $data = NULL, $retry = 3) {
...
$response = '';
while (!feof($fp) && $chunk = fread($fp, 1024)) {
$response .= $chunk;
}
...
}
It seems that espacially a ping to apache solr (which is a HEAD request with a really short response) has a problem with this loop or feof() under some circumstances.
just for testing purposes I changed the loop like this:
function drupal_http_request($url, $headers = array(), $method = 'GET', $data = NULL, $retry = 3) {
...
$response = '';
do {
$chunk = fread($fp, 1024);
$response .= $chunk;
} while (!feof($fp));
...
}
Now the "ping" worked on both servers but of course this change broke other things.
But if I do it the php5 way everything works on both servers:
function drupal_http_request($url, $headers = array(), $method = 'GET', $data = NULL, $retry = 3) {
...
$response = stream_get_contents($fp);
...
}
I attached a corresponding patch for drupal 6.14.
The remaining question is how to keep php4 support if needed for drupal 6.x.
Note: I already posted this as an comment to issue #245990: HTTP request testing unreliable and may be undesirable and was asked to open a second issue.
See http://drupal.org/node/245990#comment-2197162 and http://drupal.org/node/245990#comment-2201664
Comment | File | Size | Author |
---|---|---|---|
#30 | 617126-combo-fix-29-D6.patch | 1.57 KB | pwolanin |
#19 | 617126-combo-fix-19-D6.patch | 1.69 KB | pwolanin |
#14 | 617126-stream-meta-data-14.patch | 1.56 KB | pwolanin |
#12 | 617126-stream-meta-data-12.patch | 1.24 KB | pwolanin |
#1 | 617126-drupal-http-request-fread.patch | 617 bytes | Damien Tournoud |
Comments
Comment #1
Damien Tournoud CreditAttribution: Damien Tournoud commentedThe problem is this stupid, non-type safe and unneeded
$chunk = fread($fp, 1024)
.Drupal 7 doesn't have that, and is probably not affected.
Let's just remove the stupidity.
Comment #2
David_Rothstein CreditAttribution: David_Rothstein commentedThat certainly seems to make sense, but the code comment at http://www.php.net/manual/en/function.fread.php#93250 suggests this can lead to an infinite loop? (Perhaps it's a separate issue.)
I remember researching this stuff once before and it got very confusing very fast :(
Comment #3
pwolanin CreditAttribution: pwolanin commentedthe issue was also reported here: http://drupal.org/node/609836
with the suggested fix:
but likely the same possible problem? Could be an issue for D7 also? Isnt' there some problem with IIS not sending EOF?
This would maybe fix it? Are we relying on fread returning false or an empty string?
Comment #4
Damien Tournoud CreditAttribution: Damien Tournoud commented@David_Rothstein: there are a lot of FUD in the comments of both fread() and feof(). I'm convinced that none of those are necessary. After all, a FALSE cast to a string is the empty string, so who cares if loop one additional time?
Comment #5
pwolanin CreditAttribution: pwolanin commented@DamZ - why do you claim there would just be an extra loop? it seems the problem is rather that feof() is not reliable?
Comment #6
Damien Tournoud CreditAttribution: Damien Tournoud commentedThere are several bugs open on bugs.php.net about feof() weirdnesses. The most important one is probably #43782 - feof() does not detect timeout on socket, and it's sister issue #46049 - feof() hangs. If I understand those correctly, the behavior changed in 5.2.7 and was reverted in 5.2.8.
It means that we will probably have to fallback to using stream_get_meta_data() at each iteration of the loop (which is ugly and sad).
Comment #7
pwolanin CreditAttribution: pwolanin commentedok, so something like:
Comment #8
davecoventry CreditAttribution: davecoventry commentedI'm really not sure if I am on the right track here but I have a similar issue and I'm wondering if my D-Link G604T virtual server setup is somehow to blame.
My understanding is that this router does not do loopback, and I have a feeling that this might have an impact on your problem.
Sorry if I'm a little unclear; basically I'm suggesting that hardware might be the issue.
Comment #9
pwolanin CreditAttribution: pwolanin commentedso likely this bug needs to be handled in 7.x?
Comment #10
David Lesieur CreditAttribution: David Lesieur commentedJust encountered this peculiar issue on a Drupal 6 site running with PHP 5.2.11 on Solaris (SunOS 5.10). It was truncating some JSON responses from Solr. Peter's code in #7 solved it.
Comment #11
pwolanin CreditAttribution: pwolanin commentedok, so I'l roll #7 as a patch?
Comment #12
pwolanin CreditAttribution: pwolanin commentedComment #14
pwolanin CreditAttribution: pwolanin commentedThis version seems to fix at least some of the test failures - seems we we not setting the stream timeout, not caching all timeout conditions to return an error code.
Comment #15
jpmckinney CreditAttribution: jpmckinney commentedWould like this to be backported to D6, too.
Comment #16
Dries CreditAttribution: Dries commentedCommitted to CVS HEAD. Thanks.
Comment #17
jpmckinney CreditAttribution: jpmckinney commentedLooks like #156582: drupal_http_request() should support timeout setting needs to go in first (in D6).
Comment #18
pwolanin CreditAttribution: pwolanin commentedI'm not sure if Gabor will want to alter the API in #156582: drupal_http_request() should support timeout setting.
On the other hand, timing out the request is a little problematic if we always force the default of 30 seconds.
Comment #19
pwolanin CreditAttribution: pwolanin commentedHere's a sort of combination patch that makes no API changes to Drupal 6. An alternate maximum time for http requests can be set via a variable if needed.
Comment #20
droplet CreditAttribution: droplet commentedworks well
Comment #21
Gábor HojtsySomeone tested this on PHP 4.3.x? By carefully checking the docs, this should theoretically work the same there, but checking would be really useful.
Comment #22
hass CreditAttribution: hass commentedHui... bad. Linkchecker does HEAD by default and rely on the core function. Have not seen it myself but subscribe now
Comment #23
Gábor HojtsyComment #24
wojtha CreditAttribution: wojtha commentedSubscribing.
Comment #25
lukusSubscribing.
Comment #26
pwolanin CreditAttribution: pwolanin commented@Gabor - what kind of further review or testing is needed? Just that these functions work on 4.3/4.4?
I can try on 4.4.8, but given that even PHP 5.2 is EOL, perhaps we should up the version requirement for 6.x core to at least 4.4, or preferably 5.2.4 like 7.x?
Comment #28
Gábor Hojtsy@pwolanin: see above, I've had a request about 8 months ago without any replies yet. http://drupal.org/node/617126#comment-3665732
Comment #29
Gábor Hojtsy@pwolanin: it is helpful for future deconstruction of threads if you don't go back and edit your posts. Minimum PHP version requirement for Drupal 6 is 4.3.5, every core feature should work there too. If not, it is a regression. See: http://drupalcode.org/project/drupal.git/blob/refs/heads/6.x:/modules/sy... If you'd like that changed, please open another issue. I don't consider blocking out hosts running old PHP versions from future bugfixes and security updates to the Drupal 6 branch as something a stable backwards compatible Drupal version should do.
Comment #30
pwolanin CreditAttribution: pwolanin commentedI reinstalled Drupal 6 w/ PHP 4.4.8 and applied the patch. Git patch attached.
Update status fetch seems to work.
I also enabled aggregator module and successfully fetched feed items from
http://drupal.org/project/issues/search/rss?text=&projects=Drupal%20core...
and from
http://drupal.org/planet/rss.xml
Comment #31
lukusI applied the patch with Drupal 6.22 and PHP 5.2 and all is well.
Comment #32
rjbrown99 CreditAttribution: rjbrown99 commentedFor me, #30 seems to break apachesolr search, both with the standard module and with apachesolr_views. In my testing, Drupal and Apachesolr are on the same server. Viewing the apachesolr config page at admin/settings/apachesolr/settings shows that it has successfully contacted the server, however no search results are returned. I receive no results found for all solr searches. Backing out #30 fixes this for me. I am using Pressflow 6.22.104 with PHP 5.3.8 for what it's worth.