php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #42682 stream_select() indicates bad number of readable descriptors
Submitted: 2007-09-16 20:27 UTC Modified: 2008-04-18 23:41 UTC
Votes:12
Avg. Score:4.7 ± 0.6
Reproduced:11 of 11 (100.0%)
Same Version:6 (54.5%)
Same OS:8 (72.7%)
From: Slig at free dot fr Assigned: closed-by-jani (profile)
Status: Closed Package: Streams related
PHP Version: 5CVS-2007-10-11 (snap) OS: linux-64
Private report: No CVE-ID: None
 [2007-09-16 20:27 UTC] Slig at free dot fr
Description:
------------
stream_select fails to return the number of modified descriptors.

The bug happen on linux amd64 (tested on a quad core xeon, debian etch amd64) but not on x86 install (tested on a similar computer but dual core xeon, debian etch x86).
It seems to happen only when php is built with openssl (i tried many combinaisons), with php 5.2.0, 5.2.1, 5.2.2, 5.2.3, 5.2.4, php5 snap, and also php6 snap.

This bug is the same as #40735 but I am unable to modify the status of
that bug.


I can eventually provide a ssh access to the computer further tests and debug (ask me by email).

Reproduce code:
---------------
<?php
// replace with your smtp ip if needed, need a tcp server which reply data immediatly
$handle = fsockopen('tcp://smtp',25);

while(!feof($handle)) {

  $r = array($handle);
  $w = null;
  $e = array($handle);
  $nb = stream_select($r,$w,$e,3);
  echo "select : $nb, r=".count($r).', w='.count($w).', e='.count($e)."\n";

  while($nb>0){
    echo "Reading...\n";
    $contents = fread($handle,8192);
    echo "Contents: [$contents]\n";

    $r = array($handle);
    $w = null;
    $e = array($handle);
    $nb = stream_select($r,$w,$e,1);
    echo "select : $nb, r=".count($r).', w='.count($w).', e='.count($e)."\n";
  }

  usleep(20000);
}
fclose($handle);
?>


Expected result:
----------------
select : 1, r=1, w=0, e=0
Reading...
Contents: [220 naxos2.unice.fr ESMTP Sendmail 8.13.1/8.13.1; Sun, 16 Sep 2007 22:23:04 +0200
]
select : 0, r=0, w=0, e=0


Actual result:
--------------
select : 0, r=1, w=0, e=0
select : 0, r=1, w=0, e=0
select : 0, r=1, w=0, e=0
select : 0, r=1, w=0, e=0
select : 0, r=1, w=0, e=0


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2007-09-18 09:40 UTC] jani@php.net
I still can not reproduce this on my system.
OpenSSL Version => OpenSSL 0.9.8b 04 May 2006

Are you able to reproduce this on more than one machine? (and with other linux distro than debian)
 [2007-09-19 08:26 UTC] Slig at free dot fr
OpenSSL on the tested computer: Architecture: amd64 , Version: 0.9.8c-4

I can try only on the same server with a different cpu (dual core xeon and not quad core xeon) and another distro, but not sure when i'll have time for that, i'll tell you the result here.
 [2007-09-21 00:06 UTC] Slig at free dot fr
I tested today on a dual dual-core-xeon on current Fedora 7 x86_64, first with current php and current openssl, then building php6 from the source : same result, it give the expected result without openssl, but return 0 when build with --with-openssl when there is a descriptor to read.

