You are viewing a plain text version of this content. The canonical link for it is here.
Posted to bugs@httpd.apache.org by bu...@apache.org on 2005/09/23 14:21:46 UTC

DO NOT REPLY [Bug 36780] New: - Apache crashes while processing a request whose connection has been forcibly closed by IExplorer

DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG�
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://issues.apache.org/bugzilla/show_bug.cgi?id=36780>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND�
INSERTED IN THE BUG DATABASE.

http://issues.apache.org/bugzilla/show_bug.cgi?id=36780

           Summary: Apache crashes while processing a request whose
                    connection has been forcibly closed by IExplorer
           Product: Apache httpd-2.0
           Version: 2.0.54
          Platform: PC
        OS/Version: Windows XP
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Core
        AssignedTo: bugs@httpd.apache.org
        ReportedBy: sybspublicadress@gmx.de


we are using Windows XP resp. Windows 2000 with  Apache/2.0.54 (Win32)
mod_ssl/2.0.54 OpenSSL/0.9.7g mod_python/3.1.3 Python/2.3.5 (httpd.conf see
appendix)

Apache crashes while processing a request whose connection has been forcibly
closed by the IExplorer. This occurs while the request handler tries to write a
large amount of data for the answer.

Apache crashes in  following scenario: Apache is processing a request. Our
handler tries to write a large amount of data ( in our case  ~960000 bytes) to
the request. To do this apache calls the function apr_brigade_write. If the
amount of data is large a transient bucket with the user data address will be
created. 

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
apr_brigade.c:
APU_DECLARE(apr_status_t) apr_brigade_write(apr_bucket_brigade *b,
                                            apr_brigade_flush flush,
                                            void *ctx,
                                            const char *str, apr_size_t nbyte)
{
 ...
    if (nbyte > remaining) {
        /* either a buffer bucket exists but is full,
         * or no buffer bucket exists and the data is too big
         * to buffer.  In either case, we should flush.  */
        if (flush) {
            e = apr_bucket_transient_create(str, nbyte, b->bucket_alloc);
            APR_BRIGADE_INSERT_TAIL(b, e);
           return flush(b, ctx);
           ...
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

This bucket will be send to the next filters. In our case Mod_Deflate fragments
it in a loop to 8000 byte pieces and send it to the next filter 

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
(mod_deflate.c / line 553 : 
static apr_status_t deflate_out_filter(ap_filter_t *f,
                                       apr_bucket_brigade *bb)
{
   ...
        while (ctx->stream.avail_in != 0) {
            if (ctx->stream.avail_out == 0) {
                apr_status_t rv;

                ctx->stream.next_out = ctx->buffer;
                len = c->bufferSize - ctx->stream.avail_out;

                b = apr_bucket_heap_create((char *)ctx->buffer, len,
                                           NULL, f->c->bucket_alloc);
                APR_BRIGADE_INSERT_TAIL(ctx->bb, b);
                ctx->stream.avail_out = c->bufferSize;
                /* Send what we have right now to the next filter. */
                rv = ap_pass_brigade(f->next, ctx->bb);
                if (rv != APR_SUCCESS) {
                    return rv;
                }
            }
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

At last SSL tries to write on the connection. But in the meantime IExplorer has
closed the connection (e.g. because the user trigger a further request in the
same frame). Thus SSL_Write fails:

error.log (loglevel info):
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
[Thu Aug 25 13:20:19 2005] [info] Subsequent (No.142) HTTPS request received for
child 0 (server PDDEKA-W1165:443)
[Thu Aug 25 13:20:20 2005] [info] Subsequent (No.134) HTTPS request received for
child 1 (server PDDEKA-W1165:443)
[Thu Aug 25 13:20:20 2005] [info] (OS 10054)An existing connection was forcibly
closed by the remote host.  : core_output_filter: writing data to the network
[Thu Aug 25 13:20:20 2005] [info] (620019)APR does not understand this error
code: SSL output filter write failed.
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

The processing aborts. But unfortunately the transient buckets of apr_bucket.c
will not deleted. Because this bucket resp. its brigade will be referenced in
the ctx and this will be processed later at the finalizing of the request:
In succession of the call of ap_finalize_request_protocol(r) of this request
ap_old_write_filter  will be called. 

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
protocol.c:
AP_CORE_DECLARE_NONSTD(apr_status_t) ap_old_write_filter(
    ap_filter_t *f, apr_bucket_brigade *bb)
{
    old_write_filter_ctx *ctx = f->ctx;

    AP_DEBUG_ASSERT(ctx);

    if (ctx->bb != 0) {
        /* whatever is coming down the pipe (we don't care), we
         * can simply insert our buffered data at the front and
         * pass the whole bundle down the chain.
         */
        APR_BRIGADE_CONCAT(ctx->bb, bb);
        bb = ctx->bb;
        ctx->bb = NULL;
    }

    return ap_pass_brigade(f->next, bb);
}
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Because ctx->bb contains the "transient" bucket containing a data address which
no more exists the processing of the bucket crashes.


Following solution does solve our problem:
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
apr_brigade.c:
APU_DECLARE(apr_status_t) apr_brigade_write(apr_bucket_brigade *b,
                                            apr_brigade_flush flush,
                                            void *ctx,
                                            const char *str, apr_size_t nbyte)
{
 ...
    if (nbyte > remaining) {
        /* either a buffer bucket exists but is full,
         * or no buffer bucket exists and the data is too big
         * to buffer.  In either case, we should flush.  */
        if (flush) {
            apr_status_t rv = 0;

            e = apr_bucket_transient_create(str, nbyte, b->bucket_alloc);
            APR_BRIGADE_INSERT_TAIL(b, e);
            rv = flush(b, ctx);

            if (rv != APR_SUCCESS) {
              apr_bucket_delete(e);
              apr_brigade_cleanup(b);
            }
            return rv;
...
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Appendix: httpd.conf
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Timeout 300
KeepAlive On
MaxKeepAliveRequests 0
KeepAliveTimeout 90
<IfModule mpm_winnt.c>
ThreadsPerChild 100
MaxRequestsPerChild  0
Win32DisableAcceptEx ON
</IfModule>
LoadModule access_module modules/mod_access.so
LoadModule alias_module modules/mod_alias.so
LoadModule dir_module modules/mod_dir.so
LoadModule headers_module modules/mod_headers.so
LoadModule include_module modules/mod_include.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule mime_module modules/mod_mime.so
LoadModule negotiation_module modules/mod_negotiation.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule deflate_module modules/mod_deflate.so
<IfDefine SSL>
LoadModule ssl_module modules/mod_ssl.so
</IfDefine>
LoadModule python_module modules/mod_python.so
UseCanonicalName Off
AddType application/x-javascript .js
<Directory "/">
    AddOutputFilterByType DEFLATE text/html text/plain text/css
application/x-javascript
    Header append Vary User-Agent env=!dont-vary
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>
DirectoryIndex index.html index.html.var
AccessFileName .htaccess
<Files ~ "^\.ht">
    Order allow,deny
    Deny from all
</Files>
TypesConfig conf/mime.types
DefaultType text/plain
HostnameLookups Off
LogLevel info
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent
ServerTokens Full
ServerSignature On
AddLanguage da .dk
AddLanguage nl .nl
AddLanguage en .en
AddLanguage et .et
AddLanguage fr .fr
AddLanguage de .de
AddLanguage he .he
AddLanguage el .el
AddLanguage it .it
AddLanguage ja .ja
AddLanguage pl .po
AddLanguage ko .ko
AddLanguage pt .pt
AddLanguage nn .nn
AddLanguage no .no
AddLanguage pt-br .pt-br
AddLanguage ltz .ltz
AddLanguage ca .ca
AddLanguage es .es
AddLanguage sv .sv
AddLanguage cs .cz .cs
AddLanguage ru .ru
AddLanguage zh-CN .zh-cn
AddLanguage zh-TW .zh-tw
AddLanguage hr .hr
LanguagePriority en da nl et fr de el it ja ko no pl pt pt-br ltz ca es sv tw
ForceLanguagePriority Prefer Fallback
AddDefaultCharset ISO-8859-1
AddCharset ISO-8859-1  .iso8859-1 .latin1
AddCharset ISO-8859-2  .iso8859-2 .latin2 .cen
AddCharset ISO-8859-3  .iso8859-3 .latin3
AddCharset ISO-8859-4  .iso8859-4 .latin4
AddCharset ISO-8859-5  .iso8859-5 .latin5 .cyr .iso-ru
AddCharset ISO-8859-6  .iso8859-6 .latin6 .arb
AddCharset ISO-8859-7  .iso8859-7 .latin7 .grk
AddCharset ISO-8859-8  .iso8859-8 .latin8 .heb
AddCharset ISO-8859-9  .iso8859-9 .latin9 .trk
AddCharset ISO-2022-JP .iso2022-jp .jis
AddCharset ISO-2022-KR .iso2022-kr .kis
AddCharset ISO-2022-CN .iso2022-cn .cis
AddCharset Big5        .Big5       .big5
AddCharset WINDOWS-1251 .cp-1251   .win-1251
AddCharset CP866       .cp866
AddCharset KOI8-r      .koi8-r .koi8-ru
AddCharset KOI8-ru     .koi8-uk .ua
AddCharset ISO-10646-UCS-2 .ucs2
AddCharset ISO-10646-UCS-4 .ucs4
AddCharset UTF-8       .utf8
AddCharset GB2312      .gb2312 .gb
AddCharset utf-7       .utf7
AddCharset utf-8       .utf8
AddCharset big5        .big5 .b5
AddCharset EUC-TW      .euc-tw
AddCharset EUC-JP      .euc-jp
AddCharset EUC-KR      .euc-kr
AddCharset shift_jis   .sjis
AddType application/x-tar .tgz
AddType image/x-icon .ico
AddHandler type-map var
BrowserMatch "Mozilla/2" nokeepalive
BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0
BrowserMatch "RealPlayer 4\.0" force-response-1.0
BrowserMatch "Java/1\.0" force-response-1.0
BrowserMatch "JDK/1\.0" force-response-1.0
BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully
BrowserMatch "^WebDrive" redirect-carefully
BrowserMatch "^WebDAVFS/1.[012]" redirect-carefully
BrowserMatch "^gnome-vfs" redirect-carefully
<IfModule mod_ssl.c>
    Include conf/ssl.conf
</IfModule>

-- 
Configure bugmail: http://issues.apache.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.

---------------------------------------------------------------------
To unsubscribe, e-mail: bugs-unsubscribe@httpd.apache.org
For additional commands, e-mail: bugs-help@httpd.apache.org