dev  

Re: Changing the order of cleanup for some core objects

Bojan Smojver
Mon, 21 Jul 2008 23:12:53 -0700

On Mon, 2008-07-21 at 12:38 +0200, Mladen Turk wrote:

> I still don't know how to solve that problem effectively, so
> any ideas are welcome.

A "volatile" pool idea...

-- 
Bojan
Index: memory/unix/apr_pools.c
===================================================================
--- memory/unix/apr_pools.c	(revision 678599)
+++ memory/unix/apr_pools.c	(working copy)
@@ -503,6 +503,7 @@
 #endif /* defined(NETWARE) */
     cleanup_t            *pre_cleanups;
     cleanup_t            *free_pre_cleanups;
+    int                  is_volatile;
 };
 
 #define SIZEOF_POOL_T       APR_ALIGN_DEFAULT(sizeof(apr_pool_t))
@@ -523,6 +524,11 @@
 static apr_file_t *file_stderr = NULL;
 #endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) */
 
+#if APR_HAS_THREADS
+static apr_thread_mutex_t *volatile_mutex = NULL;
+#endif
+static apr_hash_t *volatile_pools = NULL;
+
 /*
  * Local functions
  */
@@ -588,6 +594,16 @@
 
     apr_allocator_owner_set(global_allocator, global_pool);
 
+#if APR_HAS_THREADS
+    if ((rv = apr_thread_mutex_create(&volatile_mutex,
+                                      APR_THREAD_MUTEX_DEFAULT,
+                                      global_pool)) != APR_SUCCESS) {
+        return rv;
+    }
+#endif /* APR_HAS_THREADS */
+
+    volatile_pools = apr_hash_make(global_pool);
+
     return APR_SUCCESS;
 }
 
@@ -599,6 +615,8 @@
     if (--apr_pools_initialized)
         return;
 
+    apr_thread_mutex_destroy(volatile_mutex);
+
     apr_pool_destroy(global_pool); /* This will also destroy the mutex */
     global_pool = NULL;
 
@@ -759,6 +777,20 @@
     apr_memnode_t *active;
     apr_allocator_t *allocator;
 
+    if (pool->is_volatile) {
+#if APR_HAS_THREADS
+        if (volatile_mutex)
+            apr_thread_mutex_lock(volatile_mutex);
+#endif
+
+        apr_hash_set(volatile_pools, &pool, sizeof(pool), NULL);
+
+#if APR_HAS_THREADS
+        if (volatile_mutex)
+            apr_thread_mutex_unlock(volatile_mutex);
+#endif
+    }
+
     /* Run pre destroy cleanups */
     run_cleanups(&pool->pre_cleanups);
     pool->pre_cleanups = NULL;
@@ -902,11 +934,41 @@
         pool->ref = NULL;
     }
 
+    pool->is_volatile = 0;
+
     *newpool = pool;
 
     return APR_SUCCESS;
 }
 
+APR_DECLARE(apr_status_t)
+apr_pool_volatile_create_ex(apr_pool_t **newpool,
+                            apr_pool_t *parent,
+                            apr_abortfunc_t abort_fn,
+                            apr_allocator_t *allocator)
+{
+    apr_status_t rv;
+
+    rv = apr_pool_create_ex(newpool, parent, abort_fn, allocator);
+
+    if (*newpool) {
+#if APR_HAS_THREADS
+        if (volatile_mutex)
+            apr_thread_mutex_lock(volatile_mutex);
+#endif
+
+        (*newpool)->is_volatile = 1;
+        apr_hash_set(volatile_pools, newpool, sizeof(*newpool), *newpool);
+
+#if APR_HAS_THREADS
+        if (volatile_mutex)
+            apr_thread_mutex_unlock(volatile_mutex);
+#endif
+    }
+
+    return rv;
+}
+
 /* Deprecated. Renamed to apr_pool_create_unmanaged_ex
  */
 APR_DECLARE(apr_status_t) apr_pool_create_core_ex(apr_pool_t **newpool,
@@ -1735,6 +1797,39 @@
     return APR_SUCCESS;
 }
 
