From a094707d5156a005fb6e9277bd4a14f9d7e7ab1c Mon Sep 17 00:00:00 2001 From: Matthew Jordan Date: Tue, 2 Oct 2012 01:47:16 +0000 Subject: Fix a variety of ref counting issues This patch resolves a number of ref leaks that occur primarily on Asterisk shutdown. It adds a variety of shutdown routines to core portions of Asterisk such that they can reclaim resources allocate duringd initialization. Review: https://reviewboard.asterisk.org/r/2137 ........ Merged revisions 374177 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 374178 from http://svn.asterisk.org/svn/asterisk/branches/10 ........ Merged revisions 374196 from http://svn.asterisk.org/svn/asterisk/branches/11 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@374197 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- main/asterisk.c | 3 +++ main/astobj2.c | 34 +++++++++++++++++++++++-- main/ccss.c | 27 ++++++++++++++++++++ main/cel.c | 4 +++ main/channel.c | 11 ++++++++ main/config_options.c | 2 ++ main/data.c | 10 ++++++++ main/db.c | 6 +++++ main/event.c | 42 +++++++++++++++++++++++++++++-- main/features.c | 21 +++++++++++++++- main/format.c | 37 +++++++++++++++++++++------ main/format_pref.c | 1 + main/indications.c | 10 ++++++++ main/manager.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++--- main/message.c | 31 +++++++++++++++++++---- main/named_acl.c | 1 + main/pbx.c | 42 +++++++++++++++++++++++++++++++ main/taskprocessor.c | 9 +++++++ main/udptl.c | 9 +++++++ main/xmldoc.c | 1 + 20 files changed, 349 insertions(+), 21 deletions(-) (limited to 'main') diff --git a/main/asterisk.c b/main/asterisk.c index f586a3764..03c9962b3 100644 --- a/main/asterisk.c +++ b/main/asterisk.c @@ -1787,6 +1787,9 @@ static int can_safely_quit(shutdown_nice_t niceness, int restart) * (if in batch mode). really_quit happens to call it again when running * the atexit handlers, otherwise this would be a bit early. */ ast_cdr_engine_term(); + + /* Shutdown the message queue for the technology agnostic message channel. + * This has to occur before we pause shutdown pending ast_undestroyed_channels. */ ast_msg_shutdown(); if (niceness == SHUTDOWN_NORMAL) { diff --git a/main/astobj2.c b/main/astobj2.c index 9b5f8420e..eb4ab8e5e 100644 --- a/main/astobj2.c +++ b/main/astobj2.c @@ -544,7 +544,14 @@ int __ao2_ref(void *user_data, int delta) return internal_ao2_ref(user_data, delta, __FILE__, __LINE__, __FUNCTION__); } -void ao2_cleanup(void *obj) +void __ao2_cleanup_debug(void *obj, const char *file, int line, const char *function) +{ + if (obj) { + __ao2_ref_debug(obj, -1, "ao2_cleanup", file, line, function); + } +} + +void __ao2_cleanup(void *obj) { if (obj) { ao2_ref(obj, -1); @@ -1347,7 +1354,11 @@ static void *internal_ao2_traverse(struct ao2_container *self, enum search_flags node->obj = NULL; /* Unref the node from the container. */ - __ao2_ref(node, -1); + if (tag) { + __ao2_ref_debug(node, -1, tag, file, line, func); + } else { + __ao2_ref(node, -1); + } } } @@ -1488,7 +1499,11 @@ void ao2_iterator_destroy(struct ao2_iterator *iter) ao2_iterator_restart(iter); /* Release the iterated container reference. */ +#if defined(REF_DEBUG) + __ao2_ref_debug(iter->c, -1, "ao2_iterator_destroy", __FILE__, __LINE__, __PRETTY_FUNCTION__); +#else ao2_ref(iter->c, -1); +#endif iter->c = NULL; /* Free the malloced iterator. */ @@ -2002,7 +2017,12 @@ static struct hash_bucket_node *hash_ao2_new_node(struct ao2_container_hash *sel struct hash_bucket_node *node; int i; +#if defined(REF_DEBUG) + node = __ao2_alloc_debug(sizeof(*node), hash_ao2_node_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK, + "hash_ao2_new_node", __FILE__, __LINE__, __PRETTY_FUNCTION__, 1); +#else node = __ao2_alloc(sizeof(*node), hash_ao2_node_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK); +#endif if (!node) { return NULL; } @@ -3366,12 +3386,22 @@ static struct ast_cli_entry cli_astobj2[] = { }; #endif /* defined(AO2_DEBUG) || defined(AST_DEVMODE) */ +#if defined(AST_DEVMODE) +static void astobj2_cleanup(void) +{ + ao2_ref(reg_containers, -1); +} +#endif int astobj2_init(void) { #if defined(AST_DEVMODE) reg_containers = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_RWLOCK, AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE, ao2_reg_sort_cb, NULL); + if (!reg_containers) { + return -1; + } + ast_register_atexit(astobj2_cleanup); #endif /* defined(AST_DEVMODE) */ #if defined(AO2_DEBUG) || defined(AST_DEVMODE) ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2)); diff --git a/main/ccss.c b/main/ccss.c index 9553321c3..a45ed2844 100644 --- a/main/ccss.c +++ b/main/ccss.c @@ -4520,6 +4520,31 @@ static struct ast_cli_entry cc_cli[] = { AST_CLI_DEFINE(handle_cc_kill, "Kill a CC transaction"), }; +static void cc_shutdown(void) +{ + ast_devstate_prov_del("ccss"); + ast_cc_agent_unregister(&generic_agent_callbacks); + ast_cc_monitor_unregister(&generic_monitor_cbs); + ast_unregister_application(cccancel_app); + ast_unregister_application(ccreq_app); + + if (cc_sched_context) { + ast_sched_context_destroy(cc_sched_context); + cc_sched_context = NULL; + } + if (cc_core_taskprocessor) { + cc_core_taskprocessor = ast_taskprocessor_unreference(cc_core_taskprocessor); + } + if (generic_monitors) { + ao2_t_ref(generic_monitors, -1, "Unref generic_monitor container in cc_shutdown"); + generic_monitors = NULL; + } + if (cc_core_instances) { + ao2_t_ref(cc_core_instances, -1, "Unref cc_core_instances container in cc_shutdown"); + cc_core_instances = NULL; + } +} + int ast_cc_init(void) { int res; @@ -4557,5 +4582,7 @@ int ast_cc_init(void) initialize_cc_devstate_map(); res |= ast_devstate_prov_add("ccss", ccss_device_state); + ast_register_atexit(cc_shutdown); + return res; } diff --git a/main/cel.c b/main/cel.c index 35f78cadf..3301e81e7 100644 --- a/main/cel.c +++ b/main/cel.c @@ -716,6 +716,10 @@ static void ast_cel_engine_term(void) ao2_ref(appset, -1); appset = NULL; } + if (linkedids) { + ao2_ref(linkedids, -1); + linkedids = NULL; + } } int ast_cel_engine_init(void) diff --git a/main/channel.c b/main/channel.c index 751cbdd52..b0761e185 100644 --- a/main/channel.c +++ b/main/channel.c @@ -8553,6 +8553,15 @@ static const struct ast_data_entry channel_providers[] = { AST_DATA_ENTRY("/asterisk/core/channeltypes", &channeltypes_provider), }; +static void channels_shutdown(void) +{ + ast_data_unregister(NULL); + if (channels) { + ao2_container_unregister("channels"); + ao2_ref(channels, -1); + } +} + void ast_channels_init(void) { channels = ao2_container_alloc(NUM_CHANNEL_BUCKETS, @@ -8566,6 +8575,8 @@ void ast_channels_init(void) ast_data_register_multiple_core(channel_providers, ARRAY_LEN(channel_providers)); ast_plc_reload(); + + ast_register_atexit(channels_shutdown); } /*! \brief Print call group and pickup group ---*/ diff --git a/main/config_options.c b/main/config_options.c index c350ee5f6..5e76a7a7b 100644 --- a/main/config_options.c +++ b/main/config_options.c @@ -158,6 +158,8 @@ static int link_option_to_types(struct aco_type **types, struct aco_option *opt) } return -1; } + /* The container should hold the only ref to opt */ + ao2_ref(opt, -1); } return 0; } diff --git a/main/data.c b/main/data.c index c5a34543c..7a19b1f8f 100644 --- a/main/data.c +++ b/main/data.c @@ -3314,6 +3314,14 @@ AST_TEST_DEFINE(test_data_get) #endif +/*! \internal \brief Clean up resources on Asterisk shutdown */ +static void data_shutdown(void) +{ + ast_manager_unregister("DataGet"); + ao2_t_ref(root_data.container, -1, "Unref root_data.container in data_shutdown"); + ast_rwlock_destroy(&root_data.lock); +} + int ast_data_init(void) { int res = 0; @@ -3333,5 +3341,7 @@ int ast_data_init(void) AST_TEST_REGISTER(test_data_get); #endif + ast_register_atexit(data_shutdown); + return res; } diff --git a/main/db.c b/main/db.c index 05ae26cc9..2a19ce931 100644 --- a/main/db.c +++ b/main/db.c @@ -946,8 +946,14 @@ static void *db_sync_thread(void *data) return NULL; } +/*! \internal \brief Clean up resources on Asterisk shutdown */ static void astdb_atexit(void) { + ast_manager_unregister("DBGet"); + ast_manager_unregister("DBPut"); + ast_manager_unregister("DBDel"); + ast_manager_unregister("DBDelTree"); + /* Set doexit to 1 to kill thread. db_sync must be called with * mutex held. */ doexit = 1; diff --git a/main/event.c b/main/event.c index 12d3abb7f..4c231fe91 100644 --- a/main/event.c +++ b/main/event.c @@ -1811,6 +1811,38 @@ static struct ast_cli_entry event_cli[] = { AST_CLI_DEFINE(event_dump_cache, "Dump the internal event cache (for debugging)"), }; +/*! \internal \brief Clean up resources on Asterisk shutdown */ +static void event_shutdown(void) +{ + struct ast_event_sub *sub; + int i; + + if (event_dispatcher) { + event_dispatcher = ast_taskprocessor_unreference(event_dispatcher); + } + + /* Remove any remaining subscriptions. Note that we can't just call + * unsubscribe, as it will attempt to lock the subscription list + * as well */ + for (i = 0; i < AST_EVENT_TOTAL; i++) { + AST_RWDLLIST_WRLOCK(&ast_event_subs[i]); + while ((sub = AST_RWDLLIST_REMOVE_HEAD(&ast_event_subs[i], entry))) { + ast_event_sub_destroy(sub); + } + AST_RWDLLIST_UNLOCK(&ast_event_subs[i]); + AST_RWDLLIST_HEAD_DESTROY(&ast_event_subs[i]); + } + + for (i = 0; i < AST_EVENT_TOTAL; i++) { + if (!ast_event_cache[i].hash_fn) { + continue; + } + if (ast_event_cache[i].container) { + ao2_ref(ast_event_cache[i].container, -1); + } + } +} + int ast_event_init(void) { int i; @@ -1827,17 +1859,23 @@ int ast_event_init(void) if (!(ast_event_cache[i].container = ao2_container_alloc(NUM_CACHE_BUCKETS, ast_event_hash, ast_event_cmp))) { - return -1; + goto event_init_cleanup; } } if (!(event_dispatcher = ast_taskprocessor_get("core_event_dispatcher", 0))) { - return -1; + goto event_init_cleanup; } ast_cli_register_multiple(event_cli, ARRAY_LEN(event_cli)); + ast_register_atexit(event_shutdown); + return 0; + +event_init_cleanup: + event_shutdown(); + return -1; } size_t ast_event_minimum_length(void) diff --git a/main/features.c b/main/features.c index f89ca816d..e84a2a271 100644 --- a/main/features.c +++ b/main/features.c @@ -7023,7 +7023,6 @@ static int load_config(int reload) return -1; } ast_debug(1, "Configuration of default default parking lot done.\n"); - parkinglot_addref(default_parkinglot); } cfg = ast_config_load2("features.conf", "features", config_flags); @@ -8958,6 +8957,24 @@ static struct ast_custom_function featuremap_function = { .write = featuremap_write }; +/*! \internal \brief Clean up resources on Asterisk shutdown */ +static void features_shutdown(void) +{ + ast_devstate_prov_del("Park"); + ast_custom_function_unregister(&featuremap_function); + ast_custom_function_unregister(&feature_function); + ast_manager_unregister("Bridge"); + ast_manager_unregister("Park"); + ast_manager_unregister("Parkinglots"); + ast_manager_unregister("ParkedCalls"); + ast_unregister_application(parkcall); + ast_unregister_application(parkedcall); + ast_unregister_application(app_bridge); + + pthread_cancel(parking_thread); + ao2_ref(parkinglots, -1); +} + int ast_features_init(void) { int res; @@ -8993,6 +9010,8 @@ int ast_features_init(void) res |= AST_TEST_REGISTER(features_test); #endif /* defined(TEST_FRAMEWORK) */ + ast_register_atexit(features_shutdown); + return res; } diff --git a/main/format.c b/main/format.c index 2d37eb458..139dfd331 100644 --- a/main/format.c +++ b/main/format.c @@ -957,6 +957,7 @@ static int format_list_add_static( entry->custom_entry = 0; ao2_link(format_list, entry); + ao2_ref(entry, -1); return 0; } @@ -1025,6 +1026,7 @@ static int build_format_list_array(void) ast_rwlock_unlock(&format_list_array_lock); return 0; } + static int format_list_init(void) { struct ast_format tmpfmt; @@ -1074,6 +1076,20 @@ static int format_list_init(void) return 0; } +/*! \internal \brief Clean up resources on Asterisk shutdown */ +static void format_list_shutdown(void) +{ + ast_rwlock_destroy(&format_list_array_lock); + if (format_list) { + ao2_t_ref(format_list, -1, "Unref format_list container in shutdown"); + format_list = NULL; + } + if (format_list_array) { + ao2_t_ref(format_list_array, -1, "Unref format_list_array in shutdown"); + format_list_array = NULL; + } +} + int ast_format_list_init(void) { if (ast_rwlock_init(&format_list_array_lock)) { @@ -1086,17 +1102,23 @@ int ast_format_list_init(void) goto init_list_cleanup; } + ast_register_atexit(format_list_shutdown); return 0; init_list_cleanup: - ast_rwlock_destroy(&format_list_array_lock); - ao2_ref(format_list, -1); - if (format_list_array) { - ao2_ref(format_list_array, -1); - } + format_list_shutdown(); return -1; } +/*! \internal \brief Clean up resources on Asterisk shutdown */ +static void format_attr_shutdown(void) +{ + if (interfaces) { + ao2_ref(interfaces, -1); + interfaces = NULL; + } +} + int ast_format_attr_init(void) { ast_cli_register_multiple(my_clis, ARRAY_LEN(my_clis)); @@ -1106,6 +1128,7 @@ int ast_format_attr_init(void) if (!interfaces) { return -1; } + ast_register_atexit(format_attr_shutdown); return 0; } @@ -1371,7 +1394,7 @@ int ast_format_attr_reg_interface(const struct ast_format_attr_interface *interf ast_rtp_engine_load_format(&f_list[x].format); } } - + f_list = ast_format_list_destroy(f_list); return 0; } @@ -1405,6 +1428,6 @@ int ast_format_attr_unreg_interface(const struct ast_format_attr_interface *inte /* This will remove all custom formats previously created for this interface */ load_format_config(); - + f_list = ast_format_list_destroy(f_list); return 0; } diff --git a/main/format_pref.c b/main/format_pref.c index 9cb513c22..8b495ba56 100644 --- a/main/format_pref.c +++ b/main/format_pref.c @@ -285,6 +285,7 @@ struct ast_format_list ast_codec_pref_getsize(struct ast_codec_pref *pref, struc if (idx < 0) { ast_log(AST_LOG_WARNING, "Format %s unknown; unable to get preferred codec packet size\n", ast_getformatname(format)); + ast_format_list_destroy(f_list); return fmt; } diff --git a/main/indications.c b/main/indications.c index 4f0fc2948..f3356d603 100644 --- a/main/indications.c +++ b/main/indications.c @@ -1150,6 +1150,15 @@ int ast_tone_zone_data_add_structure(struct ast_data *tree, struct ast_tone_zone return 0; } +/*! \internal \brief Clean up resources on Asterisk shutdown */ +static void indications_shutdown(void) +{ + if (ast_tone_zones) { + ao2_ref(ast_tone_zones, -1); + ast_tone_zones = NULL; + } +} + /*! \brief Load indications module */ int ast_indications_init(void) { @@ -1164,6 +1173,7 @@ int ast_indications_init(void) ast_cli_register_multiple(cli_indications, ARRAY_LEN(cli_indications)); + ast_register_atexit(indications_shutdown); return 0; } diff --git a/main/manager.c b/main/manager.c index 4807dca82..1f25f379d 100644 --- a/main/manager.c +++ b/main/manager.c @@ -7225,6 +7225,66 @@ static void load_channelvars(struct ast_variable *var) AST_RWLIST_UNLOCK(&channelvars); } +/*! \internal \brief Clean up resources on Asterisk shutdown */ +static void manager_shutdown(void) +{ + struct ast_manager_user *user; + + if (registered) { + ast_manager_unregister("Ping"); + ast_manager_unregister("Events"); + ast_manager_unregister("Logoff"); + ast_manager_unregister("Login"); + ast_manager_unregister("Challenge"); + ast_manager_unregister("Hangup"); + ast_manager_unregister("Status"); + ast_manager_unregister("Setvar"); + ast_manager_unregister("Getvar"); + ast_manager_unregister("GetConfig"); + ast_manager_unregister("GetConfigJSON"); + ast_manager_unregister("UpdateConfig"); + ast_manager_unregister("CreateConfig"); + ast_manager_unregister("ListCategories"); + ast_manager_unregister("Redirect"); + ast_manager_unregister("Atxfer"); + ast_manager_unregister("Originate"); + ast_manager_unregister("Command"); + ast_manager_unregister("ExtensionState"); + ast_manager_unregister("PresenceState"); + ast_manager_unregister("AbsoluteTimeout"); + ast_manager_unregister("MailboxStatus"); + ast_manager_unregister("MailboxCount"); + ast_manager_unregister("ListCommands"); + ast_manager_unregister("SendText"); + ast_manager_unregister("UserEvent"); + ast_manager_unregister("WaitEvent"); + ast_manager_unregister("CoreSettings"); + ast_manager_unregister("CoreStatus"); + ast_manager_unregister("Reload"); + ast_manager_unregister("CoreShowChannels"); + ast_manager_unregister("ModuleLoad"); + ast_manager_unregister("ModuleCheck"); + ast_manager_unregister("AOCMessage"); + ast_manager_unregister("Filter"); + ast_custom_function_unregister(&managerclient_function); + } + +#ifdef AST_XML_DOCS + ao2_t_global_obj_release(event_docs, "Dispose of event_docs"); +#endif + + if (sessions) { + ao2_ref(sessions, -1); + sessions = NULL; + } + + while ((user = AST_LIST_REMOVE_HEAD(&users, list))) { + ao2_ref(user->whitefilters, -1); + ao2_ref(user->blackfilters, -1); + ast_free(user); + } +} + static int __init_manager(int reload, int by_external_config) { struct ast_config *ucfg = NULL, *cfg = NULL; @@ -7295,13 +7355,13 @@ static int __init_manager(int reload, int by_external_config) #ifdef AST_XML_DOCS temp_event_docs = ast_xmldoc_build_documentation("managerEvent"); if (temp_event_docs) { - temp_event_docs = ao2_global_obj_replace(event_docs, temp_event_docs); - if (temp_event_docs) { - ao2_ref(temp_event_docs, -1); - } + ao2_t_global_obj_replace_unref(event_docs, temp_event_docs, "Toss old event docs"); + ao2_t_ref(temp_event_docs, -1, "Remove creation ref - container holds only ref now"); } #endif + ast_register_atexit(manager_shutdown); + if ((cfg = ast_config_load2("manager.conf", "manager", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) { return 0; } @@ -7700,6 +7760,7 @@ static int __init_manager(int reload, int by_external_config) } else if (ast_ssl_setup(amis_desc.tls_cfg)) { ast_tcptls_server_start(&amis_desc); } + return 0; } diff --git a/main/message.c b/main/message.c index c04413dc8..f764e2774 100644 --- a/main/message.c +++ b/main/message.c @@ -1302,6 +1302,30 @@ int ast_msg_tech_unregister(const struct ast_msg_tech *tech) return 0; } +void ast_msg_shutdown() +{ + if (msg_q_tp) { + msg_q_tp = ast_taskprocessor_unreference(msg_q_tp); + } +} + +/*! \internal \brief Clean up other resources on Asterisk shutdown + * \note This does not include the msg_q_tp object, which must be disposed + * of prior to Asterisk checking for channel destruction in its shutdown + * sequence. The atexit handlers are executed after this occurs. */ +static void message_shutdown(void) +{ + ast_custom_function_unregister(&msg_function); + ast_custom_function_unregister(&msg_data_function); + ast_unregister_application(app_msg_send); + ast_manager_unregister("MessageSend"); + + if (msg_techs) { + ao2_ref(msg_techs, -1); + msg_techs = NULL; + } +} + /* * \internal * \brief Initialize stuff during Asterisk startup. @@ -1331,10 +1355,7 @@ int ast_msg_init(void) res |= ast_register_application2(app_msg_send, msg_send_exec, NULL, NULL, NULL); res |= ast_manager_register_xml_core("MessageSend", EVENT_FLAG_MESSAGE, action_messagesend); - return res; -} + ast_register_atexit(message_shutdown); -void ast_msg_shutdown(void) -{ - msg_q_tp = ast_taskprocessor_unreference(msg_q_tp); + return res; } diff --git a/main/named_acl.c b/main/named_acl.c index 1638459fe..fce6aa88e 100644 --- a/main/named_acl.c +++ b/main/named_acl.c @@ -545,6 +545,7 @@ int ast_named_acl_init() aco_option_register(&cfg_info, "deny", ACO_EXACT, named_acl_types, NULL, OPT_ACL_T, 0, FLDSET(struct named_acl, ha)); if (aco_process_config(&cfg_info, 0)) { + aco_info_destroy(&cfg_info); return 0; } diff --git a/main/pbx.c b/main/pbx.c index 6c1fbcdbb..1e8f1a33b 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -11488,6 +11488,32 @@ static const struct ast_data_entry pbx_data_providers[] = { AST_DATA_ENTRY("asterisk/core/hints", &hints_data_provider), }; +/*! \internal \brief Clean up resources on Asterisk shutdown. + * \note Cleans up resources allocated in load_pbx */ +static void unload_pbx(void) +{ + int x; + + if (presence_state_sub) { + presence_state_sub = ast_event_unsubscribe(presence_state_sub); + } + if (device_state_sub) { + device_state_sub = ast_event_unsubscribe(device_state_sub); + } + + /* Unregister builtin applications */ + for (x = 0; x < ARRAY_LEN(builtins); x++) { + ast_unregister_application(builtins[x].name); + } + ast_manager_unregister("ShowDialPlan"); + ast_custom_function_unregister(&exception_function); + ast_custom_function_unregister(&testtime_function); + ast_data_unregister(NULL); + if (extension_state_tps) { + extension_state_tps = ast_taskprocessor_unreference(extension_state_tps); + } +} + int load_pbx(void) { int x; @@ -11526,6 +11552,7 @@ int load_pbx(void) return -1; } + ast_register_atexit(unload_pbx); return 0; } @@ -11886,11 +11913,26 @@ static int statecbs_cmp(void *obj, void *arg, int flags) return (state_cb->change_cb == change_cb) ? CMP_MATCH | CMP_STOP : 0; } +/*! \internal \brief Clean up resources on Asterisk shutdown */ +static void pbx_shutdown(void) +{ + if (hints) { + ao2_ref(hints, -1); + } + if (hintdevices) { + ao2_ref(hintdevices, -1); + } + if (statecbs) { + ao2_ref(statecbs, -1); + } +} + int ast_pbx_init(void) { hints = ao2_container_alloc(HASH_EXTENHINT_SIZE, hint_hash, hint_cmp); hintdevices = ao2_container_alloc(HASH_EXTENHINT_SIZE, hintdevice_hash_cb, hintdevice_cmp_multiple); statecbs = ao2_container_alloc(1, NULL, statecbs_cmp); + ast_register_atexit(pbx_shutdown); return (hints && hintdevices && statecbs) ? 0 : -1; } diff --git a/main/taskprocessor.c b/main/taskprocessor.c index e92b6948b..912f891b1 100644 --- a/main/taskprocessor.c +++ b/main/taskprocessor.c @@ -122,6 +122,12 @@ static struct ast_cli_entry taskprocessor_clis[] = { AST_CLI_DEFINE(cli_tps_report, "List instantiated task processors and statistics"), }; +/*! \internal \brief Clean up resources on Asterisk shutdown */ +static void tps_shutdown(void) +{ + ao2_t_ref(tps_singletons, -1, "Unref tps_singletons in shutdown"); +} + /* initialize the taskprocessor container and register CLI operations */ int ast_tps_init(void) { @@ -133,6 +139,9 @@ int ast_tps_init(void) ast_cond_init(&cli_ping_cond, NULL); ast_cli_register_multiple(taskprocessor_clis, ARRAY_LEN(taskprocessor_clis)); + + ast_register_atexit(tps_shutdown); + return 0; } diff --git a/main/udptl.c b/main/udptl.c index 3d110e21b..83dcd3d90 100644 --- a/main/udptl.c +++ b/main/udptl.c @@ -1462,6 +1462,13 @@ int ast_udptl_reload(void) return 0; } +/*! \internal \brief Clean up resources on Asterisk shutdown */ +static void udptl_shutdown(void) +{ + ao2_t_global_obj_release(globals, "Unref udptl global container in shutdown"); + aco_info_destroy(&cfg_info); +} + void ast_udptl_init(void) { if (aco_info_init(&cfg_info)) { @@ -1496,4 +1503,6 @@ void ast_udptl_init(void) ast_cli_register_multiple(cli_udptl, ARRAY_LEN(cli_udptl)); __ast_udptl_reload(0); + + ast_register_atexit(udptl_shutdown); } diff --git a/main/xmldoc.c b/main/xmldoc.c index 3c01d4300..0a8da5896 100644 --- a/main/xmldoc.c +++ b/main/xmldoc.c @@ -2279,6 +2279,7 @@ struct ao2_container *ast_xmldoc_build_documentation(const char *type) if (item) { ao2_link(docs, item); + ao2_t_ref(item, -1, "Dispose of creation ref"); item = NULL; } } -- cgit v1.2.3