Change to timeout use
| From: | Andreas Schiffler | Date: | Wed, 21 Dec 2005 15:49:56 +0000 |
| Subject: | Change to timeout use | ||
| Groups: | php.internals | ||
| Request: | Send a blank email to internals+get-21302@lists.php.net to get a copy of this message | ||
Hi all,
I am new to php source code hacking, but got into it for a particular reason: I need sub-second SOAP request timeouts.
To qualify the reasoning behind this sub-second timeout requirement a bit further, let me explain what it is used for: We are implementing a system that changes webcontent based on a remote SOAP service (i.e. customer database) and we want to never wait more than - say - 250ms for this to complete. Currently the best I can do is 1 sec connection timeout (in SoapClient() using the connection_timeout parameter) and 1 sec socket-read timeout (using ini_set() on the default_socket_timeout parameter). Assuming the remote SOAP server is down or slow, every pagerender with the SOAP request in it would get delayed by at least 1 sec, which is unacceptable in our case.
BTW, comparing the PHP situation with other SOAP implementations, we have typically millisecond timeouts available:
- Java (apachesoap): milliseconds
- Java (axis): milliseconds
- .NET: milliseconds
- perl (SOAP::Lite): seconds
Currently all socket/connection timeouts in PHP are implemented with second resolution. This is an unnecessary limitation in my view and I would love for this to be changed in mainstream PHP. I believe the effort to do so is minimal and has no impact to the users.
The timeout numbers are usually used to populate a "tv" struct - in the current PHP code only the tv.tv_sec is typically set. So the change would simply be to promote default_socket_timeout (and similar variables) to a float and use the fractional part to properly populate tv.tv_usec with a microsecond number.
In fact I found locations where the default_socket_timeout parameter is assumed to be a float (ext/standard/fsock.c - line 66).
Also this simple code shows the local default_socket_context to accept a float parameter:
<?php
ini_set("default_socket_timeout",0.5);
phpinfo();
?>
while ext/standard/file.h - line 113 stores it as a long.
So a quick review of how this parameter is used throughout the code might be a-good-thing (TM) anyhow.
An example implementation of the new, float resulution timeout use for the SoapClient/SoapServer is a few lines in ext/soap/soap.c and ext/soap/php_http.c as follows:
soap.c
if (zend_hash_find(ht, "connection_timeout", sizeof("connection
Z_TYPE_PP(tmp) == IS_DOUBLE && Z_DVAL_PP(tmp) > 0.0) {
add_property_double(this_ptr, "_connection_timeout", Z_
}
php_http.c
if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_connection_timeout", sizeof
Z_TYPE_PP(tmp) == IS_DOUBLE && Z_DVAL_PP(tmp) > 0.0) {
tv.tv_sec = floor(Z_DVAL_PP(tmp));
tv.tv_usec = (1000000.0*(Z_DVAL_PP(tmp)-floor(Z_DVAL_PP(tmp))));
timeout = &tv;
}
Similarly changes in the main PHP code could look something like this (assuming the var is a float):
main/streams/transport.c
default_timeout.tv_sec = floor(FG(default_socket_timeout));
default_timeout.tv_usec = (1000000.0 * (FG(default_socket_timeout)-floor(FG(default_socket_timeout))) );
The files that need to be changed are limited.
grep -c default_socket_timeout ind . -name "*.[ch]" | grep -v :0
gives
./ext/imap/php_imap.c:4
./ext/standard/file.c:1
./ext/standard/file.h:1
./ext/standard/fsock.c:1
./ext/standard/streamsfuncs.c:2
./ext/openssl/xp_ssl.c:2
./main/streams/transports.c:2
./main/streams/xp_socket.c:3
./main/network.c:2
grep -c default_socket_timeout ind . -name "*.[ch]" | grep -v :0
gives
./ext/ftp/ftp.c:2
./ext/curl/streams.c:1
./ext/soap/php_http.c:1
./ext/session/session.c:3
./ext/sockets/sockets.c:5
./ext/standard/uniqid.c:1
./ext/standard/lcg.c:1
./ext/standard/fsock.c:1
./ext/standard/streamsfuncs.c:4
./ext/openssl/xp_ssl.c:2
./main/streams/xp_socket.c:2
./main/network.c:2
Best regards
Andreas