summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES6
-rw-r--r--include/apr_mmap.h19
-rw-r--r--mmap/unix/mmap.c37
-rw-r--r--mmap/win32/mmap.c35
4 files changed, 47 insertions, 50 deletions
diff --git a/CHANGES b/CHANGES
index 6c25b276c..9af68a453 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,11 @@
Changes with APR 0.9.2
+ *) Changed apr_mmap_dup() and friends so that there's no longer any
+ is_owner concept on the mmaped region, but rather something more
+ along the lines of a reference count. This allows the old apr_mmap_t
+ to still be used safely when the new apr_mmap_t is in a disjoint pool.
+ [Cliff Woolley, Sander Striker]
+
*) Fix a bug in apr_hash_merge() which caused the last entry in the
overlay hash to be lost. PR 10522 [Jeff Trawick]
diff --git a/include/apr_mmap.h b/include/apr_mmap.h
index 44e51be08..2c2278c99 100644
--- a/include/apr_mmap.h
+++ b/include/apr_mmap.h
@@ -58,6 +58,7 @@
#include "apr.h"
#include "apr_pools.h"
#include "apr_errno.h"
+#include "apr_ring.h"
#include "apr_file_io.h" /* for apr_file_t */
#ifdef BEOS
@@ -115,8 +116,12 @@ struct apr_mmap_t {
void *mm;
/** The amount of data in the mmap */
apr_size_t size;
- /** Whether this object is reponsible for doing the munmap */
- int is_owner;
+ /** @deprecated this field is no longer used and will be removed
+ * in APR 1.0 */
+ int unused;
+ /** ring of apr_mmap_t's that reference the same
+ * mmap'ed region; acts in place of a reference count */
+ APR_RING_ENTRY(apr_mmap_t) link;
};
#if APR_HAS_MMAP || defined(DOXYGEN)
@@ -174,8 +179,8 @@ APR_DECLARE(apr_status_t) apr_mmap_create(apr_mmap_t **newmmap,
* @param new_mmap The structure to duplicate into.
* @param old_mmap The mmap to duplicate.
* @param p The pool to use for new_mmap.
- * @param transfer_ownership Whether responsibility for destroying
- * the memory-mapped segment is transferred from old_mmap to new_mmap
+ * @param transfer_ownership DEPRECATED: this param is now ignored
+ * and should be removed prior to APR 1.0
*/
APR_DECLARE(apr_status_t) apr_mmap_dup(apr_mmap_t **new_mmap,
apr_mmap_t *old_mmap,
@@ -185,10 +190,11 @@ APR_DECLARE(apr_status_t) apr_mmap_dup(apr_mmap_t **new_mmap,
#if defined(DOXYGEN)
/**
* Transfer the specified MMAP to a different pool
- * @param new_mmap The structure to duplicate into.
+ * @param new_mmap The structure to duplicate into.
* @param old_mmap The file to transfer.
* @param p The pool to use for new_mmap.
- * @remark After this call, old_mmap cannot be used
+ * @deprecated Just use apr_mmap_dup(). The transfer_ownership flag will
+ * go away soon anyway.
*/
APR_DECLARE(apr_status_t) apr_mmap_setaside(apr_mmap_t **new_mmap,
apr_mmap_t *old_mmap,
@@ -197,7 +203,6 @@ APR_DECLARE(apr_status_t) apr_mmap_setaside(apr_mmap_t **new_mmap,
#define apr_mmap_setaside(new_mmap, old_mmap, p) apr_mmap_dup(new_mmap, old_mmap, p, 1)
#endif /* DOXYGEN */
-
/**
* Remove a mmap'ed.
* @param mm The mmap'ed file.
diff --git a/mmap/unix/mmap.c b/mmap/unix/mmap.c
index 4a54b860e..707702662 100644
--- a/mmap/unix/mmap.c
+++ b/mmap/unix/mmap.c
@@ -83,13 +83,17 @@
static apr_status_t mmap_cleanup(void *themmap)
{
apr_mmap_t *mm = themmap;
- int rv;
+ apr_mmap_t *next = APR_RING_NEXT(mm,link);
+ int rv = 0;
- if (!mm->is_owner) {
- return APR_EINVAL;
- }
- else if (mm->mm == (void *)-1) {
- return APR_ENOENT;
+ /* we no longer refer to the mmaped region */
+ APR_RING_REMOVE(mm,link);
+ APR_RING_NEXT(mm,link) = NULL;
+ APR_RING_PREV(mm,link) = NULL;
+
+ if (next != mm) {
+ /* more references exist, so we're done */
+ return APR_SUCCESS;
}
#ifdef BEOS
@@ -163,7 +167,7 @@ APR_DECLARE(apr_status_t) apr_mmap_create(apr_mmap_t **new,
(*new)->mm = mm;
(*new)->size = size;
(*new)->cntxt = cont;
- (*new)->is_owner = 1;
+ APR_RING_ELEM_INIT(*new, link);
/* register the cleanup... */
apr_pool_cleanup_register((*new)->cntxt, (void*)(*new), mmap_cleanup,
@@ -179,21 +183,10 @@ APR_DECLARE(apr_status_t) apr_mmap_dup(apr_mmap_t **new_mmap,
*new_mmap = (apr_mmap_t *)apr_pmemdup(p, old_mmap, sizeof(apr_mmap_t));
(*new_mmap)->cntxt = p;
- /* The old_mmap can transfer ownership only if the old_mmap itself
- * is an owner of the mmap'ed segment.
- */
- if (old_mmap->is_owner) {
- if (transfer_ownership) {
- (*new_mmap)->is_owner = 1;
- old_mmap->is_owner = 0;
- apr_pool_cleanup_kill(old_mmap->cntxt, old_mmap, mmap_cleanup);
- apr_pool_cleanup_register(p, *new_mmap, mmap_cleanup,
- apr_pool_cleanup_null);
- }
- else {
- (*new_mmap)->is_owner = 0;
- }
- }
+ APR_RING_INSERT_AFTER(old_mmap, *new_mmap, link);
+
+ apr_pool_cleanup_register(p, *new_mmap, mmap_cleanup,
+ apr_pool_cleanup_null);
return APR_SUCCESS;
}
diff --git a/mmap/win32/mmap.c b/mmap/win32/mmap.c
index a113ecfcf..4053ab868 100644
--- a/mmap/win32/mmap.c
+++ b/mmap/win32/mmap.c
@@ -66,13 +66,17 @@
static apr_status_t mmap_cleanup(void *themmap)
{
apr_mmap_t *mm = themmap;
+ apr_mmap_t *next = APR_RING_NEXT(mm,link);
apr_status_t rv = 0;
- if (!mm->is_owner) {
- return APR_EINVAL;
- }
- else if (!mm->mhandle) {
- return APR_ENOENT;
+ /* we no longer refer to the mmaped region */
+ APR_RING_REMOVE(mm,link);
+ APR_RING_NEXT(mm,link) = NULL;
+ APR_RING_PREV(mm,link) = NULL;
+
+ if (next != mm) {
+ /* more references exist, so we're done */
+ return APR_SUCCESS;
}
if (mm->mv) {
@@ -163,7 +167,7 @@ APR_DECLARE(apr_status_t) apr_mmap_create(apr_mmap_t **new, apr_file_t *file,
(*new)->mm = (char*)((*new)->mv) + (*new)->poffset;
(*new)->size = size;
(*new)->cntxt = cont;
- (*new)->is_owner = 1;
+ APR_RING_ELEM_INIT(*new, link);
/* register the cleanup... */
apr_pool_cleanup_register((*new)->cntxt, (void*)(*new), mmap_cleanup,
@@ -179,21 +183,10 @@ APR_DECLARE(apr_status_t) apr_mmap_dup(apr_mmap_t **new_mmap,
*new_mmap = (apr_mmap_t *)apr_pmemdup(p, old_mmap, sizeof(apr_mmap_t));
(*new_mmap)->cntxt = p;
- /* The old_mmap can transfer ownership only if the old_mmap itself
- * is an owner of the mmap'ed segment.
- */
- if (old_mmap->is_owner) {
- if (transfer_ownership) {
- (*new_mmap)->is_owner = 1;
- old_mmap->is_owner = 0;
- apr_pool_cleanup_kill(old_mmap->cntxt, old_mmap, mmap_cleanup);
- apr_pool_cleanup_register(p, *new_mmap, mmap_cleanup,
- apr_pool_cleanup_null);
- }
- else {
- (*new_mmap)->is_owner = 0;
- }
- }
+ APR_RING_INSERT_AFTER(old_mmap, *new_mmap, link);
+
+ apr_pool_cleanup_register(p, *new_mmap, mmap_cleanup,
+ apr_pool_cleanup_null);
return APR_SUCCESS;
}