res_pjsip: make it unloadable

The res_pjsip module was previously unloadable. With this patch it can now
be unloaded.

This patch is based off the original patch on the issue (listed below) by Corey
Farrell with a few modifications. Namely, removed a few changes not required to
make the module unloadable and also fixed a bug that would cause asterisk to
crash on unloading.

This patch is the first step (should hopefully be followed by another/others at
some point) in allowing res_pjsip and the modules that depend on it to be
unloadable. At this time, res_pjsip and some of the modules that depend on
res_pjsip cannot be unloaded without causing problems of some sort.

The goal of this patch is to get res_pjsip and only res_pjsip to be able to
unload successfully and/or shutdown without incident (crashes, leaks, etc...).
Other dependent modules may still cause problems on unload.

Basically made sure, with the patch applied, that res_pjsip (with no other
dependent modules loaded) could be succesfully unloaded and Asterisk could
shutdown without any leaks or crashes that pertained directly to res_pjsip.

ASTERISK-24485 #close
Reported by: Corey Farrell
Review: https://reviewboard.asterisk.org/r/4311/
patches:
  pjsip_unload-broken-r1.patch submitted by Corey Farrell (license 5909)
........

Merged revisions 430628 from http://svn.asterisk.org/svn/asterisk/branches/13


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@430629 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Kevin Harwell
2015-01-14 23:15:23 +00:00
parent 67234b3ee2
commit 49542a794b
11 changed files with 151 additions and 32 deletions

View File

@@ -40,6 +40,8 @@
/*** MODULEINFO
<depend>pjproject</depend>
<depend>res_sorcery_config</depend>
<depend>res_sorcery_memory</depend>
<depend>res_sorcery_astdb</depend>
<support_level>core</support_level>
***/
@@ -1805,7 +1807,7 @@ static pjsip_endpoint *ast_pjsip_endpoint;
static struct ast_threadpool *sip_threadpool;
static int register_service(void *data)
static int register_service_noref(void *data)
{
pjsip_module **module = data;
if (!ast_pjsip_endpoint) {
@@ -1817,19 +1819,33 @@ static int register_service(void *data)
return -1;
}
ast_debug(1, "Registered SIP service %.*s (%p)\n", (int) pj_strlen(&(*module)->name), pj_strbuf(&(*module)->name), *module);
ast_module_ref(ast_module_info->self);
return 0;
}
static int register_service(void *data)
{
int res;
if (!(res = register_service_noref(data))) {
ast_module_ref(ast_module_info->self);
}
return res;
}
int internal_sip_register_service(pjsip_module *module)
{
return ast_sip_push_task_synchronous(NULL, register_service_noref, &module);
}
int ast_sip_register_service(pjsip_module *module)
{
return ast_sip_push_task_synchronous(NULL, register_service, &module);
}
static int unregister_service(void *data)
static int unregister_service_noref(void *data)
{
pjsip_module **module = data;
ast_module_unref(ast_module_info->self);
if (!ast_pjsip_endpoint) {
return -1;
}
@@ -1838,6 +1854,22 @@ static int unregister_service(void *data)
return 0;
}
static int unregister_service(void *data)
{
int res;
if (!(res = unregister_service_noref(data))) {
ast_module_unref(ast_module_info->self);
}
return res;
}
int internal_sip_unregister_service(pjsip_module *module)
{
return ast_sip_push_task_synchronous(NULL, unregister_service_noref, &module);
}
void ast_sip_unregister_service(pjsip_module *module)
{
ast_sip_push_task_synchronous(NULL, unregister_service, &module);
@@ -1984,26 +2016,38 @@ struct ast_sip_endpoint *ast_sip_identify_endpoint(pjsip_rx_data *rdata)
AST_RWLIST_HEAD_STATIC(endpoint_formatters, ast_sip_endpoint_formatter);
int ast_sip_register_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
void internal_sip_register_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
{
SCOPED_LOCK(lock, &endpoint_formatters, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
AST_RWLIST_INSERT_TAIL(&endpoint_formatters, obj, next);
}
int ast_sip_register_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
{
internal_sip_register_endpoint_formatter(obj);
ast_module_ref(ast_module_info->self);
return 0;
}
void ast_sip_unregister_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
int internal_sip_unregister_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
{
struct ast_sip_endpoint_formatter *i;
SCOPED_LOCK(lock, &endpoint_formatters, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&endpoint_formatters, i, next) {
if (i == obj) {
AST_RWLIST_REMOVE_CURRENT(next);
ast_module_unref(ast_module_info->self);
break;
}
}
AST_RWLIST_TRAVERSE_SAFE_END;
return i == obj ? 0 : -1;
}
void ast_sip_unregister_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
{
if (!internal_sip_unregister_endpoint_formatter(obj)) {
ast_module_unref(ast_module_info->self);
}
}
int ast_sip_format_endpoint_ami(struct ast_sip_endpoint *endpoint,
@@ -3212,7 +3256,7 @@ static int load_module(void)
return AST_MODULE_LOAD_DECLINE;
}
if (ast_sip_register_service(&supplement_module)) {
if (internal_sip_register_service(&supplement_module)) {
ast_log(LOG_ERROR, "Failed to initialize supplement hooks. Aborting load\n");
ast_sip_destroy_distributor();
ast_res_pjsip_destroy_configuration();
@@ -3227,9 +3271,9 @@ static int load_module(void)
return AST_MODULE_LOAD_DECLINE;
}
if (ast_sip_initialize_outbound_authentication()) {
if (internal_sip_initialize_outbound_authentication()) {
ast_log(LOG_ERROR, "Failed to initialize outbound authentication. Aborting load\n");
ast_sip_unregister_service(&supplement_module);
internal_sip_unregister_service(&supplement_module);
ast_sip_destroy_distributor();
ast_res_pjsip_destroy_configuration();
ast_sip_destroy_global_headers();
@@ -3245,8 +3289,6 @@ static int load_module(void)
ast_res_pjsip_init_options_handling(0);
ast_module_ref(ast_module_info->self);
return AST_MODULE_LOAD_SUCCESS;
}
@@ -3260,9 +3302,41 @@ static int reload_module(void)
return 0;
}
static int unload_pjsip(void *data)
{
if (memory_pool) {
pj_pool_release(memory_pool);
memory_pool = NULL;
}
if (ast_pjsip_endpoint) {
pjsip_endpt_destroy(ast_pjsip_endpoint);
ast_pjsip_endpoint = NULL;
}
pj_caching_pool_destroy(&caching_pool);
pj_shutdown();
return 0;
}
static int unload_module(void)
{
/* This will never get called as this module can't be unloaded */
ast_res_pjsip_cleanup_options_handling();
internal_sip_destroy_outbound_authentication();
ast_sip_destroy_distributor();
ast_res_pjsip_destroy_configuration();
ast_sip_destroy_system();
ast_sip_destroy_global_headers();
internal_sip_unregister_service(&supplement_module);
if (monitor_thread) {
stop_monitor_thread();
}
/* The thread this is called from cannot call PJSIP/PJLIB functions,
* so we have to push the work to the threadpool to handle
*/
ast_sip_push_task_synchronous(NULL, unload_pjsip, NULL);
ast_threadpool_shutdown(sip_threadpool);
ast_sip_destroy_cli();
return 0;
}