Author: ivan
Date: Wed Feb 25 14:23:00 2015
New Revision: 1662222

URL: http://svn.apache.org/r1662222
Log:
On the 'reuse-ra-session' branch: Resolve memory leak.

* subversion/libsvn_client/ra_cache.c
  (): Include "svn_pools.h".

  (cache_entry_t): Add SESSION_POOL member to have an option to destroy
   CACHE_ENTRY structure itself.

  (close_ra_session, remove_inactive_entry): Destroy SESSION_POOL
   instead of closing RA session -- we have other resources allocated
   for RA session, like RA callback baton, cache_entry etc.

  (open_new_session): New helper, factored out from
   svn_client__ra_cache_open_session().

  (svn_client__ra_cache_open_session): Create separate subpool for
   each CACHE_ENTRY and destroy it on error.

* subversion/include/private/svn_ra_private.h
* subversion/libsvn_ra/ra_loader.c
  (svn_ra__close): Remove -- we do not use it now.

Modified:
    
subversion/branches/reuse-ra-session/subversion/include/private/svn_ra_private.h
    subversion/branches/reuse-ra-session/subversion/libsvn_client/ra_cache.c
    subversion/branches/reuse-ra-session/subversion/libsvn_ra/ra_loader.c

Modified: 
subversion/branches/reuse-ra-session/subversion/include/private/svn_ra_private.h
URL: 
http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/include/private/svn_ra_private.h?rev=1662222&r1=1662221&r2=1662222&view=diff
==============================================================================
--- 
subversion/branches/reuse-ra-session/subversion/include/private/svn_ra_private.h
 (original)
+++ 
subversion/branches/reuse-ra-session/subversion/include/private/svn_ra_private.h
 Wed Feb 25 14:23:00 2015
@@ -65,16 +65,6 @@ svn_ra__dup_session(svn_ra_session_t **n
                     apr_pool_t *result_pool,
                     apr_pool_t *scratch_pool);
 
-/**
- * Close the conneection managed by @a session and destroy the
- * session. When this function returns, the @a session pointer
- * is no longer valid.
- *
- * @since New in 1.9.
- */
-void
-svn_ra__close(svn_ra_session_t *session);
-
 /* Equivalent to svn_ra__assert_capable_server()
    for SVN_RA_CAPABILITY_MERGEINFO. */
 svn_error_t *

Modified: 
subversion/branches/reuse-ra-session/subversion/libsvn_client/ra_cache.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_client/ra_cache.c?rev=1662222&r1=1662221&r2=1662222&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_client/ra_cache.c 
(original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_client/ra_cache.c 
Wed Feb 25 14:23:00 2015
@@ -28,6 +28,7 @@
 #include "svn_dirent_uri.h"
 #include "private/svn_ra_private.h"
 #include "svn_private_config.h"
+#include "svn_pools.h"
 
 #include "ra_cache.h"
 #include "private/svn_debug.h"
@@ -92,6 +93,9 @@ typedef struct cache_entry_t
   /* The actual RA session. */
   svn_ra_session_t *session;
 
+  /* POOL for this RA session and cache entry. */
+  apr_pool_t *session_pool;
+
   /* POOL that owns this session. NULL if session is not used. */
   apr_pool_t *owner_pool;
 
@@ -409,12 +413,13 @@ close_ra_session(void *data)
           --ra_cache->inactive_count;
         }
 
-      /* Close and invalidate the session. */
-      cache_entry->session = NULL;
-      svn_ra__close(session);
-
       RA_CACHE_LOG(("SESSION(%d): Closed\n", cache_entry->id));
       RA_CACHE_STATS(++ra_cache->stat.close);
