diff --git a/UPGRADE.txt b/UPGRADE.txt index 0696adb290..d9d5cec533 100644 --- a/UPGRADE.txt +++ b/UPGRADE.txt @@ -32,6 +32,9 @@ chan_dahdi: Caller-ID detection. Core: + - The REF_DEBUG compiler flag is now used to enable refdebug by default. + The setting can be overridden in asterisk.conf by setting refdebug in + the options category. No recompile is required to enable/disable it. AMI: - The 'ModuleCheck' Action's Version key will no longer show the module diff --git a/apps/app_queue.c b/apps/app_queue.c index 0b8204c33b..d2c6406bec 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -1814,50 +1814,27 @@ static void queue_member_follower_removal(struct call_queue *queue, struct membe ao2_callback(queue->members, OBJ_NODATA | OBJ_MULTIPLE, queue_member_decrement_followers, &pos); } -#ifdef REF_DEBUG #define queue_ref(q) _queue_ref(q, "", __FILE__, __LINE__, __PRETTY_FUNCTION__) #define queue_unref(q) _queue_unref(q, "", __FILE__, __LINE__, __PRETTY_FUNCTION__) #define queue_t_ref(q, tag) _queue_ref(q, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__) #define queue_t_unref(q, tag) _queue_unref(q, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__) -#define queues_t_link(c, q, tag) __ao2_link_debug(c, q, 0, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__) -#define queues_t_unlink(c, q, tag) __ao2_unlink_debug(c, q, 0, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__) +#define queues_t_link(c, q, tag) ao2_t_link(c, q, tag) +#define queues_t_unlink(c, q, tag) ao2_t_unlink(c, q, tag) static inline struct call_queue *_queue_ref(struct call_queue *q, const char *tag, const char *file, int line, const char *filename) { - __ao2_ref_debug(q, 1, tag, file, line, filename); + __ao2_ref(q, 1, tag, file, line, filename); return q; } static inline struct call_queue *_queue_unref(struct call_queue *q, const char *tag, const char *file, int line, const char *filename) { if (q) { - __ao2_ref_debug(q, -1, tag, file, line, filename); + __ao2_ref(q, -1, tag, file, line, filename); } return NULL; } -#else - -#define queue_t_ref(q, tag) queue_ref(q) -#define queue_t_unref(q, tag) queue_unref(q) -#define queues_t_link(c, q, tag) ao2_t_link(c, q, tag) -#define queues_t_unlink(c, q, tag) ao2_t_unlink(c, q, tag) - -static inline struct call_queue *queue_ref(struct call_queue *q) -{ - ao2_ref(q, 1); - return q; -} - -static inline struct call_queue *queue_unref(struct call_queue *q) -{ - if (q) { - ao2_ref(q, -1); - } - return NULL; -} -#endif - /*! \brief Set variables of queue */ static void set_queue_variables(struct call_queue *q, struct ast_channel *chan) { diff --git a/build_tools/cflags.xml b/build_tools/cflags.xml index 1a2e78ff87..b91cf5af5b 100644 --- a/build_tools/cflags.xml +++ b/build_tools/cflags.xml @@ -5,7 +5,7 @@ core - + extended diff --git a/build_tools/make_buildopts_h b/build_tools/make_buildopts_h index 55d08ba71a..df506edbe1 100755 --- a/build_tools/make_buildopts_h +++ b/build_tools/make_buildopts_h @@ -13,6 +13,20 @@ END TMP=`${GREP} -e "^MENUSELECT_CFLAGS" menuselect.makeopts | sed 's/MENUSELECT_CFLAGS\=//g' | sed 's/-D//g'` for x in ${TMP}; do echo "#define ${x} 1" + if test "${x}" = "DONT_OPTIMIZE" \ + -o "${x}" = "BETTER_BACKTRACES" \ + -o "${x}" = "LOTS_OF_SPANS" \ + -o "${x}" = "BUILD_NATIVE" \ + -o "${x}" = "REF_DEBUG" \ + -o "${x}" = "AO2_DEBUG" \ + -o "${x}" = "REBUILD_PARSERS" \ + -o "${x}" = "RADIO_RELAX" \ + -o "${x}" = "DEBUG_SCHEDULER" \ + -o "${x}" = "DETECT_DEADLOCKS" \ + -o "${x}" = "DUMP_SCHEDULER" ; then + # These aren't ABI affecting options, keep them out of AST_BUILDOPTS + continue + fi if test "x${BUILDOPTS}" != "x" ; then BUILDOPTS="${BUILDOPTS}, ${x}" else diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 3ee92da5ec..aa616cde11 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -8599,9 +8599,9 @@ struct sip_pvt *__sip_alloc(ast_string_field callid, struct ast_sockaddr *addr, { struct sip_pvt *p; - p = __ao2_alloc_debug(sizeof(*p), sip_destroy_fn, + p = __ao2_alloc(sizeof(*p), sip_destroy_fn, AO2_ALLOC_OPT_LOCK_MUTEX, "allocate a dialog(pvt) struct", - file, line, func, 1); + file, line, func); if (!p) { return NULL; } @@ -9178,7 +9178,7 @@ static struct sip_pvt *__find_call(struct sip_request *req, struct ast_sockaddr struct sip_pvt tmp_dialog = { .callid = callid, }; - sip_pvt_ptr = __ao2_find_debug(dialogs, &tmp_dialog, OBJ_POINTER, + sip_pvt_ptr = __ao2_find(dialogs, &tmp_dialog, OBJ_POINTER, "find_call in dialogs", file, line, func); if (sip_pvt_ptr) { /* well, if we don't find it-- what IS in there? */ /* Found the call */ @@ -9193,7 +9193,7 @@ static struct sip_pvt *__find_call(struct sip_request *req, struct ast_sockaddr struct sip_pvt *fork_pvt = NULL; struct match_req_args args = { 0, }; int found; - struct ao2_iterator *iterator = __ao2_callback_debug(dialogs, + struct ao2_iterator *iterator = __ao2_callback(dialogs, OBJ_POINTER | OBJ_MULTIPLE, dialog_find_multiple, &tmp_dialog, @@ -9243,7 +9243,7 @@ static struct sip_pvt *__find_call(struct sip_request *req, struct ast_sockaddr /* This is likely a forked Request that somehow resulted in us receiving multiple parts of the fork. * RFC 3261 section 8.2.2.2, Indicate that we want to merge requests by sending a 482 response. */ transmit_response_using_temp(callid, addr, 1, intended_method, req, "482 (Loop Detected)"); - __ao2_ref_debug(sip_pvt_ptr, -1, "pvt did not match incoming SIP msg, unref from search.", + __ao2_ref(sip_pvt_ptr, -1, "pvt did not match incoming SIP msg, unref from search.", file, line, func); ao2_iterator_destroy(iterator); dialog_unref(fork_pvt, "unref fork_pvt"); @@ -9255,7 +9255,7 @@ static struct sip_pvt *__find_call(struct sip_request *req, struct ast_sockaddr /* fall through */ case SIP_REQ_NOT_MATCH: default: - __ao2_ref_debug(sip_pvt_ptr, -1, "pvt did not match incoming SIP msg, unref from search", + __ao2_ref(sip_pvt_ptr, -1, "pvt did not match incoming SIP msg, unref from search", file, line, func); break; } diff --git a/configs/samples/asterisk.conf.sample b/configs/samples/asterisk.conf.sample index e4883ec97a..818f5c2fb4 100644 --- a/configs/samples/asterisk.conf.sample +++ b/configs/samples/asterisk.conf.sample @@ -14,6 +14,7 @@ astsbindir => /usr/sbin [options] ;verbose = 3 ;debug = 3 +;refdebug = yes ; Enable reference count debug logging. ;alwaysfork = yes ; Same as -F at startup. ;nofork = yes ; Same as -f at startup. ;quiet = yes ; Same as -q at startup. diff --git a/contrib/Makefile b/contrib/Makefile index 2c91b47abf..37f4df4392 100644 --- a/contrib/Makefile +++ b/contrib/Makefile @@ -20,10 +20,8 @@ clean: include $(ASTTOPDIR)/Makefile.rules install: - if [ -n "$(findstring REF_DEBUG,$(MENUSELECT_CFLAGS))" ]; then \ - $(INSTALL) -d "$(DESTDIR)$(ASTDATADIR)/scripts"; \ - $(INSTALL) -m 755 scripts/refcounter.py "$(DESTDIR)$(ASTDATADIR)/scripts/refcounter.py"; \ - fi + $(INSTALL) -d "$(DESTDIR)$(ASTDATADIR)/scripts"; \ + $(INSTALL) -m 755 scripts/refcounter.py "$(DESTDIR)$(ASTDATADIR)/scripts/refcounter.py"; \ uninstall: rm -f "$(DESTDIR)$(ASTDATADIR)/scripts/refcounter.py" diff --git a/contrib/scripts/refcounter.py b/contrib/scripts/refcounter.py index 1a97e90fd3..1f4b375170 100755 --- a/contrib/scripts/refcounter.py +++ b/contrib/scripts/refcounter.py @@ -1,8 +1,8 @@ #!/usr/bin/env python """Process a ref debug log - This file will process a log file created by the REF_DEBUG - build option in Asterisk. + This file will process a log file created by enabling + the refdebug config option in asterisk.conf. See http://www.asterisk.org for more information about the Asterisk project. Please do not directly contact diff --git a/include/asterisk/astobj2.h b/include/asterisk/astobj2.h index 1c3c2e8ad7..de35bb3240 100644 --- a/include/asterisk/astobj2.h +++ b/include/asterisk/astobj2.h @@ -141,31 +141,11 @@ list. However there is no ordering among elements. /* \note DEBUGGING REF COUNTS BIBLE: An interface to help debug refcounting is provided -in this package. It is dependent on the REF_DEBUG macro being -defined via menuselect and in using variants of the normal ao2_xxxx -function that are named ao2_t_xxxx instead, with an extra argument, -a string that will be printed out into the refs log file when the -refcount for an object is changed. +in this package. It is dependent on the refdebug being enabled in +asterisk.conf. - these ao2_t_xxx variants are provided: - -ao2_t_alloc(arg1, arg2, arg3) -ao2_t_ref(arg1,arg2,arg3) -ao2_t_container_alloc(arg1,arg2,arg3,arg4) -ao2_t_link(arg1, arg2, arg3) -ao2_t_unlink(arg1, arg2, arg3) -ao2_t_callback(arg1,arg2,arg3,arg4,arg5) -ao2_t_find(arg1,arg2,arg3,arg4) -ao2_t_iterator_next(arg1, arg2) - -If you study each argument list, you will see that these functions all have -one extra argument than their ao2_xxx counterpart. The last argument in -each case is supposed to be a string pointer, a "tag", that should contain -enough of an explanation, that you can pair operations that increment the -ref count, with operations that are meant to decrement the refcount. - -Each of these calls will generate at least one line of output in in the refs -log files. These lines look like this: +Each of the reference manipulations will generate one line of output in in the refs +log file. These lines look like this: ... 0x8756f00,+1,1234,chan_sip.c,22240,load_module,**constructor**,allocate users 0x86e3408,+1,1234,chan_sip.c,22241,load_module,**constructor**,allocate peers @@ -210,61 +190,29 @@ follows: context for the ref change. Note that any subsequent columns are considered to be part of this tag. -Sometimes you have some helper functions to do object ref/unref +Sometimes you have some helper functions to do object create/ref/unref operations. Using these normally hides the place where these functions were called. To get the location where these functions -were called to appear in /refs, you can do this sort of thing: +were called to appear in refs log, you can do this sort of thing: -#ifdef REF_DEBUG -#define dialog_ref(arg1,arg2) dialog_ref_debug((arg1),(arg2), __FILE__, __LINE__, __PRETTY_FUNCTION__) -#define dialog_unref(arg1,arg2) dialog_unref_debug((arg1),(arg2), __FILE__, __LINE__, __PRETTY_FUNCTION__) -static struct sip_pvt *dialog_ref_debug(struct sip_pvt *p, const char *tag, const char *file, int line, const char *func) +#define my_t_alloc(data,tag) my_alloc_debug((data), tag, __FILE__, __LINE__, __PRETTY_FUNCTION__) +#define my_alloc(data) my_t_alloc((data), "") + +static struct mydata *my_alloc_debug(void *data, + const char *tag, const char *file, int line, const char *func) { + struct mydata *p; + + p = __ao2_alloc(sizeof(*p), NULL, AO2_ALLOC_OPT_LOCK_MUTEX, tag, file, line, func); if (p) { - ao2_ref_debug(p, 1, tag, file, line, func); - } else { - ast_log(LOG_ERROR, "Attempt to Ref a null pointer\n"); + p->data = data; } return p; } -static struct sip_pvt *dialog_unref_debug(struct sip_pvt *p, const char *tag, const char *file, int line, const char *func) -{ - if (p) { - ao2_ref_debug(p, -1, tag, file, line, func); - } - return NULL; -} -#else -static struct sip_pvt *dialog_ref(struct sip_pvt *p, const char *tag) -{ - if (p) { - ao2_ref(p, 1); - } else { - ast_log(LOG_ERROR, "Attempt to Ref a null pointer\n"); - } - return p; -} - -static struct sip_pvt *dialog_unref(struct sip_pvt *p, const char *tag) -{ - if (p) { - ao2_ref(p, -1); - } - return NULL; -} -#endif - -In the above code, note that the "normal" helper funcs call ao2_ref() as -normal, and the "helper" functions call ao2_ref_debug directly with the -file, function, and line number info provided. You might find this -well worth the effort to help track these function calls in the code. - To find out why objects are not destroyed (a common bug), you can -edit the source file to use the ao2_t_* variants, enable REF_DEBUG -in menuselect, and add a descriptive tag to each call. Recompile, -and run Asterisk, exit asterisk with "core stop gracefully", which should -result in every object being destroyed. +enable refdebug in asterisk.conf. Run asterisk, exit with "core stop gracefully". +This should result in every object being destroyed. Then, you can "sort -k 1 {AST_LOG_DIR}/refs > x1" to get a sorted list of all the objects, or you can use "contrib/script/refcounter.py" to scan @@ -439,50 +387,23 @@ enum ao2_alloc_opts { * - the returned pointer cannot be free()'d or realloc()'ed; * rather, we just call ao2_ref(o, -1); * + * \note refdebug logging is skipped if debug_msg is NULL + * * @{ */ -#if defined(REF_DEBUG) - #define ao2_t_alloc_options(data_size, destructor_fn, options, debug_msg) \ - __ao2_alloc_debug((data_size), (destructor_fn), (options), (debug_msg), __FILE__, __LINE__, __PRETTY_FUNCTION__, 1) + __ao2_alloc((data_size), (destructor_fn), (options), (debug_msg), __FILE__, __LINE__, __PRETTY_FUNCTION__) #define ao2_alloc_options(data_size, destructor_fn, options) \ - __ao2_alloc_debug((data_size), (destructor_fn), (options), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 1) + __ao2_alloc((data_size), (destructor_fn), (options), "", __FILE__, __LINE__, __PRETTY_FUNCTION__) #define ao2_t_alloc(data_size, destructor_fn, debug_msg) \ - __ao2_alloc_debug((data_size), (destructor_fn), AO2_ALLOC_OPT_LOCK_MUTEX, (debug_msg), __FILE__, __LINE__, __PRETTY_FUNCTION__, 1) + __ao2_alloc((data_size), (destructor_fn), AO2_ALLOC_OPT_LOCK_MUTEX, (debug_msg), __FILE__, __LINE__, __PRETTY_FUNCTION__) #define ao2_alloc(data_size, destructor_fn) \ - __ao2_alloc_debug((data_size), (destructor_fn), AO2_ALLOC_OPT_LOCK_MUTEX, "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 1) + __ao2_alloc((data_size), (destructor_fn), AO2_ALLOC_OPT_LOCK_MUTEX, "", __FILE__, __LINE__, __PRETTY_FUNCTION__) -#elif defined(__AST_DEBUG_MALLOC) - -#define ao2_t_alloc_options(data_size, destructor_fn, options, debug_msg) \ - __ao2_alloc_debug((data_size), (destructor_fn), (options), (debug_msg), __FILE__, __LINE__, __PRETTY_FUNCTION__, 0) -#define ao2_alloc_options(data_size, destructor_fn, options) \ - __ao2_alloc_debug((data_size), (destructor_fn), (options), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 0) - -#define ao2_t_alloc(data_size, destructor_fn, debug_msg) \ - __ao2_alloc_debug((data_size), (destructor_fn), AO2_ALLOC_OPT_LOCK_MUTEX, (debug_msg), __FILE__, __LINE__, __PRETTY_FUNCTION__, 0) -#define ao2_alloc(data_size, destructor_fn) \ - __ao2_alloc_debug((data_size), (destructor_fn), AO2_ALLOC_OPT_LOCK_MUTEX, "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 0) - -#else - -#define ao2_t_alloc_options(data_size, destructor_fn, options, debug_msg) \ - __ao2_alloc((data_size), (destructor_fn), (options)) -#define ao2_alloc_options(data_size, destructor_fn, options) \ - __ao2_alloc((data_size), (destructor_fn), (options)) - -#define ao2_t_alloc(data_size, destructor_fn, debug_msg) \ - __ao2_alloc((data_size), (destructor_fn), AO2_ALLOC_OPT_LOCK_MUTEX) -#define ao2_alloc(data_size, destructor_fn) \ - __ao2_alloc((data_size), (destructor_fn), AO2_ALLOC_OPT_LOCK_MUTEX) - -#endif - -void *__ao2_alloc_debug(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, const char *tag, - const char *file, int line, const char *func, int ref_debug) attribute_warn_unused_result; -void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options) attribute_warn_unused_result; +void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, + const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result; /*! @} */ @@ -507,20 +428,12 @@ void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned in * can go away is when we release our reference, and it is * the last one in existence. * + * \note refdebug logging is skipped if tag is NULL * @{ */ -#ifdef REF_DEBUG - -#define ao2_t_ref(o,delta,tag) __ao2_ref_debug((o), (delta), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__) -#define ao2_ref(o,delta) __ao2_ref_debug((o), (delta), "", __FILE__, __LINE__, __PRETTY_FUNCTION__) - -#else - -#define ao2_t_ref(o,delta,tag) __ao2_ref((o), (delta)) -#define ao2_ref(o,delta) __ao2_ref((o), (delta)) - -#endif +#define ao2_t_ref(o,delta,tag) __ao2_ref((o), (delta), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__) +#define ao2_ref(o,delta) __ao2_ref((o), (delta), "", __FILE__, __LINE__, __PRETTY_FUNCTION__) /*! * \brief Retrieve the ao2 options used to create the object. @@ -550,8 +463,7 @@ unsigned int ao2_options_get(void *obj); #define ao2_bump(obj) \ ao2_t_bump((obj), "") -int __ao2_ref_debug(void *o, int delta, const char *tag, const char *file, int line, const char *func); -int __ao2_ref(void *o, int delta); +int __ao2_ref(void *o, int delta, const char *tag, const char *file, int line, const char *func); /*! * \since 12.4.0 @@ -848,20 +760,11 @@ struct ao2_global_obj { * * \return Nothing */ -#ifdef REF_DEBUG #define ao2_t_global_obj_release(holder, tag) \ __ao2_global_obj_release(&holder, (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder) #define ao2_global_obj_release(holder) \ __ao2_global_obj_release(&holder, "", __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder) -#else - -#define ao2_t_global_obj_release(holder, tag) \ - __ao2_global_obj_release(&holder, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder) -#define ao2_global_obj_release(holder) \ - __ao2_global_obj_release(&holder, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder) -#endif - void __ao2_global_obj_release(struct ao2_global_obj *holder, const char *tag, const char *file, int line, const char *func, const char *name); /*! @@ -879,20 +782,11 @@ void __ao2_global_obj_release(struct ao2_global_obj *holder, const char *tag, co * \retval Reference to previous global ao2 object stored. * \retval NULL if no object available. */ -#ifdef REF_DEBUG #define ao2_t_global_obj_replace(holder, obj, tag) \ __ao2_global_obj_replace(&holder, (obj), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder) #define ao2_global_obj_replace(holder, obj) \ __ao2_global_obj_replace(&holder, (obj), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder) -#else - -#define ao2_t_global_obj_replace(holder, obj, tag) \ - __ao2_global_obj_replace(&holder, (obj), NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder) -#define ao2_global_obj_replace(holder, obj) \ - __ao2_global_obj_replace(&holder, (obj), NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder) -#endif - void *__ao2_global_obj_replace(struct ao2_global_obj *holder, void *obj, const char *tag, const char *file, int line, const char *func, const char *name) attribute_warn_unused_result; /*! @@ -911,20 +805,11 @@ void *__ao2_global_obj_replace(struct ao2_global_obj *holder, void *obj, const c * \retval 0 The global object was previously empty * \retval 1 The global object was not previously empty */ -#ifdef REF_DEBUG #define ao2_t_global_obj_replace_unref(holder, obj, tag) \ __ao2_global_obj_replace_unref(&holder, (obj), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder) #define ao2_global_obj_replace_unref(holder, obj) \ __ao2_global_obj_replace_unref(&holder, (obj), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder) -#else - -#define ao2_t_global_obj_replace_unref(holder, obj, tag) \ - __ao2_global_obj_replace_unref(&holder, (obj), NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder) -#define ao2_global_obj_replace_unref(holder, obj) \ - __ao2_global_obj_replace_unref(&holder, (obj), NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder) -#endif - int __ao2_global_obj_replace_unref(struct ao2_global_obj *holder, void *obj, const char *tag, const char *file, int line, const char *func, const char *name); /*! @@ -937,20 +822,11 @@ int __ao2_global_obj_replace_unref(struct ao2_global_obj *holder, void *obj, con * \retval Reference to current ao2 object stored in the holder. * \retval NULL if no object available. */ -#ifdef REF_DEBUG #define ao2_t_global_obj_ref(holder, tag) \ __ao2_global_obj_ref(&holder, (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder) #define ao2_global_obj_ref(holder) \ __ao2_global_obj_ref(&holder, "", __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder) -#else - -#define ao2_t_global_obj_ref(holder, tag) \ - __ao2_global_obj_ref(&holder, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder) -#define ao2_global_obj_ref(holder) \ - __ao2_global_obj_ref(&holder, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder) -#endif - void *__ao2_global_obj_ref(struct ao2_global_obj *holder, const char *tag, const char *file, int line, const char *func, const char *name) attribute_warn_unused_result; @@ -1372,36 +1248,15 @@ struct ao2_container; * \note Destructor is set implicitly. */ -#if defined(REF_DEBUG) - #define ao2_t_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn, tag) \ - __ao2_container_alloc_hash_debug((ao2_options), (container_options), (n_buckets), (hash_fn), (sort_fn), (cmp_fn), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, 1) + __ao2_container_alloc_hash((ao2_options), (container_options), (n_buckets), (hash_fn), (sort_fn), (cmp_fn), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__) #define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn) \ - __ao2_container_alloc_hash_debug((ao2_options), (container_options), (n_buckets), (hash_fn), (sort_fn), (cmp_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 1) - -#elif defined(__AST_DEBUG_MALLOC) - -#define ao2_t_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn, tag) \ - __ao2_container_alloc_hash_debug((ao2_options), (container_options), (n_buckets), (hash_fn), (sort_fn), (cmp_fn), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, 0) -#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn) \ - __ao2_container_alloc_hash_debug((ao2_options), (container_options), (n_buckets), (hash_fn), (sort_fn), (cmp_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 0) - -#else - -#define ao2_t_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn, tag) \ - __ao2_container_alloc_hash((ao2_options), (container_options), (n_buckets), (hash_fn), (sort_fn), (cmp_fn)) -#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn) \ - __ao2_container_alloc_hash((ao2_options), (container_options), (n_buckets), (hash_fn), (sort_fn), (cmp_fn)) - -#endif + __ao2_container_alloc_hash((ao2_options), (container_options), (n_buckets), (hash_fn), (sort_fn), (cmp_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__) struct ao2_container *__ao2_container_alloc_hash(unsigned int ao2_options, - unsigned int container_options, unsigned int n_buckets, ao2_hash_fn *hash_fn, - ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn) attribute_warn_unused_result; -struct ao2_container *__ao2_container_alloc_hash_debug(unsigned int ao2_options, unsigned int container_options, unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn, - const char *tag, const char *file, int line, const char *func, int ref_debug) attribute_warn_unused_result; + const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result; /*! * \brief Allocate and initialize a list container. @@ -1418,34 +1273,14 @@ struct ao2_container *__ao2_container_alloc_hash_debug(unsigned int ao2_options, * \note Implemented as a degenerate hash table. */ -#if defined(REF_DEBUG) - #define ao2_t_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn, tag) \ - __ao2_container_alloc_list_debug((ao2_options), (container_options), (sort_fn), (cmp_fn), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, 1) + __ao2_container_alloc_list((ao2_options), (container_options), (sort_fn), (cmp_fn), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__) #define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn) \ - __ao2_container_alloc_list_debug((ao2_options), (container_options), (sort_fn), (cmp_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 1) - -#elif defined(__AST_DEBUG_MALLOC) - -#define ao2_t_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn, tag) \ - __ao2_container_alloc_list_debug((ao2_options), (container_options), (sort_fn), (cmp_fn), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, 0) -#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn) \ - __ao2_container_alloc_list_debug((ao2_options), (container_options), (sort_fn), (cmp_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 0) - -#else - -#define ao2_t_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn, tag) \ - __ao2_container_alloc_list((ao2_options), (container_options), (sort_fn), (cmp_fn)) -#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn) \ - __ao2_container_alloc_list((ao2_options), (container_options), (sort_fn), (cmp_fn)) - -#endif + __ao2_container_alloc_list((ao2_options), (container_options), (sort_fn), (cmp_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__) struct ao2_container *__ao2_container_alloc_list(unsigned int ao2_options, - unsigned int container_options, ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn) attribute_warn_unused_result; -struct ao2_container *__ao2_container_alloc_list_debug(unsigned int ao2_options, unsigned int container_options, ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn, - const char *tag, const char *file, int line, const char *func, int ref_debug) attribute_warn_unused_result; + const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result; /*! * \brief Allocate and initialize a red-black tree container. @@ -1461,34 +1296,14 @@ struct ao2_container *__ao2_container_alloc_list_debug(unsigned int ao2_options, * \note Destructor is set implicitly. */ -#if defined(REF_DEBUG) - #define ao2_t_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn, tag) \ - __ao2_container_alloc_rbtree_debug((ao2_options), (container_options), (sort_fn), (cmp_fn), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, 1) + __ao2_container_alloc_rbtree((ao2_options), (container_options), (sort_fn), (cmp_fn), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__) #define ao2_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn) \ - __ao2_container_alloc_rbtree_debug((ao2_options), (container_options), (sort_fn), (cmp_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 1) - -#elif defined(__AST_DEBUG_MALLOC) - -#define ao2_t_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn, tag) \ - __ao2_container_alloc_rbtree_debug((ao2_options), (container_options), (sort_fn), (cmp_fn), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, 0) -#define ao2_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn) \ - __ao2_container_alloc_rbtree_debug((ao2_options), (container_options), (sort_fn), (cmp_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 0) - -#else - -#define ao2_t_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn, tag) \ - __ao2_container_alloc_rbtree((ao2_options), (container_options), (sort_fn), (cmp_fn)) -#define ao2_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn) \ - __ao2_container_alloc_rbtree((ao2_options), (container_options), (sort_fn), (cmp_fn)) - -#endif + __ao2_container_alloc_rbtree((ao2_options), (container_options), (sort_fn), (cmp_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__) struct ao2_container *__ao2_container_alloc_rbtree(unsigned int ao2_options, unsigned int container_options, - ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn) attribute_warn_unused_result; -struct ao2_container *__ao2_container_alloc_rbtree_debug(unsigned int ao2_options, unsigned int container_options, ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn, - const char *tag, const char *file, int line, const char *func, int ref_debug) attribute_warn_unused_result; + const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result; /*! \brief * Returns the number of elements in a container. @@ -1528,24 +1343,13 @@ int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enu * \retval Clone container on success. * \retval NULL on error. */ -struct ao2_container *__ao2_container_clone(struct ao2_container *orig, enum search_flags flags) attribute_warn_unused_result; -struct ao2_container *__ao2_container_clone_debug(struct ao2_container *orig, enum search_flags flags, const char *tag, const char *file, int line, const char *func, int ref_debug) attribute_warn_unused_result; -#if defined(REF_DEBUG) +struct ao2_container *__ao2_container_clone(struct ao2_container *orig, enum search_flags flags, + const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result; -#define ao2_t_container_clone(orig, flags, tag) __ao2_container_clone_debug(orig, flags, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__, 1) -#define ao2_container_clone(orig, flags) __ao2_container_clone_debug(orig, flags, "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 1) - -#elif defined(__AST_DEBUG_MALLOC) - -#define ao2_t_container_clone(orig, flags, tag) __ao2_container_clone_debug(orig, flags, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__, 0) -#define ao2_container_clone(orig, flags) __ao2_container_clone_debug(orig, flags, "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 0) - -#else - -#define ao2_t_container_clone(orig, flags, tag) __ao2_container_clone(orig, flags) -#define ao2_container_clone(orig, flags) __ao2_container_clone(orig, flags) - -#endif +#define ao2_t_container_clone(orig, flags, tag) \ + __ao2_container_clone(orig, flags, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__) +#define ao2_container_clone(orig, flags) \ + __ao2_container_clone(orig, flags, "", __FILE__, __LINE__, __PRETTY_FUNCTION__) /*! * \brief Print output. @@ -1661,10 +1465,10 @@ void ao2_container_unregister(const char *name); * \note This function automatically increases the reference count to account * for the reference that the container now holds to the object. */ -#ifdef REF_DEBUG - -#define ao2_t_link(container, obj, tag) __ao2_link_debug((container), (obj), 0, (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__) -#define ao2_link(container, obj) __ao2_link_debug((container), (obj), 0, "", __FILE__, __LINE__, __PRETTY_FUNCTION__) +#define ao2_t_link(container, obj, tag) \ + __ao2_link((container), (obj), 0, (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__) +#define ao2_link(container, obj) \ + __ao2_link((container), (obj), 0, "", __FILE__, __LINE__, __PRETTY_FUNCTION__) /*! * \brief Add an object to a container. @@ -1684,21 +1488,13 @@ void ao2_container_unregister(const char *name); * \note This function automatically increases the reference count to account * for the reference that the container now holds to the object. */ -#define ao2_t_link_flags(container, obj, flags, tag) __ao2_link_debug((container), (obj), (flags), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__) -#define ao2_link_flags(container, obj, flags) __ao2_link_debug((container), (obj), (flags), "", __FILE__, __LINE__, __PRETTY_FUNCTION__) +#define ao2_t_link_flags(container, obj, flags, tag) \ + __ao2_link((container), (obj), (flags), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__) +#define ao2_link_flags(container, obj, flags) \ + __ao2_link((container), (obj), (flags), "", __FILE__, __LINE__, __PRETTY_FUNCTION__) -#else - -#define ao2_t_link(container, obj, tag) __ao2_link((container), (obj), 0) -#define ao2_link(container, obj) __ao2_link((container), (obj), 0) - -#define ao2_t_link_flags(container, obj, flags, tag) __ao2_link((container), (obj), (flags)) -#define ao2_link_flags(container, obj, flags) __ao2_link((container), (obj), (flags)) - -#endif - -int __ao2_link_debug(struct ao2_container *c, void *obj_new, int flags, const char *tag, const char *file, int line, const char *func); -int __ao2_link(struct ao2_container *c, void *obj_new, int flags); +int __ao2_link(struct ao2_container *c, void *obj_new, int flags, + const char *tag, const char *file, int line, const char *func); /*! * \brief Remove an object from a container @@ -1717,10 +1513,11 @@ int __ao2_link(struct ao2_container *c, void *obj_new, int flags); * reference to the object will be automatically released. (The * refcount will be decremented). */ -#ifdef REF_DEBUG -#define ao2_t_unlink(container, obj, tag) __ao2_unlink_debug((container), (obj), 0, (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__) -#define ao2_unlink(container, obj) __ao2_unlink_debug((container), (obj), 0, "", __FILE__, __LINE__, __PRETTY_FUNCTION__) +#define ao2_t_unlink(container, obj, tag) \ + __ao2_unlink((container), (obj), 0, (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__) +#define ao2_unlink(container, obj) \ + __ao2_unlink((container), (obj), 0, "", __FILE__, __LINE__, __PRETTY_FUNCTION__) /*! * \brief Remove an object from a container @@ -1741,25 +1538,17 @@ int __ao2_link(struct ao2_container *c, void *obj_new, int flags); * refcount will be decremented). */ -#define ao2_t_unlink_flags(container, obj, flags, tag) __ao2_unlink_debug((container), (obj), (flags), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__) -#define ao2_unlink_flags(container, obj, flags) __ao2_unlink_debug((container), (obj), (flags), "", __FILE__, __LINE__, __PRETTY_FUNCTION__) - -#else - -#define ao2_t_unlink(container, obj, tag) __ao2_unlink((container), (obj), 0) -#define ao2_unlink(container, obj) __ao2_unlink((container), (obj), 0) - -#define ao2_t_unlink_flags(container, obj, flags, tag) __ao2_unlink((container), (obj), (flags)) -#define ao2_unlink_flags(container, obj, flags) __ao2_unlink((container), (obj), (flags)) - -#endif - -void *__ao2_unlink_debug(struct ao2_container *c, void *obj, int flags, const char *tag, const char *file, int line, const char *func); -void *__ao2_unlink(struct ao2_container *c, void *obj, int flags); +#define ao2_t_unlink_flags(container, obj, flags, tag) \ + __ao2_unlink((container), (obj), (flags), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__) +#define ao2_unlink_flags(container, obj, flags) \ + __ao2_unlink((container), (obj), (flags), "", __FILE__, __LINE__, __PRETTY_FUNCTION__) +void *__ao2_unlink(struct ao2_container *c, void *obj, int flags, + const char *tag, const char *file, int line, const char *func); /*@} */ + /*! \brief * ao2_callback() is a generic function that applies cb_fn() to all objects * in a container, as described below. @@ -1842,26 +1631,15 @@ void *__ao2_unlink(struct ao2_container *c, void *obj, int flags); * * @{ */ -#ifdef REF_DEBUG #define ao2_t_callback(c, flags, cb_fn, arg, tag) \ - __ao2_callback_debug((c), (flags), (cb_fn), (arg), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__) + __ao2_callback((c), (flags), (cb_fn), (arg), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__) #define ao2_callback(c, flags, cb_fn, arg) \ - __ao2_callback_debug((c), (flags), (cb_fn), (arg), "", __FILE__, __LINE__, __PRETTY_FUNCTION__) + __ao2_callback((c), (flags), (cb_fn), (arg), "", __FILE__, __LINE__, __PRETTY_FUNCTION__) -#else - -#define ao2_t_callback(c, flags, cb_fn, arg, tag) \ - __ao2_callback((c), (flags), (cb_fn), (arg)) -#define ao2_callback(c, flags, cb_fn, arg) \ - __ao2_callback((c), (flags), (cb_fn), (arg)) - -#endif - -void *__ao2_callback_debug(struct ao2_container *c, enum search_flags flags, +void *__ao2_callback(struct ao2_container *c, enum search_flags flags, ao2_callback_fn *cb_fn, void *arg, const char *tag, const char *file, int line, const char *func); -void *__ao2_callback(struct ao2_container *c, enum search_flags flags, ao2_callback_fn *cb_fn, void *arg); /*! @} */ @@ -1880,50 +1658,27 @@ void *__ao2_callback(struct ao2_container *c, enum search_flags flags, ao2_callb * * \see ao2_callback() */ -#ifdef REF_DEBUG #define ao2_t_callback_data(container, flags, cb_fn, arg, data, tag) \ - __ao2_callback_data_debug((container), (flags), (cb_fn), (arg), (data), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__) + __ao2_callback_data((container), (flags), (cb_fn), (arg), (data), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__) #define ao2_callback_data(container, flags, cb_fn, arg, data) \ - __ao2_callback_data_debug((container), (flags), (cb_fn), (arg), (data), "", __FILE__, __LINE__, __PRETTY_FUNCTION__) + __ao2_callback_data((container), (flags), (cb_fn), (arg), (data), "", __FILE__, __LINE__, __PRETTY_FUNCTION__) -#else - -#define ao2_t_callback_data(container, flags, cb_fn, arg, data, tag) \ - __ao2_callback_data((container), (flags), (cb_fn), (arg), (data)) -#define ao2_callback_data(container, flags, cb_fn, arg, data) \ - __ao2_callback_data((container), (flags), (cb_fn), (arg), (data)) - -#endif - -void *__ao2_callback_data_debug(struct ao2_container *c, enum search_flags flags, +void *__ao2_callback_data(struct ao2_container *c, enum search_flags flags, ao2_callback_data_fn *cb_fn, void *arg, void *data, const char *tag, const char *file, int line, const char *func); -void *__ao2_callback_data(struct ao2_container *c, enum search_flags flags, - ao2_callback_data_fn *cb_fn, void *arg, void *data); /*! ao2_find() is a short hand for ao2_callback(c, flags, c->cmp_fn, arg) * XXX possibly change order of arguments ? */ -#ifdef REF_DEBUG #define ao2_t_find(container, arg, flags, tag) \ - __ao2_find_debug((container), (arg), (flags), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__) + __ao2_find((container), (arg), (flags), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__) #define ao2_find(container, arg, flags) \ - __ao2_find_debug((container), (arg), (flags), "", __FILE__, __LINE__, __PRETTY_FUNCTION__) + __ao2_find((container), (arg), (flags), "", __FILE__, __LINE__, __PRETTY_FUNCTION__) -#else - -#define ao2_t_find(container, arg, flags, tag) \ - __ao2_find((container), (arg), (flags)) -#define ao2_find(container, arg, flags) \ - __ao2_find((container), (arg), (flags)) - -#endif - -void *__ao2_find_debug(struct ao2_container *c, const void *arg, enum search_flags flags, +void *__ao2_find(struct ao2_container *c, const void *arg, enum search_flags flags, const char *tag, const char *file, int line, const char *func); -void *__ao2_find(struct ao2_container *c, const void *arg, enum search_flags flags); /*! \brief * @@ -2083,20 +1838,13 @@ void ao2_iterator_destroy(struct ao2_iterator *iter) __attribute__((noinline)); void ao2_iterator_destroy(struct ao2_iterator *iter); #endif /* defined(TEST_FRAMEWORK) */ -#ifdef REF_DEBUG +#define ao2_t_iterator_next(iter, tag) \ + __ao2_iterator_next((iter), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__) +#define ao2_iterator_next(iter) \ + __ao2_iterator_next((iter), "", __FILE__, __LINE__, __PRETTY_FUNCTION__) -#define ao2_t_iterator_next(iter, tag) __ao2_iterator_next_debug((iter), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__) -#define ao2_iterator_next(iter) __ao2_iterator_next_debug((iter), "", __FILE__, __LINE__, __PRETTY_FUNCTION__) - -#else - -#define ao2_t_iterator_next(iter, tag) __ao2_iterator_next((iter)) -#define ao2_iterator_next(iter) __ao2_iterator_next((iter)) - -#endif - -void *__ao2_iterator_next_debug(struct ao2_iterator *iter, const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result; -void *__ao2_iterator_next(struct ao2_iterator *iter) attribute_warn_unused_result; +void *__ao2_iterator_next(struct ao2_iterator *iter, + const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result; /*! * \brief Restart an iteration. @@ -2117,13 +1865,8 @@ void ao2_iterator_restart(struct ao2_iterator *iter); * down a NULL */ void __ao2_cleanup(void *obj); void __ao2_cleanup_debug(void *obj, const char *tag, const char *file, int line, const char *function); -#ifdef REF_DEBUG #define ao2_cleanup(obj) __ao2_cleanup_debug((obj), "", __FILE__, __LINE__, __PRETTY_FUNCTION__) #define ao2_t_cleanup(obj, tag) __ao2_cleanup_debug((obj), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__) -#else -#define ao2_cleanup(obj) __ao2_cleanup(obj) -#define ao2_t_cleanup(obj, tag) __ao2_cleanup((obj)) -#endif void ao2_iterator_cleanup(struct ao2_iterator *iter); /*! diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index 82abe99c1e..aec7f75296 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -1186,8 +1186,6 @@ struct ast_channel * attribute_malloc __attribute__((format(printf, 15, 16))) __ast_channel_alloc((needqueue), (state), (cid_num), (cid_name), (acctcode), (exten), (context), (assignedids), (requestor), (amaflag), (endpoint), \ __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__) - -#if defined(REF_DEBUG) || defined(__AST_DEBUG_MALLOC) /*! * \brief Create a fake channel structure * @@ -1206,25 +1204,6 @@ struct ast_channel * attribute_malloc __attribute__((format(printf, 15, 16))) */ #define ast_dummy_channel_alloc() __ast_dummy_channel_alloc(__FILE__, __LINE__, __PRETTY_FUNCTION__) struct ast_channel *__ast_dummy_channel_alloc(const char *file, int line, const char *function); -#else -/*! - * \brief Create a fake channel structure - * - * \retval NULL failure - * \retval non-NULL successfully allocated channel - * - * \note This function should ONLY be used to create a fake channel - * that can then be populated with data for use in variable - * substitution when a real channel does not exist. - * - * \note The created dummy channel should be destroyed by - * ast_channel_unref(). Using ast_channel_release() needlessly - * grabs the channel container lock and can cause a deadlock as - * a result. Also grabbing the channel container lock reduces - * system performance. - */ -struct ast_channel *ast_dummy_channel_alloc(void); -#endif /*! * \brief Queue one or more frames to a channel's frame queue diff --git a/include/asterisk/format_cache.h b/include/asterisk/format_cache.h index 9f4e06a23e..64e53b9c5f 100644 --- a/include/asterisk/format_cache.h +++ b/include/asterisk/format_cache.h @@ -252,20 +252,13 @@ int ast_format_cache_set(struct ast_format *format); * \note The returned format has its reference count incremented. It must be * dropped using ao2_ref or ao2_cleanup. */ -struct ast_format *__ast_format_cache_get(const char *name); -struct ast_format *__ast_format_cache_get_debug(const char *name, const char *tag, const char *file, int line, const char *func); +struct ast_format *__ast_format_cache_get(const char *name, + const char *tag, const char *file, int line, const char *func); -#ifdef REF_DEBUG #define ast_format_cache_get(name) \ - __ast_format_cache_get_debug((name), "", __FILE__, __LINE__, __PRETTY_FUNCTION__) + __ast_format_cache_get((name), "ast_format_cache_get", __FILE__, __LINE__, __PRETTY_FUNCTION__) #define ast_t_format_cache_get(name, tag) \ - __ast_format_cache_get_debug((name), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__) -#else -#define ast_format_cache_get(name) \ - __ast_format_cache_get((name)) -#define ast_t_format_cache_get(name, tag) \ - __ast_format_cache_get((name)) -#endif + __ast_format_cache_get((name), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__) /*! diff --git a/include/asterisk/format_cap.h b/include/asterisk/format_cap.h index 94e81f869e..e422cc6090 100644 --- a/include/asterisk/format_cap.h +++ b/include/asterisk/format_cap.h @@ -46,20 +46,14 @@ enum ast_format_cap_flags { * \retval ast_format_cap object on success. * \retval NULL on failure. */ -struct ast_format_cap *__ast_format_cap_alloc(enum ast_format_cap_flags flags); -struct ast_format_cap *__ast_format_cap_alloc_debug(enum ast_format_cap_flags flags, const char *tag, const char *file, int line, const char *func); +struct ast_format_cap *__ast_format_cap_alloc(enum ast_format_cap_flags flags, + const char *tag, const char *file, int line, const char *func); -#ifdef REF_DEBUG #define ast_format_cap_alloc(flags) \ - __ast_format_cap_alloc_debug((flags), "", __FILE__, __LINE__, __PRETTY_FUNCTION__) + __ast_format_cap_alloc((flags), "ast_format_cap_alloc", \ + __FILE__, __LINE__, __PRETTY_FUNCTION__) #define ast_t_format_cap_alloc(flags, tag) \ - __ast_format_cap_alloc_debug((flags), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__) -#else -#define ast_format_cap_alloc(flags) \ - __ast_format_cap_alloc((flags)) -#define ast_t_format_cap_alloc(flags, tag) \ - __ast_format_cap_alloc((flags)) -#endif + __ast_format_cap_alloc((flags), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__) /*! * \brief Set the global framing. @@ -103,20 +97,15 @@ unsigned int ast_format_cap_get_framing(const struct ast_format_cap *cap); * * \note If framing is specified here it overrides any global framing that has been set. */ -int __ast_format_cap_append(struct ast_format_cap *cap, struct ast_format *format, unsigned int framing); -int __ast_format_cap_append_debug(struct ast_format_cap *cap, struct ast_format *format, unsigned int framing, const char *tag, const char *file, int line, const char *func); +int __ast_format_cap_append(struct ast_format_cap *cap, struct ast_format *format, unsigned int framing, + const char *tag, const char *file, int line, const char *func); -#ifdef REF_DEBUG #define ast_format_cap_append(cap, format, framing) \ - __ast_format_cap_append_debug((cap), (format), (framing), "", __FILE__, __LINE__, __PRETTY_FUNCTION__) + __ast_format_cap_append((cap), (format), (framing), "ast_format_cap_append", \ + __FILE__, __LINE__, __PRETTY_FUNCTION__) #define ast_t_format_cap_append(cap, format, framing, tag) \ - __ast_format_cap_append_debug((cap), (format), (framing), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__) -#else -#define ast_format_cap_append(cap, format, framing) \ - __ast_format_cap_append((cap), (format), (framing)) -#define ast_t_format_cap_append(cap, format, framing, tag) \ - __ast_format_cap_append((cap), (format), (framing)) -#endif + __ast_format_cap_append((cap), (format), (framing), (tag), \ + __FILE__, __LINE__, __PRETTY_FUNCTION__) /*! * \brief Add all codecs Asterisk knows about for a specific type to diff --git a/include/asterisk/options.h b/include/asterisk/options.h index 0da5799aee..a08b8638c3 100644 --- a/include/asterisk/options.h +++ b/include/asterisk/options.h @@ -76,6 +76,8 @@ enum ast_option_flags { AST_OPT_FLAG_DONT_WARN = (1 << 18), /*! End CDRs before the 'h' extension */ AST_OPT_FLAG_END_CDR_BEFORE_H_EXTEN = (1 << 19), + /*! Reference Debugging */ + AST_OPT_FLAG_REF_DEBUG = (1 << 20), /*! Always fork, even if verbose or debug settings are non-zero */ AST_OPT_FLAG_ALWAYS_FORK = (1 << 21), /*! Disable log/verbose output to remote consoles */ @@ -131,6 +133,7 @@ enum ast_option_flags { #define ast_opt_hide_connect ast_test_flag(&ast_options, AST_OPT_FLAG_HIDE_CONSOLE_CONNECT) #define ast_opt_lock_confdir ast_test_flag(&ast_options, AST_OPT_FLAG_LOCK_CONFIG_DIR) #define ast_opt_generic_plc ast_test_flag(&ast_options, AST_OPT_FLAG_GENERIC_PLC) +#define ast_opt_ref_debug ast_test_flag(&ast_options, AST_OPT_FLAG_REF_DEBUG) extern struct ast_flags ast_options; diff --git a/main/asterisk.c b/main/asterisk.c index 574451c659..86a190bc80 100644 --- a/main/asterisk.c +++ b/main/asterisk.c @@ -3424,6 +3424,12 @@ static void ast_readconfig(void) ast_copy_string(cfg_paths.socket_path, DEFAULT_SOCKET, sizeof(cfg_paths.socket_path)); ast_copy_string(cfg_paths.run_dir, DEFAULT_RUN_DIR, sizeof(cfg_paths.run_dir)); +#ifdef REF_DEBUG + /* The REF_DEBUG compiler flag is now only used to enable refdebug by default. + * Support for debugging reference counts is always compiled in. */ + ast_set2_flag(&ast_options, 1, AST_OPT_FLAG_REF_DEBUG); +#endif + ast_set_default_eid(&ast_eid_default); /* no asterisk.conf? no problem, use buildtime config! */ @@ -3494,6 +3500,8 @@ static void ast_readconfig(void) if (sscanf(v->value, "%30d", &option_debug) != 1) { option_debug = ast_true(v->value); } + } else if (!strcasecmp(v->name, "refdebug")) { + ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_REF_DEBUG); #if HAVE_WORKING_FORK /* Disable forking (-f at startup) */ } else if (!strcasecmp(v->name, "nofork")) { diff --git a/main/astobj2.c b/main/astobj2.c index edf1e95aba..c5b5cd957b 100644 --- a/main/astobj2.c +++ b/main/astobj2.c @@ -118,36 +118,28 @@ struct ao2_stats ao2; #define INTERNAL_OBJ_RWLOCK(user_data) \ ((struct astobj2_rwlock *) (((char *) (user_data)) - sizeof(struct astobj2_rwlock))) +#define INTERNAL_OBJ(user_data) \ + (struct astobj2 *) ((char *) user_data - sizeof(struct astobj2)) + /*! * \brief convert from a pointer _p to a user-defined object * * \return the pointer to the astobj2 structure */ -static struct astobj2 *INTERNAL_OBJ(void *user_data) -{ - struct astobj2 *p; +#define __INTERNAL_OBJ_CHECK(user_data, file, line, func) \ + ({ \ + struct astobj2 *p ## __LINE__; \ + if (!user_data \ + || !(p ## __LINE__ = INTERNAL_OBJ(user_data)) \ + || IS_AO2_MAGIC_BAD(p ## __LINE__)) { \ + log_bad_ao2(user_data, file, line, func); \ + p ## __LINE__ = NULL; \ + } \ + (p ## __LINE__); \ + }) - if (!user_data) { - ast_log(LOG_ERROR, "user_data is NULL\n"); - return NULL; - } - - p = (struct astobj2 *) ((char *) user_data - sizeof(*p)); - if (IS_AO2_MAGIC_BAD(p)) { - if (p->priv_data.magic) { - ast_log(LOG_ERROR, "bad magic number 0x%x for object %p\n", - p->priv_data.magic, user_data); - } else { - ast_log(LOG_ERROR, - "bad magic number for object %p. Object is likely destroyed.\n", - user_data); - } - ast_assert(0); - return NULL; - } - - return p; -} +#define INTERNAL_OBJ_CHECK(user_data) \ + __INTERNAL_OBJ_CHECK(user_data, __FILE__, __LINE__, __PRETTY_FUNCTION__) /*! * \brief convert from a pointer _p to an astobj2 object @@ -156,14 +148,43 @@ static struct astobj2 *INTERNAL_OBJ(void *user_data) */ #define EXTERNAL_OBJ(_p) ((_p) == NULL ? NULL : (_p)->user_data) -int is_ao2_object(void *user_data) +int internal_is_ao2_object(void *user_data) { - return (INTERNAL_OBJ(user_data) != NULL); + struct astobj2 *p; + + if (!user_data) { + return 0; + } + + p = INTERNAL_OBJ(user_data); + + return !p || IS_AO2_MAGIC_BAD(p) ? 0 : 1; +} + +void log_bad_ao2(void *user_data, const char *file, int line, const char *func) +{ + struct astobj2 *p; + + if (!user_data) { + ast_log(__LOG_ERROR, file, line, func, "user_data is NULL\n"); + return; + } + + p = INTERNAL_OBJ(user_data); + if (p->priv_data.magic) { + ast_log(__LOG_ERROR, file, line, func, + "bad magic number 0x%x for object %p\n", + p->priv_data.magic, user_data); + } else { + ast_log(__LOG_ERROR, file, line, func, + "bad magic number for object %p. Object is likely destroyed.\n", + user_data); + } } int __ao2_lock(void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var) { - struct astobj2 *obj = INTERNAL_OBJ(user_data); + struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func); struct astobj2_lock *obj_mutex; struct astobj2_rwlock *obj_rwlock; int res = 0; @@ -221,7 +242,7 @@ int __ao2_lock(void *user_data, enum ao2_lock_req lock_how, const char *file, co int __ao2_unlock(void *user_data, const char *file, const char *func, int line, const char *var) { - struct astobj2 *obj = INTERNAL_OBJ(user_data); + struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func); struct astobj2_lock *obj_mutex; struct astobj2_rwlock *obj_rwlock; int res = 0; @@ -271,7 +292,7 @@ int __ao2_unlock(void *user_data, const char *file, const char *func, int line, int __ao2_trylock(void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var) { - struct astobj2 *obj = INTERNAL_OBJ(user_data); + struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func); struct astobj2_lock *obj_mutex; struct astobj2_rwlock *obj_rwlock; int res = 0; @@ -393,9 +414,11 @@ enum ao2_lock_req __adjust_lock(void *user_data, enum ao2_lock_req lock_how, int void *ao2_object_get_lockaddr(void *user_data) { - struct astobj2 *obj = INTERNAL_OBJ(user_data); + struct astobj2 *obj; struct astobj2_lock *obj_mutex; + obj = INTERNAL_OBJ_CHECK(user_data); + if (obj == NULL) { ast_assert(0); return NULL; @@ -412,9 +435,10 @@ void *ao2_object_get_lockaddr(void *user_data) return NULL; } -static int internal_ao2_ref(void *user_data, int delta, const char *file, int line, const char *func) +int __ao2_ref(void *user_data, int delta, + const char *tag, const char *file, int line, const char *func) { - struct astobj2 *obj = INTERNAL_OBJ(user_data); + struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func); struct astobj2_lock *obj_mutex; struct astobj2_rwlock *obj_rwlock; int current_value; @@ -422,6 +446,11 @@ static int internal_ao2_ref(void *user_data, int delta, const char *file, int li void *weakproxy = NULL; if (obj == NULL) { + if (ref_log && user_data) { + fprintf(ref_log, "%p,%d,%d,%s,%d,%s,**invalid**,%s\n", + user_data, delta, ast_get_tid(), file, line, func, tag ?: ""); + fflush(ref_log); + } ast_assert(0); return -1; } @@ -446,7 +475,9 @@ static int internal_ao2_ref(void *user_data, int delta, const char *file, int li if (weakproxy) { if (current_value == 1) { /* The only remaining reference is the one owned by the weak object */ - struct astobj2 *internal_weakproxy = INTERNAL_OBJ(weakproxy); + struct astobj2 *internal_weakproxy; + + internal_weakproxy = INTERNAL_OBJ_CHECK(weakproxy); /* Unlink the obj from the weak proxy */ internal_weakproxy->priv_data.weakptr = NULL; @@ -468,6 +499,12 @@ static int internal_ao2_ref(void *user_data, int delta, const char *file, int li if (0 < current_value) { /* The object still lives. */ + if (ref_log && tag) { + fprintf(ref_log, "%p,%s%d,%d,%s,%d,%s,%d,%s\n", user_data, + (delta < 0 ? "" : "+"), delta, ast_get_tid(), + file, line, func, ret, tag); + fflush(ref_log); + } return ret; } @@ -475,6 +512,12 @@ static int internal_ao2_ref(void *user_data, int delta, const char *file, int li if (current_value < 0) { ast_log(__LOG_ERROR, file, line, func, "Invalid refcount %d on ao2 object %p\n", current_value, user_data); + if (ref_log) { + /* Log to ref_log invalid even if (tag == NULL) */ + fprintf(ref_log, "%p,%d,%d,%s,%d,%s,**invalid**,%s\n", + user_data, delta, ast_get_tid(), file, line, func, tag ?: ""); + fflush(ref_log); + } ast_assert(0); /* stop here even if assert doesn't DO_CRASH */ return -1; @@ -515,51 +558,19 @@ static int internal_ao2_ref(void *user_data, int delta, const char *file, int li break; } + if (ref_log && tag) { + fprintf(ref_log, "%p,%d,%d,%s,%d,%s,**destructor**,%s\n", + user_data, delta, ast_get_tid(), file, line, func, tag); + fflush(ref_log); + } + return ret; } -int __ao2_ref_debug(void *user_data, int delta, const char *tag, const char *file, int line, const char *func) -{ - struct astobj2 *obj = INTERNAL_OBJ(user_data); - int old_refcount = -1; - - if (obj) { - old_refcount = internal_ao2_ref(user_data, delta, file, line, func); - } - - if (ref_log && user_data) { - if (!obj) { - /* Invalid object: Bad magic number. */ - fprintf(ref_log, "%p,%d,%d,%s,%d,%s,**invalid**,%s\n", - user_data, delta, ast_get_tid(), file, line, func, tag); - fflush(ref_log); - } else if (old_refcount + delta == 0) { - fprintf(ref_log, "%p,%d,%d,%s,%d,%s,**destructor**,%s\n", - user_data, delta, ast_get_tid(), file, line, func, tag); - fflush(ref_log); - } else if (delta != 0) { - fprintf(ref_log, "%p,%s%d,%d,%s,%d,%s,%d,%s\n", user_data, (delta < 0 ? "" : "+"), - delta, ast_get_tid(), file, line, func, old_refcount, tag); - fflush(ref_log); - } - } - - if (obj == NULL) { - ast_assert(0); - } - - return old_refcount; -} - -int __ao2_ref(void *user_data, int delta) -{ - return internal_ao2_ref(user_data, delta, __FILE__, __LINE__, __FUNCTION__); -} - void __ao2_cleanup_debug(void *obj, const char *tag, const char *file, int line, const char *function) { if (obj) { - __ao2_ref_debug(obj, -1, tag, file, line, function); + __ao2_ref(obj, -1, tag, file, line, function); } } @@ -570,7 +581,8 @@ void __ao2_cleanup(void *obj) } } -static void *internal_ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, const char *file, int line, const char *func) +void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, + const char *tag, const char *file, int line, const char *func) { /* allocation */ struct astobj2 *obj; @@ -633,43 +645,27 @@ static void *internal_ao2_alloc(size_t data_size, ao2_destructor_fn destructor_f ast_atomic_fetchadd_int(&ao2.total_refs, 1); #endif + if (ref_log && tag) { + fprintf(ref_log, "%p,+1,%d,%s,%d,%s,**constructor**,%s\n", + EXTERNAL_OBJ(obj), ast_get_tid(), file, line, func, tag); + fflush(ref_log); + } + /* return a pointer to the user data */ return EXTERNAL_OBJ(obj); } unsigned int ao2_options_get(void *obj) { - struct astobj2 *orig_obj = INTERNAL_OBJ(obj); + struct astobj2 *orig_obj; + + orig_obj = INTERNAL_OBJ_CHECK(obj); if (!orig_obj) { return 0; } return orig_obj->priv_data.options; } -void *__ao2_alloc_debug(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, const char *tag, - const char *file, int line, const char *func, int ref_debug) -{ - /* allocation */ - void *obj; - - if ((obj = internal_ao2_alloc(data_size, destructor_fn, options, file, line, func)) == NULL) { - return NULL; - } - - if (ref_log) { - fprintf(ref_log, "%p,+1,%d,%s,%d,%s,**constructor**,%s\n", obj, ast_get_tid(), file, line, func, tag); - fflush(ref_log); - } - - /* return a pointer to the user data */ - return obj; -} - -void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options) -{ - return internal_ao2_alloc(data_size, destructor_fn, options, __FILE__, __LINE__, __FUNCTION__); -} - void __ao2_global_obj_release(struct ao2_global_obj *holder, const char *tag, const char *file, int line, const char *func, const char *name) { @@ -687,11 +683,7 @@ void __ao2_global_obj_release(struct ao2_global_obj *holder, const char *tag, co /* Release the held ao2 object. */ if (holder->obj) { - if (tag) { - __ao2_ref_debug(holder->obj, -1, tag, file, line, func); - } else { - __ao2_ref(holder->obj, -1); - } + __ao2_ref(holder->obj, -1, tag, file, line, func); holder->obj = NULL; } @@ -715,11 +707,7 @@ void *__ao2_global_obj_replace(struct ao2_global_obj *holder, void *obj, const c } if (obj) { - if (tag) { - __ao2_ref_debug(obj, +1, tag, file, line, func); - } else { - __ao2_ref(obj, +1); - } + __ao2_ref(obj, +1, tag, file, line, func); } obj_old = holder->obj; holder->obj = obj; @@ -735,11 +723,7 @@ int __ao2_global_obj_replace_unref(struct ao2_global_obj *holder, void *obj, con obj_old = __ao2_global_obj_replace(holder, obj, tag, file, line, func, name); if (obj_old) { - if (tag) { - __ao2_ref_debug(obj_old, -1, tag, file, line, func); - } else { - __ao2_ref(obj_old, -1); - } + __ao2_ref(obj_old, -1, tag, file, line, func); return 1; } return 0; @@ -764,11 +748,7 @@ void *__ao2_global_obj_ref(struct ao2_global_obj *holder, const char *tag, const obj = holder->obj; if (obj) { - if (tag) { - __ao2_ref_debug(obj, +1, tag, file, line, func); - } else { - __ao2_ref(obj, +1); - } + __ao2_ref(obj, +1, tag, file, line, func); } __ast_rwlock_unlock(file, line, func, &holder->lock, name); @@ -798,12 +778,14 @@ void *__ao2_weakproxy_alloc(size_t data_size, ao2_destructor_fn destructor_fn, return NULL; } - weakproxy = __ao2_alloc_debug(data_size, destructor_fn, AO2_ALLOC_OPT_LOCK_MUTEX, - tag, file, line, func, 1); + weakproxy = __ao2_alloc(data_size, destructor_fn, AO2_ALLOC_OPT_LOCK_MUTEX, + tag, file, line, func); if (weakproxy) { - struct astobj2 *weakproxy_internal = INTERNAL_OBJ(weakproxy); + struct astobj2 *weakproxy_internal; + /* Just created weakproxy, no need to check if it's valid. */ + weakproxy_internal = INTERNAL_OBJ(weakproxy); weakproxy_internal->priv_data.magic = AO2_WEAK; } @@ -813,8 +795,8 @@ void *__ao2_weakproxy_alloc(size_t data_size, ao2_destructor_fn destructor_fn, int __ao2_weakproxy_set_object(void *weakproxy, void *obj, int flags, const char *tag, const char *file, int line, const char *func) { - struct astobj2 *weakproxy_internal = INTERNAL_OBJ(weakproxy); - struct astobj2 *obj_internal = INTERNAL_OBJ(obj); + struct astobj2 *weakproxy_internal = __INTERNAL_OBJ_CHECK(weakproxy, file, line, func); + struct astobj2 *obj_internal = __INTERNAL_OBJ_CHECK(obj, file, line, func); int ret = -1; if (!weakproxy_internal @@ -833,8 +815,8 @@ int __ao2_weakproxy_set_object(void *weakproxy, void *obj, int flags, } if (!weakproxy_internal->priv_data.weakptr) { - __ao2_ref_debug(obj, +1, tag, file, line, func); - __ao2_ref_debug(weakproxy, +1, tag, file, line, func); + __ao2_ref(obj, +1, tag, file, line, func); + __ao2_ref(weakproxy, +1, tag, file, line, func); weakproxy_internal->priv_data.weakptr = obj; obj_internal->priv_data.weakptr = weakproxy; @@ -857,7 +839,7 @@ int __ao2_weakproxy_set_object(void *weakproxy, void *obj, int flags, void *__ao2_weakproxy_get_object(void *weakproxy, int flags, const char *tag, const char *file, int line, const char *func) { - struct astobj2 *internal = INTERNAL_OBJ(weakproxy); + struct astobj2 *internal = __INTERNAL_OBJ_CHECK(weakproxy, file, line, func); void *obj; if (!internal || internal->priv_data.magic != AO2_WEAK) { @@ -872,7 +854,7 @@ void *__ao2_weakproxy_get_object(void *weakproxy, int flags, obj = internal->priv_data.weakptr; if (obj) { - __ao2_ref_debug(obj, +1, tag, file, line, func); + __ao2_ref(obj, +1, tag, file, line, func); } if (!(flags & OBJ_NOLOCK)) { @@ -884,7 +866,7 @@ void *__ao2_weakproxy_get_object(void *weakproxy, int flags, void *__ao2_get_weakproxy(void *obj, const char *tag, const char *file, int line, const char *func) { - struct astobj2 *obj_internal = INTERNAL_OBJ(obj); + struct astobj2 *obj_internal = __INTERNAL_OBJ_CHECK(obj, file, line, func); if (!obj_internal || obj_internal->priv_data.magic != AO2_MAGIC) { /* This method is meant to be run on normal ao2 objects! */ @@ -895,13 +877,13 @@ void *__ao2_get_weakproxy(void *obj, const char *tag, const char *file, int line return NULL; } - __ao2_ref_debug(obj_internal->priv_data.weakptr, +1, tag, file, line, func); + __ao2_ref(obj_internal->priv_data.weakptr, +1, tag, file, line, func); return obj_internal->priv_data.weakptr; } int ao2_weakproxy_subscribe(void *weakproxy, ao2_weakproxy_notification_cb cb, void *data, int flags) { - struct astobj2 *weakproxy_internal = INTERNAL_OBJ(weakproxy); + struct astobj2 *weakproxy_internal = INTERNAL_OBJ_CHECK(weakproxy); int ret = -1; if (!weakproxy_internal || weakproxy_internal->priv_data.magic != AO2_WEAK) { @@ -936,7 +918,7 @@ int ao2_weakproxy_subscribe(void *weakproxy, ao2_weakproxy_notification_cb cb, v int ao2_weakproxy_unsubscribe(void *weakproxy, ao2_weakproxy_notification_cb destroyed_cb, void *data, int flags) { - struct astobj2 *internal_weakproxy = INTERNAL_OBJ(weakproxy); + struct astobj2 *internal_weakproxy = INTERNAL_OBJ_CHECK(weakproxy); struct ao2_weakproxy *weak; struct ao2_weakproxy_notification *sub; int ret = 0; @@ -1123,29 +1105,28 @@ static void astobj2_cleanup(void) #if defined(AO2_DEBUG) ast_cli_unregister_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2)); #endif -#ifdef REF_DEBUG - fclose(ref_log); - ref_log = NULL; -#endif + + if (ast_opt_ref_debug) { + fclose(ref_log); + ref_log = NULL; + } } int astobj2_init(void) { -#ifdef REF_DEBUG char ref_filename[1024]; -#endif if (container_init() != 0) { return -1; } -#ifdef REF_DEBUG - snprintf(ref_filename, sizeof(ref_filename), "%s/refs", ast_config_AST_LOG_DIR); - ref_log = fopen(ref_filename, "w"); - if (!ref_log) { - ast_log(LOG_ERROR, "Could not open ref debug log file: %s\n", ref_filename); + if (ast_opt_ref_debug) { + snprintf(ref_filename, sizeof(ref_filename), "%s/refs", ast_config_AST_LOG_DIR); + ref_log = fopen(ref_filename, "w"); + if (!ref_log) { + ast_log(LOG_ERROR, "Could not open ref debug log file: %s\n", ref_filename); + } } -#endif #if defined(AO2_DEBUG) ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2)); diff --git a/main/astobj2_container.c b/main/astobj2_container.c index 07d10b9f93..c00da9fd41 100644 --- a/main/astobj2_container.c +++ b/main/astobj2_container.c @@ -49,11 +49,7 @@ int __container_unlink_node_debug(struct ao2_container_node *node, uint32_t flag if ((flags & AO2_UNLINK_NODE_UNLINK_OBJECT) && !(flags & AO2_UNLINK_NODE_NOUNREF_OBJECT)) { - if (tag) { - __ao2_ref_debug(node->obj, -1, tag, file, line, func); - } else { - ao2_t_ref(node->obj, -1, "Remove obj from container"); - } + __ao2_ref(node->obj, -1, tag ?: "Remove obj from container", file, line, func); } node->obj = NULL; @@ -76,7 +72,7 @@ int __container_unlink_node_debug(struct ao2_container_node *node, uint32_t flag if (flags & AO2_UNLINK_NODE_UNREF_NODE) { /* Remove node from container */ - __ao2_ref(node, -1); + ao2_t_ref(node, -1, NULL); } return 1; @@ -97,13 +93,15 @@ int __container_unlink_node_debug(struct ao2_container_node *node, uint32_t flag * \retval 0 on errors. * \retval 1 on success. */ -static int internal_ao2_link(struct ao2_container *self, void *obj_new, int flags, const char *tag, const char *file, int line, const char *func) +int __ao2_link(struct ao2_container *self, void *obj_new, int flags, + const char *tag, const char *file, int line, const char *func) { int res; enum ao2_lock_req orig_lock; struct ao2_container_node *node; - if (!is_ao2_object(obj_new) || !is_ao2_object(self) + if (!__is_ao2_object(obj_new, file, line, func) + || !__is_ao2_object(self, file, line, func) || !self->v_table || !self->v_table->new_node || !self->v_table->insert) { /* Sanity checks. */ ast_assert(0); @@ -147,7 +145,7 @@ static int internal_ao2_link(struct ao2_container *self, void *obj_new, int flag res = 1; break; case AO2_CONTAINER_INSERT_NODE_REJECTED: - __ao2_ref(node, -1); + ao2_t_ref(node, -1, NULL); break; } } @@ -161,16 +159,6 @@ static int internal_ao2_link(struct ao2_container *self, void *obj_new, int flag return res; } -int __ao2_link_debug(struct ao2_container *c, void *obj_new, int flags, const char *tag, const char *file, int line, const char *func) -{ - return internal_ao2_link(c, obj_new, flags, tag, file, line, func); -} - -int __ao2_link(struct ao2_container *c, void *obj_new, int flags) -{ - return internal_ao2_link(c, obj_new, flags, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__); -} - /*! * \brief another convenience function is a callback that matches on address */ @@ -183,10 +171,10 @@ int ao2_match_by_addr(void *user_data, void *arg, int flags) * Unlink an object from the container * and destroy the associated * bucket_entry structure. */ -void *__ao2_unlink_debug(struct ao2_container *c, void *user_data, int flags, +void *__ao2_unlink(struct ao2_container *c, void *user_data, int flags, const char *tag, const char *file, int line, const char *func) { - if (!is_ao2_object(user_data)) { + if (!__is_ao2_object(user_data, file, line, func)) { /* Sanity checks. */ ast_assert(0); return NULL; @@ -194,22 +182,7 @@ void *__ao2_unlink_debug(struct ao2_container *c, void *user_data, int flags, flags &= ~OBJ_SEARCH_MASK; flags |= (OBJ_UNLINK | OBJ_SEARCH_OBJECT | OBJ_NODATA); - __ao2_callback_debug(c, flags, ao2_match_by_addr, user_data, tag, file, line, func); - - return NULL; -} - -void *__ao2_unlink(struct ao2_container *c, void *user_data, int flags) -{ - if (!is_ao2_object(user_data)) { - /* Sanity checks. */ - ast_assert(0); - return NULL; - } - - flags &= ~OBJ_SEARCH_MASK; - flags |= (OBJ_UNLINK | OBJ_SEARCH_OBJECT | OBJ_NODATA); - __ao2_callback(c, flags, ao2_match_by_addr, user_data); + __ao2_callback(c, flags, ao2_match_by_addr, user_data, tag, file, line, func); return NULL; } @@ -268,8 +241,8 @@ static void *internal_ao2_traverse(struct ao2_container *self, enum search_flags struct ao2_container *multi_container = NULL; struct ao2_iterator *multi_iterator = NULL; - if (!is_ao2_object(self) || !self->v_table || !self->v_table->traverse_first - || !self->v_table->traverse_next) { + if (!__is_ao2_object(self, file, line, func) || !self->v_table + || !self->v_table->traverse_first || !self->v_table->traverse_next) { /* Sanity checks. */ ast_assert(0); return NULL; @@ -376,12 +349,7 @@ static void *internal_ao2_traverse(struct ao2_container *self, enum search_flags * Link the object into the container that will hold the * results. */ - if (tag) { - __ao2_link_debug(multi_container, node->obj, flags, - tag, file, line, func); - } else { - __ao2_link(multi_container, node->obj, flags); - } + __ao2_link(multi_container, node->obj, flags, tag, file, line, func); } else { ret = node->obj; /* Returning a single object. */ @@ -390,11 +358,7 @@ static void *internal_ao2_traverse(struct ao2_container *self, enum search_flags * Bump the ref count since we are not going to unlink and * transfer the container's object ref to the returned object. */ - if (tag) { - __ao2_ref_debug(ret, 1, tag, file, line, func); - } else { - ao2_t_ref(ret, 1, "Traversal found object"); - } + __ao2_ref(ret, 1, tag ?: "Traversal found object", file, line, func); } } } @@ -418,7 +382,7 @@ static void *internal_ao2_traverse(struct ao2_container *self, enum search_flags } if (node) { /* Unref the node from self->v_table->traverse_first/traverse_next() */ - __ao2_ref(node, -1); + ao2_t_ref(node, -1, NULL); } if (flags & OBJ_NOLOCK) { @@ -439,36 +403,24 @@ static void *internal_ao2_traverse(struct ao2_container *self, enum search_flags } } -void *__ao2_callback_debug(struct ao2_container *c, enum search_flags flags, +void *__ao2_callback(struct ao2_container *c, enum search_flags flags, ao2_callback_fn *cb_fn, void *arg, const char *tag, const char *file, int line, const char *func) { return internal_ao2_traverse(c, flags, cb_fn, arg, NULL, AO2_CALLBACK_DEFAULT, tag, file, line, func); } -void *__ao2_callback(struct ao2_container *c, enum search_flags flags, - ao2_callback_fn *cb_fn, void *arg) -{ - return internal_ao2_traverse(c, flags, cb_fn, arg, NULL, AO2_CALLBACK_DEFAULT, NULL, NULL, 0, NULL); -} - -void *__ao2_callback_data_debug(struct ao2_container *c, enum search_flags flags, +void *__ao2_callback_data(struct ao2_container *c, enum search_flags flags, ao2_callback_data_fn *cb_fn, void *arg, void *data, const char *tag, const char *file, int line, const char *func) { return internal_ao2_traverse(c, flags, cb_fn, arg, data, AO2_CALLBACK_WITH_DATA, tag, file, line, func); } -void *__ao2_callback_data(struct ao2_container *c, enum search_flags flags, - ao2_callback_data_fn *cb_fn, void *arg, void *data) -{ - return internal_ao2_traverse(c, flags, cb_fn, arg, data, AO2_CALLBACK_WITH_DATA, NULL, NULL, 0, NULL); -} - /*! * the find function just invokes the default callback with some reasonable flags. */ -void *__ao2_find_debug(struct ao2_container *c, const void *arg, enum search_flags flags, +void *__ao2_find(struct ao2_container *c, const void *arg, enum search_flags flags, const char *tag, const char *file, int line, const char *func) { void *arged = (void *) arg;/* Done to avoid compiler const warning */ @@ -478,19 +430,7 @@ void *__ao2_find_debug(struct ao2_container *c, const void *arg, enum search_fla ast_assert(0); return NULL; } - return __ao2_callback_debug(c, flags, c->cmp_fn, arged, tag, file, line, func); -} - -void *__ao2_find(struct ao2_container *c, const void *arg, enum search_flags flags) -{ - void *arged = (void *) arg;/* Done to avoid compiler const warning */ - - if (!c) { - /* Sanity checks. */ - ast_assert(0); - return NULL; - } - return __ao2_callback(c, flags, c->cmp_fn, arged); + return __ao2_callback(c, flags, c->cmp_fn, arged, tag, file, line, func); } /*! @@ -520,6 +460,12 @@ void ao2_iterator_restart(struct ao2_iterator *iter) if (iter->last_node) { enum ao2_lock_req orig_lock; + if (!is_ao2_object(iter->c)) { + /* Sanity check. */ + ast_assert(0); + return; + } + /* * Do a read lock in case the container node unref does not * destroy the node. If the container node is destroyed then @@ -532,7 +478,7 @@ void ao2_iterator_restart(struct ao2_iterator *iter) ao2_rdlock(iter->c); } - __ao2_ref(iter->last_node, -1); + ao2_t_ref(iter->last_node, -1, NULL); iter->last_node = NULL; if (iter->flags & AO2_ITERATOR_DONTLOCK) { @@ -568,16 +514,15 @@ void ao2_iterator_cleanup(struct ao2_iterator *iter) } } -/* - * move to the next element in the container. - */ -static void *internal_ao2_iterator_next(struct ao2_iterator *iter, const char *tag, const char *file, int line, const char *func) +void *__ao2_iterator_next(struct ao2_iterator *iter, + const char *tag, const char *file, int line, const char *func) { enum ao2_lock_req orig_lock; struct ao2_container_node *node; void *ret; - if (!is_ao2_object(iter->c) || !iter->c->v_table || !iter->c->v_table->iterator_next) { + if (!__is_ao2_object(iter->c, file, line, func) + || !iter->c->v_table || !iter->c->v_table->iterator_next) { /* Sanity checks. */ ast_assert(0); return NULL; @@ -614,14 +559,10 @@ static void *internal_ao2_iterator_next(struct ao2_iterator *iter, const char *t /* Transfer the container's node ref to the iterator. */ } else { /* Bump ref of returned object */ - if (tag) { - __ao2_ref_debug(ret, +1, tag, file, line, func); - } else { - ao2_t_ref(ret, +1, "Next iterator object."); - } + __ao2_ref(ret, +1, tag ?: "Next iterator object.", file, line, func); /* Bump the container's node ref for the iterator. */ - __ao2_ref(node, +1); + ao2_t_ref(node, +1, NULL); } } else { /* The iteration has completed. */ @@ -631,7 +572,7 @@ static void *internal_ao2_iterator_next(struct ao2_iterator *iter, const char *t /* Replace the iterator's node */ if (iter->last_node) { - __ao2_ref(iter->last_node, -1); + ao2_t_ref(iter->last_node, -1, NULL); } iter->last_node = node; @@ -644,16 +585,6 @@ static void *internal_ao2_iterator_next(struct ao2_iterator *iter, const char *t return ret; } -void *__ao2_iterator_next_debug(struct ao2_iterator *iter, const char *tag, const char *file, int line, const char *func) -{ - return internal_ao2_iterator_next(iter, tag, file, line, func); -} - -void *__ao2_iterator_next(struct ao2_iterator *iter) -{ - return internal_ao2_iterator_next(iter, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__); -} - int ao2_iterator_count(struct ao2_iterator *iter) { return ao2_container_count(iter->c); @@ -665,26 +596,8 @@ void container_destruct(void *_c) /* Unlink any stored objects in the container. */ c->destroying = 1; - __ao2_callback(c, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL); - - /* Perform any extra container cleanup. */ - if (c->v_table && c->v_table->destroy) { - c->v_table->destroy(c); - } - -#if defined(AO2_DEBUG) - ast_atomic_fetchadd_int(&ao2.total_containers, -1); -#endif -} - -void container_destruct_debug(void *_c) -{ - struct ao2_container *c = _c; - - /* Unlink any stored objects in the container. */ - c->destroying = 1; - __ao2_callback_debug(c, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, - "container_destruct_debug called", __FILE__, __LINE__, __PRETTY_FUNCTION__); + ao2_t_callback(c, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, + "container_destruct called"); /* Perform any extra container cleanup. */ if (c->v_table && c->v_table->destroy) { @@ -712,7 +625,7 @@ static int dup_obj_cb(void *obj, void *arg, int flags) { struct ao2_container *dest = arg; - return __ao2_link(dest, obj, OBJ_NOLOCK) ? 0 : (CMP_MATCH | CMP_STOP); + return ao2_t_link_flags(dest, obj, OBJ_NOLOCK, NULL) ? 0 : (CMP_MATCH | CMP_STOP); } int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enum search_flags flags) @@ -724,14 +637,14 @@ int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enu ao2_rdlock(src); ao2_wrlock(dest); } - obj = __ao2_callback(src, OBJ_NOLOCK, dup_obj_cb, dest); + obj = ao2_callback(src, OBJ_NOLOCK, dup_obj_cb, dest); if (obj) { /* Failed to put this obj into the dest container. */ ao2_t_ref(obj, -1, "Failed to put this object into the dest container."); /* Remove all items from the dest container. */ - __ao2_callback(dest, OBJ_NOLOCK | OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, - NULL); + ao2_t_callback(dest, OBJ_NOLOCK | OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, + NULL, NULL); res = -1; } if (!(flags & OBJ_NOLOCK)) { @@ -742,18 +655,19 @@ int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enu return res; } -struct ao2_container *__ao2_container_clone(struct ao2_container *orig, enum search_flags flags) +struct ao2_container *__ao2_container_clone(struct ao2_container *orig, enum search_flags flags, const char *tag, const char *file, int line, const char *func) { struct ao2_container *clone; int failed; /* Create the clone container with the same properties as the original. */ - if (!is_ao2_object(orig) || !orig->v_table || !orig->v_table->alloc_empty_clone) { + if (!__is_ao2_object(orig, file, line, func) + || !orig->v_table || !orig->v_table->alloc_empty_clone) { /* Sanity checks. */ ast_assert(0); return NULL; } - clone = orig->v_table->alloc_empty_clone(orig); + clone = orig->v_table->alloc_empty_clone(orig, tag, file, line, func); if (!clone) { return NULL; } @@ -767,42 +681,7 @@ struct ao2_container *__ao2_container_clone(struct ao2_container *orig, enum sea } if (failed) { /* Object copy into the clone container failed. */ - ao2_t_ref(clone, -1, "Clone creation failed."); - clone = NULL; - } - return clone; -} - -struct ao2_container *__ao2_container_clone_debug(struct ao2_container *orig, enum search_flags flags, const char *tag, const char *file, int line, const char *func, int ref_debug) -{ - struct ao2_container *clone; - int failed; - - /* Create the clone container with the same properties as the original. */ - if (!is_ao2_object(orig) || !orig->v_table || !orig->v_table->alloc_empty_clone_debug) { - /* Sanity checks. */ - ast_assert(0); - return NULL; - } - clone = orig->v_table->alloc_empty_clone_debug(orig, tag, file, line, func, ref_debug); - if (!clone) { - return NULL; - } - - if (flags & OBJ_NOLOCK) { - ao2_wrlock(clone); - } - failed = ao2_container_dup(clone, orig, flags); - if (flags & OBJ_NOLOCK) { - ao2_unlock(clone); - } - if (failed) { - /* Object copy into the clone container failed. */ - if (ref_debug) { - __ao2_ref_debug(clone, -1, tag, file, line, func); - } else { - ao2_t_ref(clone, -1, "Clone creation failed."); - } + __ao2_ref(clone, -1, tag ?: "Clone creation failed", file, line, func); clone = NULL; } return clone; diff --git a/main/astobj2_container_private.h b/main/astobj2_container_private.h index 07779a5f96..3651ca41f3 100644 --- a/main/astobj2_container_private.h +++ b/main/astobj2_container_private.h @@ -87,26 +87,15 @@ typedef void (*ao2_container_destroy_fn)(struct ao2_container *self); * \brief Create an empty copy of this container. * * \param self Container to operate upon. - * - * \retval empty-container on success. - * \retval NULL on error. - */ -typedef struct ao2_container *(*ao2_container_alloc_empty_clone_fn)(struct ao2_container *self); - -/*! - * \brief Create an empty copy of this container. (Debug version) - * - * \param self Container to operate upon. * \param tag used for debugging. * \param file Debug file name invoked from * \param line Debug line invoked from * \param func Debug function name invoked from - * \param ref_debug TRUE if to output a debug reference message. * * \retval empty-container on success. * \retval NULL on error. */ -typedef struct ao2_container *(*ao2_container_alloc_empty_clone_debug_fn)(struct ao2_container *self, const char *tag, const char *file, int line, const char *func, int ref_debug); +typedef struct ao2_container *(*ao2_container_alloc_empty_clone_fn)(struct ao2_container *self, const char *tag, const char *file, int line, const char *func); /*! * \brief Create a new container node. @@ -250,8 +239,6 @@ struct ao2_container_methods { ao2_container_destroy_fn destroy; /*! \brief Create an empty copy of this container. */ ao2_container_alloc_empty_clone_fn alloc_empty_clone; - /*! \brief Create an empty copy of this container. (Debug version) */ - ao2_container_alloc_empty_clone_debug_fn alloc_empty_clone_debug; /*! Create a new container node. */ ao2_container_new_node_fn new_node; /*! Insert a node into this container. */ @@ -336,10 +323,9 @@ int __container_unlink_node_debug(struct ao2_container_node *node, uint32_t flag const char *tag, const char *file, int line, const char *func); #define __container_unlink_node(node, flags) \ - __container_unlink_node_debug(node, flags, NULL, NULL, 0, NULL) + __container_unlink_node_debug(node, flags, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__) void container_destruct(void *_c); -void container_destruct_debug(void *_c); int container_init(void); #endif /* ASTOBJ2_CONTAINER_PRIVATE_H_ */ diff --git a/main/astobj2_hash.c b/main/astobj2_hash.c index 110dd1602c..91ad2d2d07 100644 --- a/main/astobj2_hash.c +++ b/main/astobj2_hash.c @@ -104,47 +104,27 @@ struct hash_traversal_state_check { /*! * \internal * \brief Create an empty copy of this container. - * \since 12.0.0 - * - * \param self Container to operate upon. - * - * \retval empty-clone-container on success. - * \retval NULL on error. - */ -static struct ao2_container *hash_ao2_alloc_empty_clone(struct ao2_container_hash *self) -{ - if (!is_ao2_object(self)) { - return NULL; - } - - return ao2_t_container_alloc_hash(ao2_options_get(self), self->common.options, self->n_buckets, - self->hash_fn, self->common.sort_fn, self->common.cmp_fn, "Clone hash container"); -} - -/*! - * \internal - * \brief Create an empty copy of this container. (Debug version) - * \since 12.0.0 + * \since 14.0.0 * * \param self Container to operate upon. * \param tag used for debugging. * \param file Debug file name invoked from * \param line Debug line invoked from * \param func Debug function name invoked from - * \param ref_debug TRUE if to output a debug reference message. * * \retval empty-clone-container on success. * \retval NULL on error. */ -static struct ao2_container *hash_ao2_alloc_empty_clone_debug(struct ao2_container_hash *self, const char *tag, const char *file, int line, const char *func, int ref_debug) +static struct ao2_container *hash_ao2_alloc_empty_clone(struct ao2_container_hash *self, + const char *tag, const char *file, int line, const char *func) { - if (!is_ao2_object(self)) { + if (!__is_ao2_object(self, file, line, func)) { return NULL; } - return __ao2_container_alloc_hash_debug(ao2_options_get(self), self->common.options, + return __ao2_container_alloc_hash(ao2_options_get(self), self->common.options, self->n_buckets, self->hash_fn, self->common.sort_fn, self->common.cmp_fn, - tag, file, line, func, ref_debug); + tag, file, line, func); } /*! @@ -230,7 +210,7 @@ static struct hash_bucket_node *hash_ao2_new_node(struct ao2_container_hash *sel struct hash_bucket_node *node; int i; - node = __ao2_alloc(sizeof(*node), hash_ao2_node_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK); + node = ao2_t_alloc_options(sizeof(*node), hash_ao2_node_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK, NULL); if (!node) { return NULL; } @@ -238,11 +218,7 @@ static struct hash_bucket_node *hash_ao2_new_node(struct ao2_container_hash *sel i = abs(self->hash_fn(obj_new, OBJ_SEARCH_OBJECT)); i %= self->n_buckets; - if (tag) { - __ao2_ref_debug(obj_new, +1, tag, file, line, func); - } else { - ao2_t_ref(obj_new, +1, "Container node creation"); - } + __ao2_ref(obj_new, +1, tag ?: "Container node creation", file, line, func); node->common.obj = obj_new; node->common.my_container = (struct ao2_container *) self; node->my_bucket = i; @@ -440,7 +416,7 @@ static struct hash_bucket_node *hash_ao2_find_first(struct ao2_container_hash *s } /* We have the first traversal node */ - __ao2_ref(node, +1); + ao2_t_ref(node, +1, NULL); return node; } } @@ -482,7 +458,7 @@ static struct hash_bucket_node *hash_ao2_find_first(struct ao2_container_hash *s } /* We have the first traversal node */ - __ao2_ref(node, +1); + ao2_t_ref(node, +1, NULL); return node; } } @@ -551,7 +527,7 @@ static struct hash_bucket_node *hash_ao2_find_next(struct ao2_container_hash *se } /* We have the next traversal node */ - __ao2_ref(node, +1); + ao2_t_ref(node, +1, NULL); /* * Dereferencing the prev node may result in our next node @@ -559,7 +535,7 @@ static struct hash_bucket_node *hash_ao2_find_next(struct ao2_container_hash *se * the container uses RW locks and the container was read * locked. */ - __ao2_ref(prev, -1); + ao2_t_ref(prev, -1, NULL); if (node->common.obj) { return node; } @@ -595,7 +571,7 @@ hash_descending_resume:; } /* We have the next traversal node */ - __ao2_ref(node, +1); + ao2_t_ref(node, +1, NULL); /* * Dereferencing the prev node may result in our next node @@ -603,7 +579,7 @@ hash_descending_resume:; * the container uses RW locks and the container was read * locked. */ - __ao2_ref(prev, -1); + ao2_t_ref(prev, -1, NULL); if (node->common.obj) { return node; } @@ -615,7 +591,7 @@ hash_ascending_resume:; } /* No more nodes in the container left to traverse. */ - __ao2_ref(prev, -1); + ao2_t_ref(prev, -1, NULL); return NULL; } @@ -1037,8 +1013,6 @@ static int hash_ao2_integrity(struct ao2_container_hash *self) /*! Hash container virtual method table. */ static const struct ao2_container_methods v_table_hash = { .alloc_empty_clone = (ao2_container_alloc_empty_clone_fn) hash_ao2_alloc_empty_clone, - .alloc_empty_clone_debug = - (ao2_container_alloc_empty_clone_debug_fn) hash_ao2_alloc_empty_clone_debug, .new_node = (ao2_container_new_node_fn) hash_ao2_new_node, .insert = (ao2_container_insert_fn) hash_ao2_insert_node, .traverse_first = (ao2_container_find_first_fn) hash_ao2_find_first, @@ -1103,26 +1077,9 @@ static struct ao2_container *hash_ao2_container_init( } struct ao2_container *__ao2_container_alloc_hash(unsigned int ao2_options, - unsigned int container_options, unsigned int n_buckets, ao2_hash_fn *hash_fn, - ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn) -{ - unsigned int num_buckets; - size_t container_size; - struct ao2_container_hash *self; - - num_buckets = hash_fn ? n_buckets : 1; - container_size = sizeof(struct ao2_container_hash) + num_buckets * sizeof(struct hash_bucket); - - self = ao2_t_alloc_options(container_size, container_destruct, ao2_options, - "New hash container"); - return hash_ao2_container_init(self, container_options, num_buckets, - hash_fn, sort_fn, cmp_fn); -} - -struct ao2_container *__ao2_container_alloc_hash_debug(unsigned int ao2_options, unsigned int container_options, unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn, - const char *tag, const char *file, int line, const char *func, int ref_debug) + const char *tag, const char *file, int line, const char *func) { unsigned int num_buckets; size_t container_size; @@ -1131,25 +1088,17 @@ struct ao2_container *__ao2_container_alloc_hash_debug(unsigned int ao2_options, num_buckets = hash_fn ? n_buckets : 1; container_size = sizeof(struct ao2_container_hash) + num_buckets * sizeof(struct hash_bucket); - self = __ao2_alloc_debug(container_size, - ref_debug ? container_destruct_debug : container_destruct, ao2_options, - tag, file, line, func, ref_debug); + self = __ao2_alloc(container_size, container_destruct, ao2_options, + tag ?: __PRETTY_FUNCTION__, file, line, func); return hash_ao2_container_init(self, container_options, num_buckets, hash_fn, sort_fn, cmp_fn); } struct ao2_container *__ao2_container_alloc_list(unsigned int ao2_options, - unsigned int container_options, ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn) -{ - return __ao2_container_alloc_hash(ao2_options, container_options, 1, NULL, sort_fn, - cmp_fn); -} - -struct ao2_container *__ao2_container_alloc_list_debug(unsigned int ao2_options, unsigned int container_options, ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn, - const char *tag, const char *file, int line, const char *func, int ref_debug) + const char *tag, const char *file, int line, const char *func) { - return __ao2_container_alloc_hash_debug(ao2_options, container_options, 1, NULL, - sort_fn, cmp_fn, tag, file, line, func, ref_debug); + return __ao2_container_alloc_hash(ao2_options, container_options, 1, NULL, + sort_fn, cmp_fn, tag, file, line, func); } diff --git a/main/astobj2_private.h b/main/astobj2_private.h index 0583faf7fa..ef47ed7742 100644 --- a/main/astobj2_private.h +++ b/main/astobj2_private.h @@ -43,7 +43,24 @@ struct ao2_stats { extern struct ao2_stats ao2; #endif /* defined(AO2_DEBUG) */ -int is_ao2_object(void *user_data); +void log_bad_ao2(void *user_data, const char *file, int line, const char *func); +int internal_is_ao2_object(void *user_data); + +#define __is_ao2_object(user_data, file, line, func) \ + ({ \ + int ret ## __LINE__ = 0; \ + if (user_data) { \ + ret ## __LINE__ = internal_is_ao2_object(user_data); \ + } \ + if (!ret ## __LINE__) { \ + log_bad_ao2(user_data, file, line, func); \ + } \ + (ret ## __LINE__); \ + }) + +#define is_ao2_object(user_data) \ + __is_ao2_object(user_data, __FILE__, __LINE__, __PRETTY_FUNCTION__) + enum ao2_lock_req __adjust_lock(void *user_data, enum ao2_lock_req lock_how, int keep_stronger); #endif /* ASTOBJ2_PRIVATE_H_ */ diff --git a/main/astobj2_rbtree.c b/main/astobj2_rbtree.c index d3a9025720..b06813d6fd 100644 --- a/main/astobj2_rbtree.c +++ b/main/astobj2_rbtree.c @@ -543,49 +543,29 @@ static void rb_rotate_right(struct ao2_container_rbtree *self, struct rbtree_nod child->right = node; } -/*! - * \internal - * \brief Create an empty copy of this container. - * \since 12.0.0 - * - * \param self Container to operate upon. - * - * \retval empty-clone-container on success. - * \retval NULL on error. - */ -static struct ao2_container *rb_ao2_alloc_empty_clone(struct ao2_container_rbtree *self) -{ - if (!is_ao2_object(self)) { - return NULL; - } - - return ao2_t_container_alloc_rbtree(ao2_options_get(self), self->common.options, - self->common.sort_fn, self->common.cmp_fn, "Clone rbtree container"); -} - /*! * \internal * \brief Create an empty copy of this container. (Debug version) - * \since 12.0.0 + * \since 14.0.0 * * \param self Container to operate upon. * \param tag used for debugging. * \param file Debug file name invoked from * \param line Debug line invoked from * \param func Debug function name invoked from - * \param ref_debug TRUE if to output a debug reference message. * * \retval empty-clone-container on success. * \retval NULL on error. */ -static struct ao2_container *rb_ao2_alloc_empty_clone_debug(struct ao2_container_rbtree *self, const char *tag, const char *file, int line, const char *func, int ref_debug) +static struct ao2_container *rb_ao2_alloc_empty_clone(struct ao2_container_rbtree *self, + const char *tag, const char *file, int line, const char *func) { - if (!is_ao2_object(self)) { + if (!__is_ao2_object(self, file, line, func)) { return NULL; } - return __ao2_container_alloc_rbtree_debug(ao2_options_get(self), self->common.options, - self->common.sort_fn, self->common.cmp_fn, tag, file, line, func, ref_debug); + return __ao2_container_alloc_rbtree(ao2_options_get(self), self->common.options, + self->common.sort_fn, self->common.cmp_fn, tag, file, line, func); } /*! @@ -925,16 +905,12 @@ static struct rbtree_node *rb_ao2_new_node(struct ao2_container_rbtree *self, vo { struct rbtree_node *node; - node = __ao2_alloc(sizeof(*node), rb_ao2_node_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK); + node = ao2_t_alloc_options(sizeof(*node), rb_ao2_node_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK, NULL); if (!node) { return NULL; } - if (tag) { - __ao2_ref_debug(obj_new, +1, tag, file, line, func); - } else { - ao2_t_ref(obj_new, +1, "Container node creation"); - } + __ao2_ref(obj_new, +1, tag ?: "Container node creation", file, line, func); node->common.obj = obj_new; node->common.my_container = (struct ao2_container *) self; @@ -1337,7 +1313,7 @@ static struct rbtree_node *rb_ao2_find_next(struct ao2_container_rbtree *self, s } /* We have the next traversal node */ - __ao2_ref(node, +1); + ao2_t_ref(node, +1, NULL); /* * Dereferencing the prev node may result in our next node @@ -1345,7 +1321,7 @@ static struct rbtree_node *rb_ao2_find_next(struct ao2_container_rbtree *self, s * the container uses RW locks and the container was read * locked. */ - __ao2_ref(prev, -1); + ao2_t_ref(prev, -1, NULL); if (node->common.obj) { return node; } @@ -1353,7 +1329,7 @@ static struct rbtree_node *rb_ao2_find_next(struct ao2_container_rbtree *self, s } /* No more nodes in the container left to traverse. */ - __ao2_ref(prev, -1); + ao2_t_ref(prev, -1, NULL); return NULL; } @@ -1636,7 +1612,7 @@ static struct rbtree_node *rb_ao2_find_first(struct ao2_container_rbtree *self, } /* We have the first traversal node */ - __ao2_ref(node, +1); + ao2_t_ref(node, +1, NULL); return node; } @@ -2018,8 +1994,6 @@ static int rb_ao2_integrity(struct ao2_container_rbtree *self) /*! rbtree container virtual method table. */ static const struct ao2_container_methods v_table_rbtree = { .alloc_empty_clone = (ao2_container_alloc_empty_clone_fn) rb_ao2_alloc_empty_clone, - .alloc_empty_clone_debug = - (ao2_container_alloc_empty_clone_debug_fn) rb_ao2_alloc_empty_clone_debug, .new_node = (ao2_container_new_node_fn) rb_ao2_new_node, .insert = (ao2_container_insert_fn) rb_ao2_insert_node, .traverse_first = (ao2_container_find_first_fn) rb_ao2_find_first, @@ -2063,24 +2037,8 @@ static struct ao2_container *rb_ao2_container_init(struct ao2_container_rbtree * } struct ao2_container *__ao2_container_alloc_rbtree(unsigned int ao2_options, unsigned int container_options, - ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn) -{ - struct ao2_container_rbtree *self; - - if (!sort_fn) { - /* Sanity checks. */ - ast_log(LOG_ERROR, "Missing sort_fn()!\n"); - return NULL; - } - - self = ao2_t_alloc_options(sizeof(*self), container_destruct, ao2_options, - "New rbtree container"); - return rb_ao2_container_init(self, container_options, sort_fn, cmp_fn); -} - -struct ao2_container *__ao2_container_alloc_rbtree_debug(unsigned int ao2_options, unsigned int container_options, ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn, - const char *tag, const char *file, int line, const char *func, int ref_debug) + const char *tag, const char *file, int line, const char *func) { struct ao2_container_rbtree *self; @@ -2090,9 +2048,8 @@ struct ao2_container *__ao2_container_alloc_rbtree_debug(unsigned int ao2_option return NULL; } - self = __ao2_alloc_debug(sizeof(*self), - ref_debug ? container_destruct_debug : container_destruct, ao2_options, - tag, file, line, func, ref_debug); + self = __ao2_alloc(sizeof(*self), container_destruct, ao2_options, + tag ?: __PRETTY_FUNCTION__, file, line, func); return rb_ao2_container_init(self, container_options, sort_fn, cmp_fn); } diff --git a/main/channel.c b/main/channel.c index db126db763..fee77630a3 100644 --- a/main/channel.c +++ b/main/channel.c @@ -795,7 +795,9 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char return NULL; } - if (!(tmp = ast_channel_internal_alloc(ast_channel_destructor, assignedids, requestor))) { + tmp = __ast_channel_internal_alloc(ast_channel_destructor, assignedids, requestor, + file, line, function); + if (!tmp) { /* Channel structure allocation failure. */ return NULL; } @@ -987,16 +989,14 @@ struct ast_channel *__ast_channel_alloc(int needqueue, int state, const char *ci /* only do the minimum amount of work needed here to make a channel * structure that can be used to expand channel vars */ -#if defined(REF_DEBUG) || defined(__AST_DEBUG_MALLOC) struct ast_channel *__ast_dummy_channel_alloc(const char *file, int line, const char *function) -#else -struct ast_channel *ast_dummy_channel_alloc(void) -#endif { struct ast_channel *tmp; struct varshead *headp; - if (!(tmp = ast_channel_internal_alloc(ast_dummy_channel_destructor, NULL, NULL))) { + tmp = __ast_channel_internal_alloc(ast_dummy_channel_destructor, NULL, NULL, + file, line, function); + if (!tmp) { /* Dummy channel structure allocation failure. */ return NULL; } diff --git a/main/channel_internal_api.c b/main/channel_internal_api.c index 4e85398897..0bb38499b2 100644 --- a/main/channel_internal_api.c +++ b/main/channel_internal_api.c @@ -1439,15 +1439,9 @@ static int pvt_cause_cmp_fn(void *obj, void *vstr, int flags) struct ast_channel *__ast_channel_internal_alloc(void (*destructor)(void *obj), const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *file, int line, const char *function) { struct ast_channel *tmp; -#if defined(REF_DEBUG) - tmp = __ao2_alloc_debug(sizeof(*tmp), destructor, - AO2_ALLOC_OPT_LOCK_MUTEX, "", file, line, function, 1); -#elif defined(__AST_DEBUG_MALLOC) - tmp = __ao2_alloc_debug(sizeof(*tmp), destructor, - AO2_ALLOC_OPT_LOCK_MUTEX, "", file, line, function, 0); -#else - tmp = ao2_alloc(sizeof(*tmp), destructor); -#endif + + tmp = __ao2_alloc(sizeof(*tmp), destructor, + AO2_ALLOC_OPT_LOCK_MUTEX, "", file, line, function); if (!tmp) { return NULL; diff --git a/main/format_cache.c b/main/format_cache.c index 3e729769c4..def795c9d4 100644 --- a/main/format_cache.c +++ b/main/format_cache.c @@ -457,22 +457,14 @@ int ast_format_cache_set(struct ast_format *format) return 0; } -struct ast_format *__ast_format_cache_get(const char *name) +struct ast_format *__ast_format_cache_get(const char *name, + const char *tag, const char *file, int line, const char *func) { if (ast_strlen_zero(name)) { return NULL; } - return ao2_find(formats, name, OBJ_SEARCH_KEY); -} - -struct ast_format *__ast_format_cache_get_debug(const char *name, const char *tag, const char *file, int line, const char *func) -{ - if (ast_strlen_zero(name)) { - return NULL; - } - - return __ao2_find_debug(formats, name, OBJ_SEARCH_KEY, S_OR(tag, "ast_format_cache_get"), file, line, func); + return __ao2_find(formats, name, OBJ_SEARCH_KEY, tag, file, line, func); } struct ast_format *ast_format_cache_get_slin_by_rate(unsigned int rate) diff --git a/main/format_cap.c b/main/format_cap.c index c9c6c3b303..7456a444b1 100644 --- a/main/format_cap.c +++ b/main/format_cap.c @@ -103,25 +103,13 @@ static inline void format_cap_init(struct ast_format_cap *cap, enum ast_format_c cap->framing = UINT_MAX; } -struct ast_format_cap *__ast_format_cap_alloc(enum ast_format_cap_flags flags) +struct ast_format_cap *__ast_format_cap_alloc(enum ast_format_cap_flags flags, + const char *tag, const char *file, int line, const char *func) { struct ast_format_cap *cap; - cap = ao2_alloc_options(sizeof(*cap), format_cap_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK); - if (!cap) { - return NULL; - } - - format_cap_init(cap, flags); - - return cap; -} - -struct ast_format_cap *__ast_format_cap_alloc_debug(enum ast_format_cap_flags flags, const char *tag, const char *file, int line, const char *func) -{ - struct ast_format_cap *cap; - - cap = __ao2_alloc_debug(sizeof(*cap), format_cap_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK, S_OR(tag, "ast_format_cap_alloc"), file, line, func, 1); + cap = __ao2_alloc(sizeof(*cap), format_cap_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK, + tag, file, line, func); if (!cap) { return NULL; } @@ -187,26 +175,7 @@ static int format_in_format_cap(struct ast_format_cap *cap, struct ast_format *f return 0; } -int __ast_format_cap_append(struct ast_format_cap *cap, struct ast_format *format, unsigned int framing) -{ - struct format_cap_framed *framed; - - ast_assert(format != NULL); - - if (format_in_format_cap(cap, format)) { - return 0; - } - - framed = ao2_alloc_options(sizeof(*framed), format_cap_framed_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK); - if (!framed) { - return -1; - } - framed->format = ao2_bump(format); - - return format_cap_framed_init(framed, cap, format, framing); -} - -int __ast_format_cap_append_debug(struct ast_format_cap *cap, struct ast_format *format, unsigned int framing, const char *tag, const char *file, int line, const char *func) +int __ast_format_cap_append(struct ast_format_cap *cap, struct ast_format *format, unsigned int framing, const char *tag, const char *file, int line, const char *func) { struct format_cap_framed *framed; @@ -221,7 +190,7 @@ int __ast_format_cap_append_debug(struct ast_format_cap *cap, struct ast_format return -1; } - __ao2_ref_debug(format, +1, S_OR(tag, "ast_format_cap_append"), file, line, func); + __ao2_ref(format, +1, tag, file, line, func); framed->format = format; return format_cap_framed_init(framed, cap, format, framing); diff --git a/main/loader.c b/main/loader.c index 26d229fdbf..eb959fa805 100644 --- a/main/loader.c +++ b/main/loader.c @@ -122,10 +122,8 @@ static int modules_loaded; struct ast_module { const struct ast_module_info *info; -#ifdef REF_DEBUG - /* Used to get module references into REF_DEBUG logs */ + /* Used to get module references into refs log */ void *ref_debug; -#endif void *lib; /* the shared lib, or NULL if embedded */ int usecount; /* the number of 'users' currently in this module */ struct module_user_list users; /* the list of users in the module */ @@ -199,9 +197,9 @@ void ast_module_register(const struct ast_module_info *info) ast_debug(5, "Registering module %s\n", info->name); mod->info = info; -#ifdef REF_DEBUG - mod->ref_debug = ao2_t_alloc(0, NULL, info->name); -#endif + if (ast_opt_ref_debug) { + mod->ref_debug = ao2_t_alloc(0, NULL, info->name); + } AST_LIST_HEAD_INIT(&mod->users); /* during startup, before the loader has been initialized, @@ -248,9 +246,7 @@ void ast_module_unregister(const struct ast_module_info *info) if (mod) { ast_debug(5, "Unregistering module %s\n", info->name); AST_LIST_HEAD_DESTROY(&mod->users); -#ifdef REF_DEBUG ao2_cleanup(mod->ref_debug); -#endif ast_free(mod); } } @@ -270,9 +266,9 @@ struct ast_module_user *__ast_module_user_add(struct ast_module *mod, struct ast AST_LIST_INSERT_HEAD(&mod->users, u, entry); AST_LIST_UNLOCK(&mod->users); -#ifdef REF_DEBUG - ao2_ref(mod->ref_debug, +1); -#endif + if (mod->ref_debug) { + ao2_ref(mod->ref_debug, +1); + } ast_atomic_fetchadd_int(&mod->usecount, +1); @@ -298,9 +294,9 @@ void __ast_module_user_remove(struct ast_module *mod, struct ast_module_user *u) return; } -#ifdef REF_DEBUG - ao2_ref(mod->ref_debug, -1); -#endif + if (mod->ref_debug) { + ao2_ref(mod->ref_debug, -1); + } ast_atomic_fetchadd_int(&mod->usecount, -1); ast_free(u); @@ -318,9 +314,9 @@ void __ast_module_user_hangup_all(struct ast_module *mod) ast_softhangup(u->chan, AST_SOFTHANGUP_APPUNLOAD); } -#ifdef REF_DEBUG - ao2_ref(mod->ref_debug, -1); -#endif + if (mod->ref_debug) { + ao2_ref(mod->ref_debug, -1); + } ast_atomic_fetchadd_int(&mod->usecount, -1); ast_free(u); @@ -641,9 +637,7 @@ void ast_module_shutdown(void) mod->info->unload(); } AST_LIST_HEAD_DESTROY(&mod->users); -#ifdef REF_DEBUG ao2_cleanup(mod->ref_debug); -#endif ast_free(mod); somethingchanged = 1; } @@ -1477,9 +1471,9 @@ struct ast_module *__ast_module_ref(struct ast_module *mod, const char *file, in return NULL; } -#ifdef REF_DEBUG - __ao2_ref_debug(mod->ref_debug, +1, "", file, line, func); -#endif + if (mod->ref_debug) { + __ao2_ref(mod->ref_debug, +1, "", file, line, func); + } ast_atomic_fetchadd_int(&mod->usecount, +1); ast_update_use_count(); @@ -1503,9 +1497,9 @@ void __ast_module_unref(struct ast_module *mod, const char *file, int line, cons return; } -#ifdef REF_DEBUG - __ao2_ref_debug(mod->ref_debug, -1, "", file, line, func); -#endif + if (mod->ref_debug) { + __ao2_ref(mod->ref_debug, -1, "", file, line, func); + } ast_atomic_fetchadd_int(&mod->usecount, -1); ast_update_use_count(); diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c index 24a3a280fa..eaf1f4ea86 100644 --- a/res/res_musiconhold.c +++ b/res/res_musiconhold.c @@ -210,7 +210,7 @@ static int reload(void); #define mohclass_ref(class,string) (ao2_t_ref((class), +1, (string)), class) -#ifndef REF_DEBUG +#ifndef AST_DEVMODE #define mohclass_unref(class,string) ({ ao2_t_ref((class), -1, (string)); (struct mohclass *) NULL; }) #else #define mohclass_unref(class,string) _mohclass_unref(class, string, __FILE__,__LINE__,__PRETTY_FUNCTION__) @@ -219,14 +219,14 @@ static struct mohclass *_mohclass_unref(struct mohclass *class, const char *tag, struct mohclass *dup = ao2_callback(mohclasses, OBJ_POINTER, ao2_match_by_addr, class); if (dup) { - if (__ao2_ref_debug(dup, -1, (char *) tag, (char *) file, line, funcname) == 2) { + if (__ao2_ref(dup, -1, tag, file, line, funcname) == 2) { ast_log(LOG_WARNING, "Attempt to unref mohclass %p (%s) when only 1 ref remained, and class is still in a container! (at %s:%d (%s))\n", class, class->name, file, line, funcname); } else { ao2_ref(class, -1); } } else { - __ao2_ref_debug(class, -1, (char *) tag, (char *) file, line, funcname); + __ao2_ref(class, -1, tag, file, line, funcname); } return NULL; } @@ -877,12 +877,8 @@ static struct mohclass *_get_mohbyname(const char *name, int warn, int flags, co ast_copy_string(tmp_class.name, name, sizeof(tmp_class.name)); -#ifdef REF_DEBUG - moh = __ao2_find_debug(mohclasses, &tmp_class, flags, + moh = __ao2_find(mohclasses, &tmp_class, flags, "get_mohbyname", file, lineno, funcname); -#else - moh = __ao2_find(mohclasses, &tmp_class, flags); -#endif if (!moh && warn) { ast_debug(1, "Music on Hold class '%s' not found in memory\n", name); @@ -1373,17 +1369,9 @@ static struct mohclass *_moh_class_malloc(const char *file, int line, const char { struct mohclass *class; - if ((class = -#ifdef REF_DEBUG - __ao2_alloc_debug(sizeof(*class), moh_class_destructor, - AO2_ALLOC_OPT_LOCK_MUTEX, "Allocating new moh class", file, line, funcname, 1) -#elif defined(__AST_DEBUG_MALLOC) - __ao2_alloc_debug(sizeof(*class), moh_class_destructor, - AO2_ALLOC_OPT_LOCK_MUTEX, "Allocating new moh class", file, line, funcname, 0) -#else - ao2_alloc(sizeof(*class), moh_class_destructor) -#endif - )) { + class = __ao2_alloc(sizeof(*class), moh_class_destructor, AO2_ALLOC_OPT_LOCK_MUTEX, + "Allocating new moh class", file, line, funcname); + if (class) { class->format = ao2_bump(ast_format_slin); class->srcfd = -1; }