Hi all,

I came across a wierd problem with the apache/post test which seems to
occur on certain OSes. The symptoms are that the test locks up on one of
the subtests, LWP eventually times out on the request, the test fails and
then all subsequent tests that are run fail.

The problem seems to be this:
 - LWP writes the entire request in one go.
 - mod_echo_post send its response as it processes the request.
 - only when it has finished sending the request does LWP attempt to read
   the response.

I think what is happening is that, with large requests, a large amount of
data is simultanously being fed into the socket from both directions, and
some buffer somewhere in the OSes socket handler is being filled. My
suspicions are backed up by the fact that I modified mod_echo_post (see
attached) to read the entire request and only then send the response, and
this solves the problem.

If this is the case then it really should be fixed by making LWP read and
write simultanously; you may have guessed from my hazy terminology that I
don't really know a lot about how sockets _really_ work, but do any of
you guys think that this sounds about right? If so, I'll email the LWP
maintainers and see what they say.

Later,
Gary

[ [EMAIL PROTECTED] ][ GnuPG 85A8F78B ][ http://inauspicious.org/ ]
#if CONFIG_FOR_HTTPD_TEST

<Location /echo_post>
   SetHandler echo_post
</Location>

#endif

#define APACHE_HTTPD_TEST_HANDLER echo_post_handler

#include "apache_httpd_test.h"

static int echo_post_handler(request_rec *r)
{
    int rc;
    long nrd, buff_size;
    char *buff, *buff_p;

    if (strcmp(r->handler, "echo_post")) {
        return DECLINED;
    }
    if (r->method_number != M_POST) {
        return DECLINED;
    }

    if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)) != OK) {
        ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO,
#ifdef APACHE2
                     0,
#endif /* APACHE2 */
                     r->server,
                     "[mod_echo_post] ap_setup_client_block failed: %d", rc);
        return 0;
    }

    if (!ap_should_client_block(r)) {
        return OK;
    }

    /* Allocate a buffer to read the request into */
    buff_size = r->remaining;
    buff = malloc(buff_size);
    if (!buff) {
        ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO,
#ifdef APACHE2
                     0,
#endif /* APACHE2 */
                     r->server,
                     "[mod_echo_post] unable to malloc(%d)", buff_size);
        return HTTP_INTERNAL_SERVER_ERROR;
    }
    
    fprintf(stderr, "[mod_echo_post] going to read %ld bytes...\n",
            buff_size);

    /* Read the request */
    buff_p = buff;
    while ((nrd = ap_get_client_block(r, buff_p, r->remaining)) > 0) {
        fprintf(stderr,
                "[mod_echo_post] read %ld bytes (remaining=%ld)\n",
                nrd, r->remaining);
        buff_p += nrd;
    }
    if (r->remaining) {
        ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO,
#ifdef APACHE2
                     0,
#endif /* APACHE2 */
                     r->server,
                     "[mod_echo_post] data stopped %d bytes short",
                     r->remaining);
        return HTTP_INTERNAL_SERVER_ERROR;
    }

    /* Send the response */
#ifdef APACHE1
    fprintf(stderr, "[mod_echo_post] sending response headers...\n");
    ap_send_http_header(r);
#endif
    fprintf(stderr, "[mod_echo_post] sending response...\n");
    ap_rwrite(buff, buff_size, r);
    fprintf(stderr, "[mod_echo_post] done...\n");
    
    return OK;
}

APACHE_HTTPD_TEST_MODULE(echo_post);

Reply via email to