Bug #2251: scary fsockopen() screwup for mod_php3
| From: | sp-bugs dot php dot net-19990906 at WRonline dot de | Date: | Mon, 06 Sep 1999 18:46:58 +0000 |
| Subject: | Bug #2251: scary fsockopen() screwup for mod_php3 | ||
| Groups: | php.dev | ||
| Request: | Send a blank email to php-dev+get-10629@lists.php.net to get a copy of this message | ||
From: sp-bugs.php.net-19990906@WRonline.de
Operating system: Linux 2.2.10 SMP, glibc2, Debian slink
PHP version: 3.0.12
PHP Bug Type: Misbehaving function
Bug description: scary fsockopen() screwup for mod_php3
Ladies and Gentlemen!
Please consider this simple piece of code:
<?php
$errno = 0; $errstr = "";
if ($fd = fsockopen("horatio.lan.wronline.de", 79, &$errno, &$errstr, 10)) {
fputs($fd, "\n");
while ($line = fgets($fd, 100)) {
echo $line;
}
fclose($fd);
}
else {
echo "$errno: $errstr\n";
}
?>
This works fine under PHP CGI, but bombs out with "0: Success" under mod_php3. Funny,
error 0...
Let's see what strace reveals. First with PHP CGI:
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 5
[...]
fcntl(5, F_GETFL) = 0x2 (flags O_RDWR)
fcntl(5, F_SETFL, O_RDWR|O_NONBLOCK) = 0
connect(5, {sin_family=AF_INET, sin_port=htons(79), sin_addr=inet_addr("195.4.83.179")},
16) = -1 EINPROGRESS (Operation now in progress)
select(6, [5], [5], NULL, {10, 0}) = 1 (out [5], left {9, 970000})
getsockopt(5, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
fcntl(5, F_SETFL, O_RDWR) = 0
We are in connect_nonb() in functions/fsock.c here obviously.
Now caught with mod_php:
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 89
[...]
fcntl(89, F_GETFL) = 0x2 (flags O_RDWR)
fcntl(89, F_SETFL, O_RDWR|O_NONBLOCK) = 0
connect(89, {sin_family=AF_INET, sin_port=htons(79), sin_addr=inet_addr("195.4.83.179")},
16) = -1 EINPROGRESS (Operation now in progress)
close(89) = 0
What's going on here? According to the code, a select() should occurr if(errno == EINPROGRESS).
Above trace can only
be seen if(errno != EINPROGRESS) return -1.
This seems like a "cannot happen" to me. I even validated that the preprocessor
substitutes 115 for EINPROGRESS as <asm/errno.h> says it should.
My "fix" was to change connect_nonb() like:
n = connect(sockfd, addr, addrlen);
/* if((n = connect(sockfd, addr, addrlen)) < 0)
if(errno != EINPROGRESS)
return -1;
*/
This cures the problem, works fine till now. :-) No error handling though. :-(
configure line:
CC="egcc" CFLAGS="-mpentiumpro -mcpu=i686 -O2" ./configure --with-ldap
--with-mysql=/opt/mysql --with-gd --with-ttf --with-mhash --with-mcrypt --with-xml --with-zlib
--with-config-file-path=/www/etc --enable-safe-mode --with-exec-dir=/www/php-bin --enable-track-vars
--enable-memory-limit --enable-sysvsem --enable-sysvshm --with-gdbm --with-ndbm
--with-apxs=/www/bin/apxs
Apache is: Apache/1.3.6 (Unix) mod_ssl/2.3.11 OpenSSL/0.9.4 PHP/3.0.12
Please note that later mentioned PHP-3.0.9 was configured without "-O2" and without
"--with-ldap".
Funny is, it worked (in 3.0.9) the whole last week,
but "stopped working" (oh how I hate this) for the weekend, still with 3.0.9 - 3.0.12 was
no better though.
I can't believe this...
Stefan