mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-03 03:20:57 +00:00
res_pjsip_outbound_registration: Fix reload race condition.
Performing a CLI "module reload" command when there are new pjsip.conf registration objects defined frequently failed to load them correctly. What happens is a race condition between res_pjsip pushing its reload into an asynchronous task processor task and the thread that does the rest of the reloads when it gets to reloading the res_pjsip_outbound_registration module. A similar race condition happens between a reload and the CLI/AMI show registrations commands. The reload updates the current_states container and the CLI/AMI commands call get_registrations() which builds a new current_states container. * Made res_pjsip.c reload_module() use ast_sip_push_task_synchronous() instead of ast_sip_push_task() to eliminate two threads processing config reloads at the same time. * Made get_registrations() not replace the global current_states container so the CLI/AMI show registrations command cannot interfere with reloading. You could never add/remove objects in the container without the possibility of the container being replaced out from under you by get_registrations(). * Added a registration loaded sorcery instance observer to purge any dead registration objects since get_registrations() cannot do this job anymore. The struct ast_sorcery_instance_observer callbacks must be used because the callback happens inline with the load process. The struct ast_sorcery_observer callbacks are pushed to a different thread. * Added some global current_states NULL pointer checks in case the container disappears because of unload_module(). * Made sorcery's struct ast_sorcery_instance_observer.object_type_loaded callbacks guaranteed to be called before any struct ast_sorcery_observer.loaded callbacks will be called. * Moved the check for non-reloadable objects to before the sorcery instance loading callbacks happen to short circuit unnecessary work. Previously with non-reloadable objects, the sorcery instance loading/loaded callbacks would always happen, the individual wizard loading/loaded would be prevented, and the non-reloadable type logging message would be logged for each associated wizard. ASTERISK-24729 #close Review: https://reviewboard.asterisk.org/r/4381/ ........ Merged revisions 431243 from http://svn.asterisk.org/svn/asterisk/branches/13 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@431251 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -1176,12 +1176,6 @@ static int sorcery_wizard_load(void *obj, void *arg, int flags)
|
||||
struct sorcery_load_details *details = arg;
|
||||
void (*load)(void *data, const struct ast_sorcery *sorcery, const char *type);
|
||||
|
||||
if (details->reload && !sorcery_reloadable(details->sorcery, details->type)) {
|
||||
ast_log(LOG_NOTICE, "Type '%s' is not reloadable, "
|
||||
"maintaining previous values\n", details->type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
load = !details->reload ? wizard->wizard->callbacks.load : wizard->wizard->callbacks.reload;
|
||||
|
||||
if (load) {
|
||||
@@ -1256,22 +1250,31 @@ static int sorcery_object_load(void *obj, void *arg, int flags)
|
||||
|
||||
details->type = type->name;
|
||||
|
||||
if (details->reload && !sorcery_reloadable(details->sorcery, details->type)) {
|
||||
ast_log(LOG_NOTICE, "Type '%s' is not reloadable, maintaining previous values\n",
|
||||
details->type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
NOTIFY_INSTANCE_OBSERVERS(details->sorcery->observers, object_type_loading,
|
||||
details->sorcery->module_name, details->sorcery, type->name, details->reload);
|
||||
|
||||
ao2_callback(type->wizards, OBJ_NODATA, sorcery_wizard_load, details);
|
||||
|
||||
if (ao2_container_count(type->observers)) {
|
||||
struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(type, NULL);
|
||||
NOTIFY_INSTANCE_OBSERVERS(details->sorcery->observers, object_type_loaded,
|
||||
details->sorcery->module_name, details->sorcery, type->name, details->reload);
|
||||
|
||||
if (invocation && ast_taskprocessor_push(type->serializer, sorcery_observers_notify_loaded, invocation)) {
|
||||
if (ao2_container_count(type->observers)) {
|
||||
struct sorcery_observer_invocation *invocation;
|
||||
|
||||
invocation = sorcery_observer_invocation_alloc(type, NULL);
|
||||
if (invocation
|
||||
&& ast_taskprocessor_push(type->serializer, sorcery_observers_notify_loaded,
|
||||
invocation)) {
|
||||
ao2_cleanup(invocation);
|
||||
}
|
||||
}
|
||||
|
||||
NOTIFY_INSTANCE_OBSERVERS(details->sorcery->observers, object_type_loaded,
|
||||
details->sorcery->module_name, details->sorcery, type->name, details->reload);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user