axis-c-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Chris Darroch (JIRA)" <j...@apache.org>
Subject [jira] Commented: (AXIS2C-399) memory leaks
Date Tue, 14 Nov 2006 18:57:38 GMT
    [ http://issues.apache.org/jira/browse/AXIS2C-399?page=comments#action_12449734 ] 
            
Chris Darroch commented on AXIS2C-399:
--------------------------------------

Just to reiterate a point, I think that if Axis2/C could be converted to the use of
APR memory pools, this kind of concern about memory leakage would be
significantly reduced, if not erased.  I provided an initial patch here:

http://marc.theaimsgroup.com/?l=axis-c-dev&m=116259914508051&w=2

where mod_axis2 is modified to override the standard AXIS2_MALLOC()
and AXIS2_FREE().  In particular, AXIS2_FREE() becomes a no-op, and
AXIS2_MALLOC() allocates from an APR memory pool.

During httpd configuration, the memory pool is the one that's passed to
the child_init hook function -- this pool is suitable for use when creating
"configuration" data that should persist throughout the life of a process.

Then, for each request, the pool that's used is the thread-private pool for
that individual request.  Anything that's allocated during the request is then
cleared automatically after httpd finishes serving the request.

The axis2_http_server could be fairly easily modified to do a similar thing.
You do need to remove any calls to AXIS2_REALLOC(); I did this in the
main code but rampart and a few other places would need editing as well.

The problem I've had is that after a few requests, you get a segfault.  My
assumption is that this must be caused by some place where the code
is editing the "config" data structures within each request.  Any such editing
should either be removed -- i.e., do it during the child_init phase -- or
should use the pool that was used for the original "config" data.

This can be done by:

a) Creating a thread mutex and sub-pool in child_init, using the sub-pool
for all "config" allocations, and then storing pointers to the mutex and sub-pool
in the "config" data structures.

b) During a request, acquiring the mutex, using the "config" sub-pool to modify
the "config" data structures, and releasing the mutex.

Those steps ensure that the "config" data can be modified in a thread-safe
manner during request handling.  The sub-pool is required to ensure that
you don't try to use the original pool passed during child_init, because at
request time some other thread in a different part of httpd might be using it.
You can use it in child_init safely because httpd is single-threaded at that
early stage, but not if you're planning on modifying the stuff you do in child_init
later on.

If that can be done, then you can later simply remove all calls to AXIS2_FREE()
and friends (like AXIOM_NODE_FREE_TREE() and so forth)!  This has
multiple advantages.

First, it's much harder to accidentally free something too early and cause
a segfault.  If you do get a segfault, you know you must be messing with
"config" data somewhere.

Second, when dealing with the normal code path (where no errors occur),
you don't have to worry about freeing everything you allocate.  This is
presumably the source of the memory leaks caught by valgrind, since the
bug reporter's service is just a stub.  Given all the code that might
execute to handle a single request, and all the different normal code paths
(depending on the type of request, whether MTOM or addressing or rampart
or whatever is in use, etc.), that's a lot of code you otherwise have to
review and verify has absolutely no leaks.  Hard.

Third, when dealing with error conditions, you can also simplify your code.
In many functions, an error condition requires you to free all the internal
structures that have been allocated so far during the function's execution.
Often each subsequent error handling block has to free one additional data
structure.  It's easy to lose track of what needs to be freed when writing
such code, especially because it's unlikely any coder would actually test
each error handling block -- so they'll only execute when someone actually
encounters an error, and then errors in the error handling block itself
(such as memory freed too early, or twice) end up disguising the error
condition!  If you can just forget about freeing memory, these error handling
blocks of code often become much simpler and easier to write and verify.

Anyway, that's my long-winded 2 cents worth.

> memory leaks
> ------------
>
>                 Key: AXIS2C-399
>                 URL: http://issues.apache.org/jira/browse/AXIS2C-399
>             Project: Axis2-C
>          Issue Type: Bug
>    Affects Versions: Current (Nightly)
>         Environment: linux simple http server
>            Reporter: Marc Giger
>
> I see massive memory leaks with the Simple Axis2 HTTP Server.
> Because I can't test it with mod_axis2 I can only report it with the simple http server.
> Here are two valgrind outputs:
> The first one is with a shoot to the sample echo service:
> Started Simple Axis2 HTTP Server ...
> ==19904==
> ==19904== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 45 from
> 1) ==19904== malloc/free: in use at exit: 71,000 bytes in 1,038 blocks.
> ==19904== malloc/free: 15,119 allocs, 14,081 frees, 1,513,871 bytes
> allocated. ==19904== For counts of detected errors, rerun with: -v
> ==19904== searching for pointers to 1,038 not-freed blocks.
> ==19904== checked 8,697,064 bytes.
> ==19904==
> ==19904== LEAK SUMMARY:
> ==19904==    definitely lost: 70,309 bytes in 1,023 blocks.
> ==19904==      possibly lost: 136 bytes in 1 blocks.
> ==19904==    still reachable: 555 bytes in 14 blocks.
> ==19904==         suppressed: 0 bytes in 0 blocks.
> ==19904== Use --leak-check=full to see details of leaked memory.
> This second one is with a service built with the skeleton generator and
> no data binding but just XML in/out:
> Started Simple Axis2 HTTP Server ...
> ==13034==
> ==13034== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 46 from
> 1) ==13034== malloc/free: in use at exit: 200,214 bytes in 1,025 blocks.
> ==13034== malloc/free: 24,826 allocs, 23,801 frees, 2,676,022 bytes
> allocated. ==13034== For counts of detected errors, rerun with: -v
> ==13034== searching for pointers to 1,025 not-freed blocks.
> ==13034== checked 8,697,064 bytes.
> ==13034==
> ==13034== LEAK SUMMARY:
> ==13034==    definitely lost: 199,523 bytes in 1,010 blocks.
> ==13034==      possibly lost: 136 bytes in 1 blocks.
> ==13034==    still reachable: 555 bytes in 14 blocks.
> ==13034==         suppressed: 0 bytes in 0 blocks.
> ==13034== Use --leak-check=full to see details of leaked memory.
> My service function looks like the following:
> axiom_node_t* axis2_skel_TestService_Test (const axis2_env_t *env,
> 					      axiom_node_t* param0 )
> {
> 	return param0;
> }
> In this case i sent a document with about 34KB in size.

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

---------------------------------------------------------------------
To unsubscribe, e-mail: axis-c-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: axis-c-dev-help@ws.apache.org


Mime
View raw message