You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modules-dev@httpd.apache.org by Moacir Schmidt <mo...@gmail.com> on 2008/02/14 19:53:32 UTC

ap_get_brigade hangs when submitting a muitipart/form-data

Hi, everybody!

I'm trying to develop an 'uploader'  dso module to handle file
submissions from client browsers. The code worked well on win32 but on
debian hangs with files which size is over 22k.

Debugging my component shows me that the function ap_get_brigade slows
down after two or three loop interactions.

I isolated the problem in a 'helloworld' packet as follows:
index.htm: sample submit form:
---------------------------------------------
<form name="teste" enctype="multipart/form-data" method="post"
action=helloworld>
<input type=file name="arquivo" style="left:0;top:0;width:271; height:21;">
<input type=submit name="enviar" style="position:absolute;left:0;top:50">
</form>
----------------------------------------------
t02.c: module source code:
---------------------------------------
#include <httpd.h>
#include <http_log.h>
#include <http_protocol.h>
#include <http_config.h>
// most of this code came from mod_cgi.c
static int helloworld_handler(request_rec* r)
{
  if (!r->handler || strcmp(r->handler, "helloworld"))
    return DECLINED;
  apr_bucket_brigade *bb;
  int seen_eos, child_stopped_reading;
  bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
  seen_eos = 0;
  child_stopped_reading = 0;
  apr_status_t rv;
  ap_set_content_type(r, "text/html;charset=ascii"); // just to see
something on the browser
  do {
    apr_bucket *bucket;

    // ap_get_brigade slows down here after some loop iteractions when file
submitted is larger than 22kb
    rv = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES,
APR_BLOCK_READ, 8192);
    //   ^^^^^^^^^^^^^^
    if (rv != APR_SUCCESS) {
      return HTTP_INTERNAL_SERVER_ERROR;
    }
    for (bucket = APR_BRIGADE_FIRST(bb);
    bucket != APR_BRIGADE_SENTINEL(bb);
    bucket = APR_BUCKET_NEXT(bucket)) {
       apr_size_t len;
       const char *data;
       if (APR_BUCKET_IS_EOS(bucket)) {
         seen_eos = 1;
         break;
       }

       if (APR_BUCKET_IS_FLUSH(bucket)) {
          continue;
       }

       if (child_stopped_reading) {
          continue;
       }
       rv = apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ);
       if (rv != APR_SUCCESS) {
          child_stopped_reading = 1;
       }
       ap_rputs(data,r); // just do see something on the browser
    }
    apr_brigade_cleanup(bb);
  }  while (!seen_eos);
  return OK;
}
static void register_hooks(apr_pool_t* pool)
{
  ap_hook_handler(helloworld_handler, NULL, NULL, APR_HOOK_MIDDLE);
}
module AP_MODULE_DECLARE_DATA helloworld_module = {
  STANDARD20_MODULE_STUFF,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  register_hooks
};
--------------------------------------------------
PIC_12930.jpg: a sample file to upload that hangs ap_get_brigade (attached)

to reproduce the problem:

1) Compile module with apxs
apxs -c t02.c
apxs -ie t02.la

2) configure httpd.conf
LoadModule helloworld_module modules/t02.so
<Location /helloworld>
 SetHandler helloworld
</Location>

3) start apache with -X
httpd -k start -X

4) open index.htm on a client browser and submit file PIC_12930. jpg.
You'll receive no response from server on a reasonable time. Debugging
this process reveal me that the problem was on ap_get_brigade function

I don't know if there is something wrong with my code or if there is
some bug on ap_get_brigade function. Any help will be very appreciate!

Thanks to everybody!

Important information:

Apache: version: 2.2.8
OS: Debian GNU Linux (kernel 2.4 or 2.6. it happens on both)

Re: ap_get_brigade hangs when submitting a muitipart/form-data

Posted by Moacir Schmidt <mo...@gmail.com>.
Thanks for your replay, Jarek. Unfortunately, ap_get_client_block was used
on my module's first version (currently version is named t02.c because
of this, eh eh). On my initial researchs I figured out that
ap_get_client_block is implemented using ap_get_brigade (as  you can see on
http_filters.c, ). I've read some apache developers public
messages suggesting that the ap_get_client_block could be deprecated in the
future. Then I decided to try another implementation using ap_get_brigades
hoping that the problem could be solved. Unfortunately, first version hangs
exactly as second one did.

