> Date: Thu, 31 Mar 2011 15:01:48 +0200 > Subject: Re: cpu 100% > From: sor...@gmail.com > To: modules-dev@httpd.apache.org > > On Thu, Mar 31, 2011 at 14:32, Niko Goutte <ngou...@hotmail.com> wrote: > > > > Hello, > > > > I developped an apache module which send small data coming from file. > > A client request from file through a Get request and data are sent with > > block > > size equals to 100KB. > > One 100KB buffer is allocated in the pool, then each buffer are used to > > create > > one bucket that will be sent just after being inserted into the brigade. > > To sum up: > > ---------------------------------------------------------------------------------------------------------------------------- > > apr_bucket_brigade *bb; > > apr_bucket* b; > > > > bb = apr_brigade_create(r->pool, r->connection->bucket_alloc); > > Buf = apr_palloc(r->pool,100KB); > > > > while(lastBufferToSend==false) > > { > > Processing(Buf); > > > > b = apr_bucket_pool_create(Buf ,size, r->pool, > > r->connection->bucket_alloc) ; > > > > APR_BRIGADE_INSERT_TAIL(bb, b); > > APR_BRIGADE_INSERT_TAIL(bb,apr_bucket_flush_create(bb->bucket_alloc)); > > > > if(lastBufferToSend) > > { > > APR_BRIGADE_INSERT_TAIL(bb,apr_bucket_eos_create(bb->bucket_alloc)); > > } > > > > rv = ap_pass_brigade(r->output_filters, bb); > > if (rv != APR_SUCCESS) > > { > > return HTTP_INTERNAL_SERVER_ERROR; > > } > > > > apr_brigade_cleanup(bb); > > } > > > > apr_brigade_destroy(bb); > > ---------------------------------------------------------------------------------------------------------------------------- > > > > > > I want to call ap_pass_brigade for each buffer because I want the module to > > send immediatly 100KB. > > > > Clients don't have to wait for the complete processing of the file more than > > 2GB. They receive small blocks until the end. > > > > -------------------------------------------------------------------------------------------------------------------------- > > > > > > Apache Server is in prefork mode. > > <IfModule prefork.c> > > StartServers 8 > > MinSpareServers 5 > > MaxSpareServers 20 > > ServerLimit 256 > > MaxClients 256 > > MaxRequestsPerChild 4000 > > </IfModule> > > > > In worker mode, everything is excepted 10 bytes that are send in addition > > including value > > "\n256\r\n" : it is very strange because the sum of every chunk > > corrsesponds exactly to the expected size. > > <IfModule worker.c> > > StartServers 2 > > MinSpareThreads 25 > > MaxSpareThreads 75 > > ThreadPerChild 64 > > MaxClients 1024 > > MaxRequestsPerChild 0 > > </IfModule> > > > > -------------------------------------------------------------------------------------------------------------------------- > > > > MY PROBLEMS: > > > > In prefork mode, the first 8 client requests (which corresponds to the > > StartServers = 8) are well processed. My client received all data, > > everything is fine. > > But the 9th freezes the module in ap_pass_brigade function. httpd is > > freezed with 100% cpu on this process. > > > > In worker mode, it is ok excepted the 10 bytes added. It seems that it is > > linked with apr_brigade_destroy or apr_bucket_delete(b). > > > Are you sure that the value of lastBufferToSend changes in your while-loop? > > Can you post your exact code to see how you add the 10 bytes? > > Sorin ------------------------------------------------------------------------------------------------------------------------------- HERE IS: #include <httpd.h> #include <http_config.h> #include <http_protocol.h> #include <http_request.h> #include <http_log.h> #include <ap_compat.h> #include <apr_buckets.h> #include <apr_strings.h>
#define ASE_FILE_SIZE 512000 #define ASE_BUFFER_SIZE 104858 module AP_MODULE_DECLARE_DATA ase_mod_module; #define ASE_MOD_HANDLER "ase-mod.extensions" static int ase_mod_handler(request_rec *r) { apr_status_t rv = APR_SUCCESS; apr_bucket_brigade* bb = NULL;; apr_bucket* b = NULL;; char filename[256]; /* First, some housekeeping. */ if (((!r->handler) != 0)|| (strcmp(r->handler, ASE_MOD_HANDLER))) { /* r->handler wasn't "ase_mod", so it's none of our business */ ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,"Decline processing file %s is not %s and handler %s", r->filename,ASE_MOD_HANDLER,r->handler); return DECLINED; } if (r->method_number != M_GET) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,"Error METHOD_NOT_ALLOWED (%d)",r->method_number); return HTTP_METHOD_NOT_ALLOWED; } ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,"%s",r->the_request); // Construct filename strncpy(filename, r->filename, sizeof(filename) / sizeof(char) - 1); filename[sizeof(filename) / sizeof(char) - 1] = '\0'; ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,"filename = %s",filename); int DataSize = ASE_FILE_SIZE; ap_set_content_type(r, "video/ase"); ap_update_mtime(r, r->finfo.mtime); ap_set_last_modified(r); apr_table_setn(r->headers_out, "Accept-Ranges", "bytes"); r->vlist_validator = apr_pstrcat(r->pool, "X",apr_itoa(r->pool, DataSize), "\"", NULL); ap_set_etag(r); char content_range[64]; sprintf(content_range,"bytes %d-%d/%d",0,ASE_FILE_SIZE-1,ASE_FILE_SIZE); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,"Add content range %s",content_range); apr_table_setn(r->headers_out, "Content-Range",content_range); r->status = HTTP_OK; bb = apr_brigade_create(r->pool, r->connection->bucket_alloc); char* Buf; Buf = apr_palloc(r->pool,ASE_BUFFER_SIZE); int size = ASE_BUFFER_SIZE; unsigned int count = 0; while(DataSize>0) { if((DataSize - size)<0) { size = DataSize; } memset(Buf,count,size); b = apr_bucket_pool_create(Buf ,size, r->pool, r->connection->bucket_alloc) ; APR_BRIGADE_INSERT_TAIL(bb, b); APR_BRIGADE_INSERT_TAIL(bb,apr_bucket_flush_create(bb->bucket_alloc)); if(DataSize <= size) { APR_BRIGADE_INSERT_TAIL(bb,apr_bucket_eos_create(bb->bucket_alloc)); ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,"APR_BRIGADE_INSERT_TAIL EOS Bucket"); } rv = ap_pass_brigade(r->output_filters, bb); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,"HTTP_INTERNAL_SERVER_ERROR ap_pass_brigade "); r->status = HTTP_INTERNAL_SERVER_ERROR; return r->status; } DataSize = DataSize - size; count++; ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,"ap_pass_brigade, DataSize = %d and Size = %d",DataSize, size ); apr_brigade_cleanup(bb); } ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,"Out of While"); apr_bucket_delete(b); //apr_brigade_destroy(bb); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,"End return %d",r->status); return r->status; } static void ase_mod_hooks(apr_pool_t *pool) { if(pool){} ap_hook_handler(ase_mod_handler, NULL, NULL, APR_HOOK_MIDDLE); } module AP_MODULE_DECLARE_DATA ase_mod_module = { STANDARD20_MODULE_STUFF, NULL, /*create dir config */ NULL, /*merge dir config */ NULL, /*create server config*/ NULL, /*merge server config */ NULL, /*command table */ ase_mod_hooks }; ------------------------------------------------------------------------------------------------------------------------------- I would like to understand first why this module crashes with a segmentation fault in prefork mode on the 9th simple request: curl http://IP/filename.ext where .ext is the "ase-mod.extensions" Thank you.