+APR_DECLARE(apr_status_t)
+apr_pool_volatile_create_ex_debug(apr_pool_t **newpool,
+                            apr_pool_t *parent,
+                            apr_abortfunc_t abort_fn,
+                            apr_allocator_t *allocator,
+                            const char *file_line)
+{
+    apr_status_t rv;
+
+    rv = apr_pool_create_ex_debug(newpool, parent, abort_fn, allocator);
+
+    if (*newpool) {
+#if APR_HAS_THREADS
+        if (volatile_mutex)
+            apr_thread_mutex_lock(volatile_mutex);
+#endif
+
+        (*newpool)->is_volatile = 1;
+        apr_hash_set(volatile_pools, newpool, sizeof(*newpool), *newpool);
+
+#if APR_HAS_THREADS
+        if (volatile_mutex)
+            apr_thread_mutex_unlock(volatile_mutex);
+#endif
+    }
+
+#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE)
+    apr_pool_log_event(pool, "CREATE", file_line, 1);
+#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE) */
+
+    return rv;
+}
+
 APR_DECLARE(apr_status_t) apr_pool_create_core_ex_debug(apr_pool_t **newpool,
                                                    apr_abortfunc_t abort_fn,
                                                    apr_allocator_t *allocator,
@@ -2504,6 +2599,16 @@
     return apr_pool_create_ex(newpool, parent, abort_fn, allocator);
 }
 
+APR_DECLARE(apr_status_t)
+apr_pool_volatile_create_ex_debug(apr_pool_t **newpool,
+                                  apr_pool_t *parent,
+                                  apr_abortfunc_t abort_fn,
+                                  apr_allocator_t *allocator,
+                                                   const char *file_line)
+{
+    return apr_pool_volatile_create_ex(newpool, parent, abort_fn, allocator);
+}
+
 APR_DECLARE(apr_status_t) apr_pool_create_core_ex_debug(apr_pool_t **newpool,
                                                    apr_abortfunc_t abort_fn,
                                                    apr_allocator_t *allocator,
Index: include/apr_pools.h
===================================================================
--- include/apr_pools.h	(revision 678599)
+++ include/apr_pools.h	(working copy)
@@ -189,6 +189,22 @@
                                              apr_allocator_t *allocator);
 
 /**
+ * Create a new volatile pool.
+ * @param newpool The pool we have just created.
+ * @param parent The parent pool.  If this is NULL, the new pool is a root
+ *        pool.  If it is non-NULL, the new pool will inherit all
+ *        of its parent pool's attributes, except the apr_pool_t will
+ *        be a sub-pool.
+ * @param abort_fn A function to use if the pool cannot allocate more memory.
+ * @param allocator The allocator to use with the new pool.  If NULL the
+ *        allocator of the parent pool will be used.
+ */
+APR_DECLARE(apr_status_t)
+apr_pool_volatile_create_ex(apr_pool_t **newpool,
+                            apr_pool_t *parent,
+                            apr_abortfunc_t abort_fn,
+                            apr_allocator_t *allocator);
+/**
  * Create a new pool.
  * @deprecated @see apr_pool_create_unmanaged_ex.
  */
@@ -303,6 +319,28 @@
 #endif
 
 /**
+ * Create a new volatile pool.
+ * @param newpool The pool we have just created.
+ * @param parent The parent pool.  If this is NULL, the new pool is a root
+ *        pool.  If it is non-NULL, the new pool will inherit all
+ *        of its parent pool's attributes, except the apr_pool_t will
+ *        be a sub-pool.
+ */
+#if defined(DOXYGEN)
+APR_DECLARE(apr_status_t) apr_pool_volatile_create(apr_pool_t **newpool,
+                                                   apr_pool_t *parent);
+#else
+#if APR_POOL_DEBUG
+#define apr_pool_volatile_create(newpool, parent) \
+    apr_pool_volatile_create_ex_debug(newpool, parent, NULL, NULL, \
+                                      APR_POOL__FILE_LINE__)
+#else
+#define apr_pool_volatile_create(newpool, parent) \
+    apr_pool_volatile_create_ex(newpool, parent, NULL, NULL)
+#endif
+#endif
+
+/**
  * Create a new pool.
  * @param newpool The pool we have just created.
  */