Anyway, i'm posting the first version using ap_get_client_block that has
exactly the same problem:
t01.c:
---------------------------
#include <httpd.h>
#include <http_protocol.h>
#include <http_config.h>
static int helloworld_handler(request_rec* r)
{
  int rc;
  if (!r->handler || strcmp(r->handler, "helloworld"))
    return DECLINED;
  ap_set_content_type(r, "text/html;charset=ascii"); // debug purposes
  if ((rc=ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))!=OK) {
    return rc;
  }
  if (ap_should_client_block(r)) {
    char argsbuf[HUGE_STRING_LEN];
    int rsize, len_read, rpos=0;
    long length = r->remaining;
    char buf[45000];
    while ((len_read=ap_get_client_block(r,argsbuf,sizeof(argsbuf))) > 0) {
      if ((rpos+len_read) > length) {
        rsize =  length-rpos;
      } else {
        rsize = len_read;
      }
      memcpy((char *)buf+rpos,argsbuf,rsize);
      rpos += rsize;
      ap_rputs(buf,r); // debug purposes
    }
  }
  return OK;
}
static void register_hooks(apr_pool_t* pool)
{
  ap_hook_handler(helloworld_handler, NULL, NULL, APR_HOOK_MIDDLE);
}
module AP_MODULE_DECLARE_DATA helloworld_module = {
  STANDARD20_MODULE_STUFF,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  register_hooks
};
------------------------------





On Thu, Feb 14, 2008 at 5:14 PM, Jarek Kucypera <ja...@netstellar.com>
wrote:

>
> > I don't know if there is something wrong with my code or if there is
> > some bug on ap_get_brigade function. Any help will be very appreciate!
> >
> ap_get_brigade is designed to be used in input filters.
> If you want read request data in your content handler,
> you must use ap_should_client_block and ap_get_client_block.
>
> Regards,
> J.K.
>

Re: ap_get_brigade hangs when submitting a muitipart/form-data

Posted by Moacir Schmidt <mo...@gmail.com>.
***News***: After some days and headaches, I figured out that this problem
occurs only on my local machine running IE (6 or 7) on Windows Server 2003
accessing Debian Linux (sarge or etch) on a virtual machine at the same
computar (using vmware) with apache 2.2.3-4 or 2.2.8.

It does not happen on my production apache server.

I still have no idea why above configuration causes this strange
behaviour...but the problem seems not so important now!

On 2/15/08, Brian Smith <br...@briansmith.org> wrote:
>
> Jarek Kucypera wrote:
> > ap_get_brigade is designed to be used in input filters.
> > If you want read request data in your content handler, you
> > must use ap_should_client_block and ap_get_client_block.
>
> There are lots of modules that ship with Apache that are using
> ap_get_brigade, and the source code for ap_get_client_block specifically
> warns against using ap_get_client_block. So, I believe the above is not
> true.
>
> - Brian
>
>

Re: ap_get_brigade hangs when submitting a muitipart/form-data

Posted by Jarek Kucypera <ja...@netstellar.com>.
> Where can I find out which APIs are official vs. unofficial

comments in the source code

J.K.

Re: ap_get_brigade hangs when submitting a muitipart/form-data

Posted by Nick Kew <ni...@webthing.com>.
On Sat, 16 Feb 2008 07:36:41 -0800
"Brian Smith" <br...@briansmith.org> wrote:


> Where can I find out which APIs are official vs. unofficial?

If it's in include/something.h, it's official.

-- 
Nick Kew

Application Development with Apache - the Apache Modules Book
http://www.apachetutor.org/

RE: ap_get_brigade hangs when submitting a muitipart/form-data

Posted by Brian Smith <br...@briansmith.org>.
> In 2.2.2 ap_get_client_block is the official api, i believe 
> the same in 2.2.8, my opinion is to obey apis or once you get 
> into trouble when upgrading.
> The modules using ap_get_grigade happen to come from the 
> authors of the api, so it looks like they just now, how to 
> navigate "under the surface" of the api.

Where can I find out which APIs are official vs. unofficial?

- Brian


Re: ap_get_brigade hangs when submitting a muitipart/form-data

Posted by Jarek Kucypera <ja...@netstellar.com>.
>
>> ap_get_brigade is designed to be used in input filters.
>> If you want read request data in your content handler, you 
>> must use ap_should_client_block and ap_get_client_block.
>>     
>
> There are lots of modules that ship with Apache that are using
> ap_get_brigade, and the source code for ap_get_client_block specifically
> warns against using ap_get_client_block. So, I believe the above is not
> true.
>   

In 2.2.2 ap_get_client_block is the official api, i believe the same in 
2.2.8, my opinion is to
obey apis or once you get into trouble when upgrading.
The modules using ap_get_grigade happen to come from the authors of the 
api, so it looks
like they just now, how to navigate "under the surface" of the api.

J.K.


RE: ap_get_brigade hangs when submitting a muitipart/form-data

Posted by Brian Smith <br...@briansmith.org>.
Jarek Kucypera wrote:
> ap_get_brigade is designed to be used in input filters.
> If you want read request data in your content handler, you 
> must use ap_should_client_block and ap_get_client_block.

There are lots of modules that ship with Apache that are using
ap_get_brigade, and the source code for ap_get_client_block specifically
warns against using ap_get_client_block. So, I believe the above is not
true.

- Brian


Re: ap_get_brigade hangs when submitting a muitipart/form-data

Posted by Jarek Kucypera <ja...@netstellar.com>.
> I don't know if there is something wrong with my code or if there is
> some bug on ap_get_brigade function. Any help will be very appreciate!
>
ap_get_brigade is designed to be used in input filters.
If you want read request data in your content handler,
you must use ap_should_client_block and ap_get_client_block.

Regards,
J.K.