static void smdi_interface_destroy(void *obj)
{
struct ast_smdi_interface *iface = obj;
+ int mod_unref_defer = 0;
if (iface->thread != AST_PTHREADT_NULL && iface->thread != AST_PTHREADT_STOP) {
pthread_cancel(iface->thread);
pthread_join(iface->thread, NULL);
+ mod_unref_defer = 1;
}
iface->thread = AST_PTHREADT_STOP;
ast_mutex_destroy(&iface->mwi_q_lock);
ast_cond_destroy(&iface->mwi_q_cond);
- free(iface);
-
- ast_module_unref(ast_module_info->self);
+ if (mod_unref_defer) {
+ ast_module_unref(ast_module_info->self);
+ }
}
/*!
md_msg = ao2_alloc(sizeof(*md_msg), NULL);
if (!md_msg) {
- ao2_ref(iface, -1);
return NULL;
}
if (c == EOF) {
ast_log(LOG_ERROR, "Unexpected EOF while reading MD message\n");
ao2_ref(md_msg, -1);
- ao2_ref(iface, -1);
return NULL;
}
md_msg->mesg_desk_num[i] = (char) c;
if (c == EOF) {
ast_log(LOG_ERROR, "Unexpected EOF while reading SMDI message\n");
ao2_ref(md_msg, -1);
- ao2_ref(iface, -1);
return NULL;
}
md_msg->mesg_desk_term[i] = (char) c;
if (c == EOF) {
ast_log(LOG_ERROR, "Unexpected EOF while reading SMDI message\n");
ao2_ref(md_msg, -1);
- ao2_ref(iface, -1);
return NULL;
}
md_msg->type = (char) c;
mwi_msg = ao2_alloc(sizeof(*mwi_msg), NULL);
if (!mwi_msg) {
- ao2_ref(iface, -1);
return NULL;
}
if (c == EOF) {
ast_log(LOG_ERROR, "Unexpected EOF while reading MWI message\n");
ao2_ref(mwi_msg, -1);
- ao2_ref(iface, -1);
return NULL;
}
mwi_msg->cause[i] = (char) c;
}
ast_log(LOG_ERROR, "Error reading from SMDI interface %s, stopping listener thread\n", iface->name);
- ao2_ref(iface, -1);
return NULL;
}
return 0;
new_ifaces = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL, smdi_ifaces_cmp_fn);
+ if (!new_ifaces) {
+ ast_config_destroy(conf);
+ return -1;
+ }
+
for (v = ast_variable_browse(conf, "interfaces"); v; v = v->next) {
RAII_VAR(struct ast_smdi_interface *, iface, NULL, ao2_cleanup);
/* set the message expiry time */
iface->msg_expiry = msg_expiry;
- /* start the listener thread */
+ /*
+ * start the listener thread
+ *
+ * The listener thread does not actually hold a ref to iface. When all
+ * external refs go away, the destructor will stop the listener thread
+ * before actually destroying the iface object.
+ */
ast_verb(3, "Starting SMDI monitor thread for %s\n", iface->name);
if (ast_pthread_create_background(&iface->thread, NULL, smdi_read, iface)) {
ast_log(LOG_ERROR, "Error starting SMDI monitor thread for %s\n", iface->name);
return -1;
}
- if (ao2_container_count(new_ifaces)) {
+ if (!ao2_container_count(new_ifaces)) {
res = 1;
}