talloc: add talloc_set_strict_owner_mode()
[metze/samba/wip.git] / lib / talloc / talloc.c
index f68b1eb5ece523583be18c44609959e6d7c5a7c4..6913c088516056da2df12df6d2d1b74e1800ab12 100644 (file)
 static void *null_context;
 static void *autofree_context;
 static void *no_owner_context = TALLOC_MAGIC_NO_OWNER;
+static const char *strict_owner_mode;
 static inline int _talloc_free(void *ptr);
 
 struct talloc_reference_handle {
@@ -142,6 +143,11 @@ struct talloc_chunk {
 #define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15)
 #define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
 
+void _talloc_set_strict_owner_mode(const char *location)
+{
+       strict_owner_mode = location;
+}
+
 static void (*talloc_abort_fn)(const char *reason);
 
 void talloc_set_abort_fn(void (*abort_fn)(const char *reason))
@@ -613,6 +619,15 @@ static inline int _talloc_free(void *ptr)
                if (is_child) {
                        _talloc_free(tc->refs);
                        return _talloc_free(ptr);
+               } else if (talloc_parent_is_no_owner(ptr)) {
+                       /*
+                        * if no_owner_context is already the owner
+                        * we free the last reference (first in the list)
+                        *
+                        * This path is ownly reached if
+                        * talloc_set_strict_owner_mode() wasn't used
+                        */
+                       return _talloc_free(tc->refs);
                } else {
                        /*
                         * we can't free if we have refs,
@@ -687,10 +702,11 @@ void *_talloc_steal(const void *new_ctx, const void *ptr)
                return NULL;
        }
 
-       if (unlikely(talloc_parent_is_no_owner(ptr) &&
+       if (unlikely(strict_owner_mode &&
+                    talloc_parent_is_no_owner(ptr) &&
                     new_ctx != no_owner_context)) {
-//             talloc_abort_no_owner_free();
-//             return NULL;
+               talloc_abort_no_owner_free();
+               return NULL;
        }
 
        if (unlikely(new_ctx == TALLOC_MAGIC_NO_OWNER)) {
@@ -1029,7 +1045,8 @@ int talloc_free(void *ptr)
                return 0;
        }
 
-       if (unlikely(talloc_parent_is_no_owner(ptr))) {
+       if (unlikely(strict_owner_mode &&
+                    talloc_parent_is_no_owner(ptr))) {
                talloc_abort_no_owner_free();
                return -1;
        }