ID:               26494
 User updated by:  hexer at studentcenter dot org
 Reported By:      hexer at studentcenter dot org
-Status:           Feedback
+Status:           Open
 Bug Type:         Apache related
 Operating System: Linux
 PHP Version:      4.3.4
 New Comment:

To reproduce this problem one needs to start loading a php page and
force an ungraceful disconnection before the page is done loading. The
easiest way to force an ungraceful disconnection is to unplug the
computer from the internet as soon as the page is requested by the
browser.

As the result, php will keep trying to write data to the socket and
will eventually block until the operating system's default socket
timeout is reached.

The following script will do the job:
<?php
for($i = 0; $i < 1000000; $i++) {
        echo "XXXXXXXXXXXXXXXXXXXXXXXX<br>\n";
}
?>

This should work on virtually any UNIX configuration with mod_php
compiled into apache 1.3.x.

It is important that the client's connection is broken ungracefully
instead of just being closed, that way the operating system has no way
of knowing that the connection with the client is no longer valid.
Normally apache will give up after trying to send for N seconds
specified in the Timeout directive of httpd.conf. Apache 1.3.x modules,
however, must explicitly make API calls that start and stop the timer
to mark the sections of the code where send's take place.

This problem can be reproduced with the default http.conf and php.ini
on apache 1.3.29 and mod_php 4.3.4 it has also been observed on earlier
versions of php and apache.
httpd.conf can have the following setting:
#
# Timeout: The number of seconds before receives and sends time out.
#
Timeout 300

also to easilly see the processes be sure to enable mod_status by
uncommenting the following lines in httpd.conf

AddModule mod_status.c

ExtendedStatus On

<Location /server-status>
    SetHandler server-status
    Order deny,allow
#    Deny from all
    Allow from all
</Location>

from the status page you can see the process getting stuck on 'W'
status for a much longer duration than Timeout setting:

45-7 32133 0/50/3553 W  0.38 895 0 0.0 0.23 10.62  151.204.xxx.xxx
test.mydomain.com GET /test.php HTTP/1.1


Previous Comments:
------------------------------------------------------------------------

[2003-12-02 01:11:19] [EMAIL PROTECTED]

Can not reproduce. Please provide the process & script to easily
reproduce this. Also the configure line used to configure PHP is
required.


------------------------------------------------------------------------

[2003-12-01 17:58:25] hexer at studentcenter dot org

Description:
------------
Problem: On Apache 1.3.x, the compiled-in mod_php4 will cause stuck
httpd processes while trying to send output from php to a dead client
connection.

The Cause: mod_php4.c does not set the Apache Timeout timer in the send
functions.

Solution: Apache recommends any modules that write to the client to use
the timeout functions provided by the Apache API.

The following modification to mod_php4.c will fix the problem and make
mod_php4 comply with Apache 1.3.x Timeout setting.


static int sapi_apache_ub_write(const char *str, uint str_length
TSRMLS_DC)
{
    int ret=0;

    if (SG(server_context)) {

+        ap_hard_timeout("php send body", (request_rec *)
SG(server_context));

        ret = rwrite(str, str_length, (request_rec *)
SG(server_context));

+        ap_kill_timeout((request_rec *) SG(server_context));

    }
    if (ret != str_length) {
        php_handle_aborted_connection();
    }
    return ret;
}


Reproduce code:
---------------
This problem is easilly reproduced by simply breaking the connection
with the server while trying to load any php-generated  page.

Expected result:
----------------
Apache process must abort processing the request if a single write
operation exceeds the amount of seconds set in the Timeout setting in
httpd.conf.

Actual result:
--------------
#0  0x420d368d in writev () from /lib/i686/libc.so.6
#1  0x0815fb08 in writev_it_all ()
#2  0x0815fe77 in large_write ()
#3  0x0815ff3b in ap_bwrite ()
#4  0x08172c10 in ap_rwrite ()
#5  0x080884da in sapi_apache_ub_write ()
#6  0x0809ab6f in php_ub_body_write_no_header (
    str=0x86484ec "XXXXXX"..., str_length=4144) at
/usr/local/src/php-4.3.4/main/output.c:689
#7  0x0809a117 in php_end_ob_buffer (send_buffer=1 '\001', just_flush=1
'\001')
    at /usr/local/src/php-4.3.4/main/output.c:299
#8  0x0809ab39 in php_b_body_write (
    str=0x8666834 "XXXXXX", 
    str_length=51) at /usr/local/src/php-4.3.4/main/output.c:616
#9  0x08099dd2 in php_body_write (
    str=0x8666834 "XXXXXX", 
    str_length=51) at /usr/local/src/php-4.3.4/main/output.c:121
#10 0x080abe89 in zend_print_zval_ex (
    write_func=0x808ef40 <php_body_write_wrapper>, expr=0x85992ac,
indent=0)
    at /usr/local/src/php-4.3.4/Zend/zend.c:211
#11 0x080abe2f in zend_print_zval (expr=0x85992ac, indent=0)
    at /usr/local/src/php-4.3.4/Zend/zend.c:192
---Type <return> to continue, or q <return> to quit---
#12 0x080abb70 in zend_print_variable (var=0x85992ac)
    at /usr/local/src/php-4.3.4/Zend/zend_variables.c:147
#13 0x080b64b5 in execute (op_array=0x8642fac)
    at /usr/local/src/php-4.3.4/Zend/zend_execute.c:1244
#14 0x080b8635 in execute (op_array=0x862bf24)
    at /usr/local/src/php-4.3.4/Zend/zend_execute.c:2181
#15 0x080acc03 in zend_execute_scripts (type=8, retval=0x0,
file_count=3)
    at /usr/local/src/php-4.3.4/Zend/zend.c:884
#16 0x0808ffb3 in php_execute_script (primary_file=0xbffff650)
    at /usr/local/src/php-4.3.4/main/main.c:1729
#17 0x080ba6e2 in apache_php_module_main (r=0x8256564,
display_source_mode=0)
    at /usr/local/src/php-4.3.4/sapi/apache/sapi_apache.c:54
#18 0x08089038 in send_php ()
#19 0x080890a3 in send_parsed_php ()
#20 0x0816109c in ap_invoke_handler ()
#21 0x08175b1f in process_request_internal ()
#22 0x08175b7e in ap_process_request ()
#23 0x0816cd55 in child_main ()
#24 0x0816cfb6 in make_child ()
#25 0x0816d2f5 in perform_idle_server_maintenance ()
#26 0x0816d914 in standalone_main ()
#27 0x0816df1a in main ()
#28 0x420158d4 in __libc_start_main () from /lib/i686/libc.so.6


------------------------------------------------------------------------


-- 
Edit this bug report at http://bugs.php.net/?id=26494&edit=1

Reply via email to