Note: If i use as workaround 'while($nb>0 || count($r)>0){' and reduce the read buffer ( fread($handle,30); for example), then i see that after the first read the value returned by stream_select is ok... but it shows another bug (#42720) :d
 [2007-10-11 16:29 UTC] Slig at free dot fr
Sorry, still the same with the last snapshot on amd64/dual core xeon on debian etch : it works without  --with-openssl  but don't work when built using  --with-openssl  :(
 [2007-10-11 18:50 UTC] margus at zone dot ee
I was hit by the same annoying bug (CentOS 4.5/x64/PHP5.1.6 & 5.2.3)

After debugging PHP stream_select() I found out that system's select() returns correct number but this value get's mysteriously set to zero (memory is overwritten?) a few steps before returning it to PHP script. 

Anyway, the cure for me was to change an variable type from int to long and explicitly reset it to 0. This patch works for both PHP 5.1 and 5.2:

--- ext/standard/streamsfuncs.c.orig    2007-10-09 16:21:30.000000000 +0300
+++ ext/standard/streamsfuncs.c 2007-10-09 16:21:41.000000000 +0300
@@ -608,7 +608,7 @@
        zval **elem, **dest_elem;
        php_stream *stream;
        HashTable *new_hash;
-       int this_fd, ret = 0;
+       long this_fd = 0, ret = 0;
 
        if (Z_TYPE_P(stream_array) != IS_ARRAY) {
                return 0;
 [2007-10-12 10:10 UTC] jani@php.net
But it won't work in future. I tried to figure out why changing that int to long would help but AFAICT it's really supposed to be int since everything else using this_fd is expecting it to be int..
 [2007-10-12 17:17 UTC] Slig at free dot fr
No, just setting it to 0 doesn't work.

And margus is true, using 'long this_fd;' it works (with or without setting it to 0). I don't say it's the right solution, perhaps it's more something to change in php_stream_cast(), i don't know.
 [2007-10-12 18:25 UTC] margus at zone dot ee
Perhaps it helps if I give test results on different machines and where and how it manifests:

stream_select() works flawlessly without patching on:
- my multiple 32bit machines. Those have SuSE90 or SuSE93 installed.
- my multiple 64bit SuSE10 machines

stream_select() works only when patched 'long this_fd;' or 'long this_fd=0;' on:
- my multiple 64bit CentOS 4.5 systems (Xeon Quadcore)

stream_select() works only when patched 'long this_fd=0;' (stream_select segfaults without variable initializing) on:
- my one 64bit CentOS 4.5 machine (Opteron Dualcore). 

Origin of this bug must be somewhere in php_stream_cast() or even lower. I tried also compiling without OpenSSL support and yes, the bug along with SSL socket support can be "eliminated" this way too :)
 [2007-10-22 11:00 UTC] jani@php.net
Is there difference between openssl versions on those Suse/Centos machines?
 [2008-02-22 10:50 UTC] hans at parse dot nl
This is stil a pretty serious issue on x86_64. Just ran into this one while swapping out a bunch of x86 webservers for new x86_64 boxes.

Both the new and the old boxes run Gentoo, with the same gcc version, same php version. The 32 bit boxes were fine, the new 64 bit boxes fail on all stream fread's due to this issue.

Target: x86_64-pc-linux-gnu
Thread model: posix
gcc version 4.1.2 (Gentoo 4.1.2 p1.0.2)
glibc-2.6.1
openssl-0.9.8g
php-5.2.5 (using php-5.2.5-r1 gentoo ebuild)
 [2008-04-15 10:52 UTC] hans at parse dot nl
Problem persists in 5.2.6RC4. 

Tested using the testcase above, on a freshly installed Athlon64 Gentoo system. Tested against the following openssl versions:

openssl-0.9.8g
openssl-0.9.8e
openssl-0.9.7i

Recompiled php-5.2.6RC4 ebuild after each openssl version change. All versions exhibit same erroneous behavior, as described in the initial bugreport.

Compiling php without openssl support eliminates the problem, as reported earlier.

Target: x86_64-pc-linux-gnu
Thread model: posix
gcc version 4.1.2 (Gentoo 4.1.2 p1.0.2)
glibc-2.6.1
php-5.2.6RC4 (using dev-lang/php-5.2.6_rc4 gentoo ebuild)
 [2008-04-15 11:28 UTC] hans at parse dot nl
Just did a final test and recompiled php with gcc optimization set to -O1 instead of -O2 used in previous tests, and i can confirm that compiling with -O1 eliminates the problem aswell.

So to summarize:

-changing this_fd from int to long eliminates the problem
-compiling without openssl eliminates the problem, though this is obviously not an option in most cases
-compiling without gcc optimizations eliminates the problem

So now the question is, is this a gcc, a php or a openssl problem?

I'm willing to test and provide you with all necessary information.
 [2008-04-16 07:59 UTC] hans at parse dot nl
More info:

Upgraded to gcc-4.2.3 to check for possible gcc-related issue. Recompiled entire system overnight. Problem persists.

Since the last response from a php devver is almost 6 months back, it would be very welcome to see some response on these latest additions.
 [2008-04-16 13:43 UTC] hans at parse dot nl
php-5.2.6RC5 seems to solve this issue. Just tested with -O2 optimizations and the testcase returns the expected result.
 [2008-04-18 23:41 UTC] jani@php.net
Apparently fixed in CVS then. (and in 5.2.6, once it's released :) 
Reopen if this is not the case.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Wed Nov 27 16:01:29 2024 UTC