apr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Brian Doyle <li...@balancesoftware.com>
Subject Timing(?) bug in httpd 2.0.40
Date Thu, 29 Aug 2002 23:16:51 GMT
Hello,

    My apologies in advance for the crosspost, I'm not sure which group
should handle this.

    I am running httpd 2.0.40 on Linux 2.5.24 (compiled with gcc 3.1).  I
have noticed a problem where httpd is unable to determine the content-length
of a POST message and aborts prior to calling the specified CGI script.

    The problem is being reported in the apr code, but I don't know if
that's where the trouble is starting.  Unfortunately, I do not know the
apache source code at all and as such am not in a good position to debug it.
If you are a serious developer and cannot reproduce it on your machine, I
will set up an account for you on my machine if you are interested in fixing
the problem.

    Here's the gist of the problem:

    - I have a test CGI in the /cgi-bin/ directory.  The CGI works normally
      if it is referenced directly from a URL.  This problem occurs with
      any CGI.  Here is the code for my dummy CGI that I'm using for the
      test.  It resides in /cgi-bin/foo :

        /* FILE:  /cgi-bin/foo -- START */

        #include <stdio.h>
    
        int main( void ) {
            fprintf( stdout, "Content-type: text/plain\n\n" );
            fprintf( stdout, "Hello, World!\n" );

            return 0;
        }

    /* FILE:  /cgi-bin/foo -- END */


    - Initially I discovered this problem trying to post data from an HTML
      form, but here is what I've reduced the POST request to that will
      still demonstrate the problem:


        POST /cgi-bin/foo HTTP/1.1
        Host: foo.com
        Content-type: application/x-www-form-urlencoded
        Content-length: 36

        Submit=Submit&hiddenField=hiddenData


      * please note that there is nothing special about the data,
        my choice of a hiddenField form element is arbitrary, the problem
        (I don't believe) is related to the form data). *

   
    - When I take this data and type it in line-by-line over a
      telnet connection, everything works fine and the "foo" CGI is
      called.

      When I send the data in one packet (or very close time-wise), httpd
      closes the TCP connection and reports the following in the log:

    [<time>] [error] [client <addr>] (104)Connection reset by peer:
ap_content_length_filter: apr_bucket_read() failed

      Note that tcpdump shows that it is the server that is resetting the
      connection, *not* the client, even though the message given is
      "connection reset by peer".

      The critical thing seems to be whether or not the actual content is
      sent independently of the header.

      Here is some code that causes this behavior to happen every time on my
      machine.  Note the sleep( 1 ) call in the code.  If this line *is*
      present, the CGI is invoked and everything is hunky-dory.  If the
      sleep line is commented out and the server fails with the above error.


Here is the sample code, please contact me directly by reply email if you
need some help reproducing this or if I can help.  If you fix it, please
send me a patch :)  I'm sorry I can't help more, but it would take me a long
time to familiarize myself with the apache code to a point where I could
successfully debug this and unfortunately I'm engaged on another project.

Thank you,

Brian Doyle
Balance Software, Inc.


/* FILE:  cgi_post_test.c -- START */

#include    <arpa/inet.h>
#include    <netinet/in.h>
#include    <stdio.h>
#include    <string.h>
#include    <sys/types.h>
#include    <sys/socket.h>
#include    <unistd.h>

int connect_to_www_server( char *ip_address, int *sockfd );


char packet1[] = "POST /cgi-bin/foo HTTP/1.1\r\n" \
                 "Host: foo.com\r\n" \
                 "Content-type: application/x-www-form-urlencoded\r\n" \
                 "Content-length: 36\r\n" \
                 "\r\n";
char packet2[] = "Submit=Submit&hiddenField=hiddenData\r\n";


int main(int argc, char **argv) {
    char                buf[ 4096 ];
    int                    sockfd, n, err = 0;

    if ( argc != 2 ) {
        fprintf( stdout, "usage: %s <IP address of web server>\n", argv[ 0 ]
);
        err = 1;
    }
    
    if ( ! err ) err = connect_to_www_server( argv[ 1 ], &sockfd );
    
    if ( ! err && write( sockfd, packet1, strlen( packet1 ) ) < 0 ) err = 1;
        
    /*
       With the sleep( 1 ) line intact below, the /cgi-bin/foo script is
       executed and "Hello, World!" is returned.
       
       If the sleep( 1 ) call is commented out, the /cgi-bin/foo script is
       *NOT* invoked, and apache returns the following error:
       
       [Thu Aug 29 14:59:51 2002] [error] [client 10.0.0.10]
          (104)Connection reset by peer: ap_content_length_filter:
apr_bucket_read() failed
    */

    sleep( 1 );
    
    if ( ! err && write( sockfd, packet2, strlen( packet2 ) ) < 0 ) err = 1;

    while ( ! err && ( n = read( sockfd, buf, 4095 ) ) > 0 ) {
        buf[ n ] = 0;
        fprintf( stdout, "%s", buf );
    }

    if ( err ) fprintf( stderr, "an error occurred\n" );

    return err;
}


int connect_to_www_server( char *ip_address, int *sockfd ) {
    struct sockaddr_in    server;
    int                    err = 0;

    if ( ( *sockfd = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) err = 1;

    if ( ! err ) {
        bzero( &server, sizeof(server) );
        
        server.sin_family = AF_INET;
        server.sin_port    = htons( 80 ); /* www */

        if ( inet_pton( AF_INET, ip_address, &server.sin_addr) <= 0 ) {
            err = 1;
        }
    }
    
    if ( ! err ) {
        if ( connect( *sockfd, (struct sockaddr *) &server, sizeof(server) )
< 0 ) {
            err = 1;
        }
    }

    return err;
}

/* FILE:  cgi_post_test.c -- END */


Mime
View raw message