+
+      /* Close and invalidate the session. */
+      svn_pool_destroy(cache_entry->session_pool);
+      cache_entry->session = NULL;
+      cache_entry->session_pool = NULL;
     }
   else
     {
@@ -438,16 +443,10 @@ remove_inactive_entry(svn_client__ra_cac
                       cache_entry_t *cache_entry,
                       svn_boolean_t expired)
 {
-  svn_ra_session_t *const session = cache_entry->session;
-
   APR_RING_REMOVE(cache_entry, freelist);
   APR_RING_ELEM_INIT(cache_entry, freelist);
   --ra_cache->inactive_count;
 
-  /* Close and invalidate the session. */
-  cache_entry->session = NULL;
-  svn_ra__close(session);
-
   RA_CACHE_LOG(("SESSION(%d): Closed (%s)\n", cache_entry->id,
                 (expired ? "expired" : "expunged")));
   RA_CACHE_STATS(
@@ -455,6 +454,11 @@ remove_inactive_entry(svn_client__ra_cac
         ++ra_cache->stat.expire;
       else
         ++ra_cache->stat.expunge);
+
+  /* Close and invalidate the session. */
+  svn_pool_destroy(cache_entry->session_pool);
+  cache_entry->session = NULL;
+  cache_entry->session_pool = NULL;
 }
 
 /* Limit the size of the inactive session list in RA_CACHE and remove
@@ -530,6 +534,71 @@ find_session_by_url(cache_entry_t **cach
   return SVN_NO_ERROR;
 }
 
+/* Helper for svn_client__ra_cache_open_session(). Allocates new
+   *CACHE_ENTRY_P and opens new RA session using BASE_URL, UUID,
+   CBTABLE and CALLBACK_BATON arguments. RA session and CACHE_ENTRY
+   will be allocated from SESSION_POOL and linked lifetime of
+   OWNER_POOL. */
+static svn_error_t *
+open_new_session(cache_entry_t **cache_entry_p,
+                 const char **corrected_p,
+                 svn_client__ra_cache_t *ra_cache,
+                 const char *base_url,
+                 const char *uuid,
+                 svn_ra_callbacks2_t *cbtable,
+                 void *callback_baton,
+                 apr_pool_t *session_pool,
+                 apr_pool_t *owner_pool)
+{
+  cache_entry_t *cache_entry;
+  svn_ra_callbacks2_t *ra_callbacks;
+  svn_ra_session_t *session;
+
+  cache_entry = apr_pcalloc(session_pool, sizeof(*cache_entry));
+  APR_RING_ELEM_INIT(cache_entry, freelist);
+  cache_entry->session_pool = session_pool;
+
+  SVN_ERR(svn_ra_create_callbacks(&ra_callbacks, session_pool));
+  ra_callbacks->open_tmp_file = open_tmp_file;
+  ra_callbacks->get_wc_prop = get_wc_prop;
+  ra_callbacks->set_wc_prop = set_wc_prop;
+  ra_callbacks->push_wc_prop = push_wc_prop;
+  ra_callbacks->invalidate_wc_props = invalidate_wc_props;
+  ra_callbacks->auth_baton = cbtable->auth_baton; /* new-style */
+  ra_callbacks->progress_func = progress_func;
+  ra_callbacks->progress_baton = cache_entry;
+  ra_callbacks->cancel_func = cancel_func;
+  ra_callbacks->get_client_string = get_client_string;
+  ra_callbacks->get_wc_contents = get_wc_contents;
+  ra_callbacks->check_tunnel_func = check_tunnel_func;
+  ra_callbacks->open_tunnel_func = open_tunnel_func;
+  ra_callbacks->tunnel_baton = cache_entry;
+
+  cache_entry->owner_pool = owner_pool;
+  cache_entry->cb_table = cbtable;
+  cache_entry->cb_baton = callback_baton;
+  cache_entry->id = ra_cache->next_id;
+
+  SVN_ERR(svn_ra_open4(&session, corrected_p, base_url, uuid,
+                       ra_callbacks, cache_entry,
+                       ra_cache->config, session_pool));
+
+  if (corrected_p && *corrected_p)
+    {
+      /* Caller is ready to follow redirection and we got redirection.
+         Just return corrected URL without RA session. */
+      return SVN_NO_ERROR;
+    }
+
+  cache_entry->session = session;
+
+  SVN_ERR(svn_ra_get_repos_root2(session, &cache_entry->root_url,
+                                 session_pool));
+
+  *cache_entry_p = cache_entry;
+  return SVN_NO_ERROR;
+}
+
 /* Convert a public client context pointer to a pointer to the RA
    session cache in the private client context. */
 static svn_client__ra_cache_t *
@@ -604,49 +673,30 @@ svn_client__ra_cache_open_session(svn_ra
   else
     {
       /* No existing RA session found. Open new one. */
-      svn_ra_callbacks2_t *ra_callbacks;
-      svn_ra_session_t *session;
-
-      cache_entry = apr_pcalloc(ra_cache->pool, sizeof(*cache_entry));
-      APR_RING_ELEM_INIT(cache_entry, freelist);
-
-      SVN_ERR(svn_ra_create_callbacks(&ra_callbacks, ra_cache->pool));
-      ra_callbacks->open_tmp_file = open_tmp_file;
-      ra_callbacks->get_wc_prop = get_wc_prop;
-      ra_callbacks->set_wc_prop = set_wc_prop;
-      ra_callbacks->push_wc_prop = push_wc_prop;
-      ra_callbacks->invalidate_wc_props = invalidate_wc_props;
-      ra_callbacks->auth_baton = cbtable->auth_baton; /* new-style */
-      ra_callbacks->progress_func = progress_func;
-      ra_callbacks->progress_baton = cache_entry;
-      ra_callbacks->cancel_func = cancel_func;
-      ra_callbacks->get_client_string = get_client_string;
-      ra_callbacks->get_wc_contents = get_wc_contents;
-      ra_callbacks->check_tunnel_func = check_tunnel_func;
-      ra_callbacks->open_tunnel_func = open_tunnel_func;
-      ra_callbacks->tunnel_baton = cache_entry;
-
-      cache_entry->owner_pool = result_pool;
-      cache_entry->cb_table = cbtable;
-      cache_entry->cb_baton = callback_baton;
-      cache_entry->id = ra_cache->next_id;
+      svn_error_t *err;
+      apr_pool_t *session_pool = svn_pool_create(ra_cache->pool);
 
-      SVN_ERR(svn_ra_open4(&session, corrected_p, base_url, uuid,
-                           ra_callbacks, cache_entry,
-                           ra_cache->config, ra_cache->pool));
+      err = open_new_session(&cache_entry, corrected_p, ra_cache,
+                             base_url, uuid, cbtable, callback_baton,
+                             session_pool, result_pool);
+      if (err)
+        {
+          svn_pool_destroy(session_pool);
+          return svn_error_trace(err);
+        }
 
       if (corrected_p && *corrected_p)
         {
+          /* Copy corrected url to RESULT_POOL before cleaning
+             SESSION_POOL. */
+          *corrected_p = apr_pstrdup(result_pool, *corrected_p);
+
+          svn_pool_destroy(session_pool);
           /* Caller is ready to follow redirection and we got redirection.
              Just return corrected URL without RA session. */
           return SVN_NO_ERROR;
         }
 
-      cache_entry->session = session;
-
-      SVN_ERR(svn_ra_get_repos_root2(session, &cache_entry->root_url,
-                                     ra_cache->pool));
-
       RA_CACHE_LOG(("SESSION(%d): Open('%s')\n", cache_entry->id, base_url));
       RA_CACHE_STATS(++ra_cache->stat.open);
 

Modified: subversion/branches/reuse-ra-session/subversion/libsvn_ra/ra_loader.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_ra/ra_loader.c?rev=1662222&r1=1662221&r2=1662222&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_ra/ra_loader.c 
(original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_ra/ra_loader.c Wed 
Feb 25 14:23:00 2015
@@ -228,14 +228,6 @@ check_ra_version(const svn_version_t *ra
 
 /* -------------------------------------------------------------- */
 
-/*** Private Inter-Library Interfaces ***/
-void
-svn_ra__close(svn_ra_session_t *session)
-{
-  if (session && session->pool)
-    apr_pool_destroy(session->pool);
-}
-
 /* -------------------------------------------------------------- */
 
 /*** Public Interfaces ***/


Reply via email to