<p>Joshua Colp <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/7831">View Change</a></p><div style="white-space:pre-wrap">Approvals:
Richard Mudgett: Looks good to me, but someone else must approve
Joshua Colp: Looks good to me, approved; Approved for Submit
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">res_stasis: Reduce RAII_VAR usage.<br><br>In addition to being a micro-optimization (RAII_VAR has overhead), this<br>change improves output of REF_DEBUG. Unfortunately when RAII_VAR calls<br>ao2_cleanup it does so from a generated _dtor_varname function. For<br>example this caused _dtor_app to release a reference instead of<br>__stasis_app_unregister.<br><br>Change-Id: I4ce67120583a446babf9adeec678b71d37fcd9e5<br>---<br>M res/res_stasis.c<br>M res/stasis/app.c<br>M res/stasis/command.c<br>M res/stasis/control.c<br>M res/stasis/stasis_bridge.c<br>5 files changed, 323 insertions(+), 172 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/res/res_stasis.c b/res/res_stasis.c<br>index 42a19bf..be3cb7f 100644<br>--- a/res/res_stasis.c<br>+++ b/res/res_stasis.c<br>@@ -498,7 +498,8 @@<br> /*! Request a bridge MOH channel */<br> static struct ast_channel *prepare_bridge_moh_channel(void)<br> {<br>- RAII_VAR(struct ast_format_cap *, cap, NULL, ao2_cleanup);<br>+ struct ast_channel *chan;<br>+ struct ast_format_cap *cap;<br> <br> cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);<br> if (!cap) {<br>@@ -507,7 +508,10 @@<br> <br> ast_format_cap_append(cap, ast_format_slin, 0);<br> <br>- return ast_request("Announcer", cap, NULL, NULL, "ARI_MOH", NULL);<br>+ chan = ast_request("Announcer", cap, NULL, NULL, "ARI_MOH", NULL);<br>+ ao2_ref(cap, -1);<br>+<br>+ return chan;<br> }<br> <br> /*! Provides the moh channel with a thread so it can actually play its music */<br>@@ -599,23 +603,27 @@<br> <br> struct ast_channel *stasis_app_bridge_moh_channel(struct ast_bridge *bridge)<br> {<br>- RAII_VAR(struct stasis_app_bridge_channel_wrapper *, moh_wrapper, NULL, ao2_cleanup);<br>+ struct ast_channel *chan;<br>+ struct stasis_app_bridge_channel_wrapper *moh_wrapper;<br> <br>- {<br>- SCOPED_AO2LOCK(lock, app_bridges_moh);<br>+ ao2_lock(app_bridges_moh);<br>+ moh_wrapper = ao2_find(app_bridges_moh, bridge->uniqueid, OBJ_SEARCH_KEY | OBJ_NOLOCK);<br>+ if (!moh_wrapper) {<br>+ chan = bridge_moh_create(bridge);<br>+ }<br>+ ao2_unlock(app_bridges_moh);<br> <br>- moh_wrapper = ao2_find(app_bridges_moh, bridge->uniqueid, OBJ_SEARCH_KEY | OBJ_NOLOCK);<br>- if (!moh_wrapper) {<br>- return bridge_moh_create(bridge);<br>- }<br>+ if (moh_wrapper) {<br>+ chan = ast_channel_get_by_name(moh_wrapper->channel_id);<br>+ ao2_ref(moh_wrapper, -1);<br> }<br> <br>- return ast_channel_get_by_name(moh_wrapper->channel_id);<br>+ return chan;<br> }<br> <br> int stasis_app_bridge_moh_stop(struct ast_bridge *bridge)<br> {<br>- RAII_VAR(struct stasis_app_bridge_channel_wrapper *, moh_wrapper, NULL, ao2_cleanup);<br>+ struct stasis_app_bridge_channel_wrapper *moh_wrapper;<br> struct ast_channel *chan;<br> <br> moh_wrapper = ao2_find(app_bridges_moh, bridge->uniqueid, OBJ_SEARCH_KEY | OBJ_UNLINK);<br>@@ -624,6 +632,7 @@<br> }<br> <br> chan = ast_channel_get_by_name(moh_wrapper->channel_id);<br>+ ao2_ref(moh_wrapper, -1);<br> if (!chan) {<br> return -1;<br> }<br>@@ -862,25 +871,30 @@<br> static struct replace_channel_store *get_replace_channel_store(struct ast_channel *chan, int no_create)<br> {<br> struct ast_datastore *datastore;<br>+ struct replace_channel_store *ret;<br> <br>- SCOPED_CHANNELLOCK(lock, chan);<br>+ ast_channel_lock(chan);<br> datastore = ast_channel_datastore_find(chan, &replace_channel_store_info, NULL);<br>- if (!datastore) {<br>- if (no_create) {<br>- return NULL;<br>- }<br>-<br>+ if (!datastore && !no_create) {<br> datastore = ast_datastore_alloc(&replace_channel_store_info, NULL);<br>- if (!datastore) {<br>- return NULL;<br>+ if (datastore) {<br>+ ast_channel_datastore_add(chan, datastore);<br> }<br>- ast_channel_datastore_add(chan, datastore);<br>+ }<br>+<br>+ if (!datastore) {<br>+ ast_channel_unlock(chan);<br>+ return NULL;<br> }<br> <br> if (!datastore->data) {<br> datastore->data = ast_calloc(1, sizeof(struct replace_channel_store));<br> }<br>- return datastore->data;<br>+<br>+ ret = datastore->data;<br>+ ast_channel_unlock(chan);<br>+<br>+ return ret;<br> }<br> <br> int app_set_replace_channel_snapshot(struct ast_channel *chan, struct ast_channel_snapshot *replace_snapshot)<br>@@ -959,9 +973,9 @@<br> int argc, char *argv[], struct ast_channel_snapshot *snapshot,<br> struct ast_channel_snapshot *replace_channel_snapshot)<br> {<br>- RAII_VAR(struct ast_json *, json_blob, NULL, ast_json_unref);<br>+ struct ast_json *json_blob;<br> struct ast_json *json_args;<br>- RAII_VAR(struct start_message_blob *, payload, NULL, ao2_cleanup);<br>+ struct start_message_blob *payload;<br> struct stasis_message *msg;<br> int i;<br> <br>@@ -986,8 +1000,11 @@<br> "args");<br> if (!json_blob) {<br> ast_log(LOG_ERROR, "Error packing JSON for StasisStart message\n");<br>+ ao2_ref(payload, -1);<br> return -1;<br> }<br>+ payload->blob = json_blob;<br>+<br> <br> /* Append arguments to args array */<br> json_args = ast_json_object_get(json_blob, "args");<br>@@ -997,13 +1014,14 @@<br> ast_json_string_create(argv[i]));<br> if (r != 0) {<br> ast_log(LOG_ERROR, "Error appending to StasisStart message\n");<br>+ ao2_ref(payload, -1);<br> return -1;<br> }<br> }<br> <br>- payload->blob = ast_json_ref(json_blob);<br> <br> msg = stasis_message_create(start_message_type(), payload);<br>+ ao2_ref(payload, -1);<br> if (!msg) {<br> ast_log(LOG_ERROR, "Error sending StasisStart message\n");<br> return -1;<br>@@ -1020,9 +1038,9 @@<br> static int send_start_msg(struct stasis_app *app, struct ast_channel *chan,<br> int argc, char *argv[])<br> {<br>- RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);<br>- RAII_VAR(struct ast_channel_snapshot *, replace_channel_snapshot,<br>- NULL, ao2_cleanup);<br>+ int ret = -1;<br>+ struct ast_channel_snapshot *snapshot;<br>+ struct ast_channel_snapshot *replace_channel_snapshot;<br> <br> ast_assert(chan != NULL);<br> <br>@@ -1032,10 +1050,13 @@<br> ast_channel_lock(chan);<br> snapshot = ast_channel_snapshot_create(chan);<br> ast_channel_unlock(chan);<br>- if (!snapshot) {<br>- return -1;<br>+ if (snapshot) {<br>+ ret = send_start_msg_snapshots(chan, app, argc, argv, snapshot, replace_channel_snapshot);<br>+ ao2_ref(snapshot, -1);<br> }<br>- return send_start_msg_snapshots(chan, app, argc, argv, snapshot, replace_channel_snapshot);<br>+ ao2_cleanup(replace_channel_snapshot);<br>+<br>+ return ret;<br> }<br> <br> static void remove_masquerade_store(struct ast_channel *chan);<br>@@ -1478,7 +1499,7 @@<br> <br> int stasis_app_send(const char *app_name, struct ast_json *message)<br> {<br>- RAII_VAR(struct stasis_app *, app, NULL, ao2_cleanup);<br>+ struct stasis_app *app;<br> <br> if (!apps_registry) {<br> return -1;<br>@@ -1494,6 +1515,8 @@<br> return -1;<br> }<br> app_send(app, message);<br>+ ao2_ref(app, -1);<br>+<br> return 0;<br> }<br> <br>@@ -1528,7 +1551,7 @@<br> <br> struct ao2_container *stasis_app_get_all(void)<br> {<br>- RAII_VAR(struct ao2_container *, apps, NULL, ao2_cleanup);<br>+ struct ao2_container *apps;<br> <br> if (!apps_registry) {<br> return NULL;<br>@@ -1541,12 +1564,12 @@<br> <br> ao2_callback(apps_registry, OBJ_NODATA, append_name, apps);<br> <br>- return ao2_bump(apps);<br>+ return apps;<br> }<br> <br> static int __stasis_app_register(const char *app_name, stasis_app_cb handler, void *data, int all_events)<br> {<br>- RAII_VAR(struct stasis_app *, app, NULL, ao2_cleanup);<br>+ struct stasis_app *app;<br> <br> if (!apps_registry) {<br> return -1;<br>@@ -1558,24 +1581,25 @@<br> app_update(app, handler, data);<br> } else {<br> app = app_create(app_name, handler, data, all_events ? STASIS_APP_SUBSCRIBE_ALL : STASIS_APP_SUBSCRIBE_MANUAL);<br>- if (app) {<br>- if (all_events) {<br>- struct stasis_app_event_source *source;<br>- SCOPED_LOCK(lock, &event_sources, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK);<br>-<br>- AST_LIST_TRAVERSE(&event_sources, source, next) {<br>- if (!source->subscribe) {<br>- continue;<br>- }<br>-<br>- source->subscribe(app, NULL);<br>- }<br>- }<br>- ao2_link_flags(apps_registry, app, OBJ_NOLOCK);<br>- } else {<br>+ if (!app) {<br> ao2_unlock(apps_registry);<br> return -1;<br> }<br>+<br>+ if (all_events) {<br>+ struct stasis_app_event_source *source;<br>+<br>+ AST_RWLIST_RDLOCK(&event_sources);<br>+ AST_LIST_TRAVERSE(&event_sources, source, next) {<br>+ if (!source->subscribe) {<br>+ continue;<br>+ }<br>+<br>+ source->subscribe(app, NULL);<br>+ }<br>+ AST_RWLIST_UNLOCK(&event_sources);<br>+ }<br>+ ao2_link_flags(apps_registry, app, OBJ_NOLOCK);<br> }<br> <br> /* We lazily clean up the apps_registry, because it's good enough to<br>@@ -1583,6 +1607,7 @@<br> */<br> cleanup();<br> ao2_unlock(apps_registry);<br>+ ao2_ref(app, -1);<br> return 0;<br> }<br> <br>@@ -1598,7 +1623,7 @@<br> <br> void stasis_app_unregister(const char *app_name)<br> {<br>- RAII_VAR(struct stasis_app *, app, NULL, ao2_cleanup);<br>+ struct stasis_app *app;<br> <br> if (!app_name) {<br> return;<br>@@ -1621,23 +1646,27 @@<br> * and clean up, just in case<br> */<br> cleanup();<br>+<br>+ ao2_ref(app, -1);<br> }<br> <br> void stasis_app_register_event_source(struct stasis_app_event_source *obj)<br> {<br>- SCOPED_LOCK(lock, &event_sources, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);<br>+ AST_RWLIST_WRLOCK(&event_sources);<br> AST_LIST_INSERT_TAIL(&event_sources, obj, next);<br> /* only need to bump the module ref on non-core sources because the<br> core ones are [un]registered by this module. */<br> if (!stasis_app_is_core_event_source(obj)) {<br> ast_module_ref(ast_module_info->self);<br> }<br>+ AST_RWLIST_UNLOCK(&event_sources);<br> }<br> <br> void stasis_app_unregister_event_source(struct stasis_app_event_source *obj)<br> {<br> struct stasis_app_event_source *source;<br>- SCOPED_LOCK(lock, &event_sources, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);<br>+<br>+ AST_RWLIST_WRLOCK(&event_sources);<br> AST_RWLIST_TRAVERSE_SAFE_BEGIN(&event_sources, source, next) {<br> if (source == obj) {<br> AST_RWLIST_REMOVE_CURRENT(next);<br>@@ -1648,6 +1677,7 @@<br> }<br> }<br> AST_RWLIST_TRAVERSE_SAFE_END;<br>+ AST_RWLIST_UNLOCK(&event_sources);<br> }<br> <br> /*!<br>@@ -1666,12 +1696,15 @@<br> const struct stasis_app *app, struct ast_json *json)<br> {<br> struct stasis_app_event_source *source;<br>- SCOPED_LOCK(lock, &event_sources, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK);<br>+<br>+ AST_RWLIST_RDLOCK(&event_sources);<br> AST_LIST_TRAVERSE(&event_sources, source, next) {<br> if (source->to_json) {<br> source->to_json(app, json);<br> }<br> }<br>+ AST_RWLIST_UNLOCK(&event_sources);<br>+<br> return json;<br> }<br> <br>@@ -1686,9 +1719,12 @@<br> <br> struct ast_json *stasis_app_to_json(const char *app_name)<br> {<br>- RAII_VAR(struct stasis_app *, app, find_app_by_name(app_name), ao2_cleanup);<br>+ struct stasis_app *app = find_app_by_name(app_name);<br>+ struct ast_json *json = stasis_app_object_to_json(app);<br> <br>- return stasis_app_object_to_json(app);<br>+ ao2_cleanup(app);<br>+<br>+ return json;<br> }<br> <br> /*!<br>@@ -1705,13 +1741,16 @@<br> static struct stasis_app_event_source *app_event_source_find(const char *uri)<br> {<br> struct stasis_app_event_source *source;<br>- SCOPED_LOCK(lock, &event_sources, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK);<br>+<br>+ AST_RWLIST_RDLOCK(&event_sources);<br> AST_LIST_TRAVERSE(&event_sources, source, next) {<br> if (ast_begins_with(uri, source->scheme)) {<br>- return source;<br>+ break;<br> }<br> }<br>- return NULL;<br>+ AST_RWLIST_UNLOCK(&event_sources);<br>+<br>+ return source;<br> }<br> <br> /*!<br>@@ -1746,8 +1785,10 @@<br> int event_sources_count, struct ast_json **json,<br> app_subscription_handler handler)<br> {<br>- RAII_VAR(struct stasis_app *, app, find_app_by_name(app_name), ao2_cleanup);<br>+ struct stasis_app *app = find_app_by_name(app_name);<br> int i;<br>+<br>+ ast_assert(handler != NULL);<br> <br> if (!app) {<br> return STASIS_ASR_APP_NOT_FOUND;<br>@@ -1755,16 +1796,21 @@<br> <br> for (i = 0; i < event_sources_count; ++i) {<br> const char *uri = event_source_uris[i];<br>- enum stasis_app_subscribe_res res = STASIS_ASR_INTERNAL_ERROR;<br> struct stasis_app_event_source *event_source;<br>+ enum stasis_app_subscribe_res res;<br> <br>- if (!(event_source = app_event_source_find(uri))) {<br>+ event_source = app_event_source_find(uri);<br>+ if (!event_source) {<br> ast_log(LOG_WARNING, "Invalid scheme: %s\n", uri);<br>+ ao2_ref(app, -1);<br>+<br> return STASIS_ASR_EVENT_SOURCE_BAD_SCHEME;<br> }<br> <br>- if (handler &&<br>- ((res = handler(app, uri, event_source)))) {<br>+ res = handler(app, uri, event_source);<br>+ if (res != STASIS_ASR_OK) {<br>+ ao2_ref(app, -1);<br>+<br> return res;<br> }<br> }<br>@@ -1774,13 +1820,15 @@<br> *json = stasis_app_object_to_json(app);<br> }<br> <br>+ ao2_ref(app, -1);<br>+<br> return STASIS_ASR_OK;<br> }<br> <br> enum stasis_app_subscribe_res stasis_app_subscribe_channel(const char *app_name,<br> struct ast_channel *chan)<br> {<br>- RAII_VAR(struct stasis_app *, app, find_app_by_name(app_name), ao2_cleanup);<br>+ struct stasis_app *app = find_app_by_name(app_name);<br> int res;<br> <br> if (!app) {<br>@@ -1790,6 +1838,8 @@<br> ast_debug(3, "%s: Subscribing to %s\n", app_name, ast_channel_uniqueid(chan));<br> <br> res = app_subscribe_channel(app, chan);<br>+ ao2_ref(app, -1);<br>+<br> if (res != 0) {<br> ast_log(LOG_ERROR, "Error subscribing app '%s' to channel '%s'\n",<br> app_name, ast_channel_uniqueid(chan));<br>@@ -1892,12 +1942,10 @@<br> struct ast_json *json_variables)<br> {<br> RAII_VAR(struct stasis_app *, app, find_app_by_name(app_name), ao2_cleanup);<br>- RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);<br>- RAII_VAR(struct ast_multi_object_blob *, multi, NULL, ao2_cleanup);<br>- RAII_VAR(void *, obj, NULL, ao2_cleanup);<br>- RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);<br>+ struct ast_json *blob = NULL;<br>+ struct ast_multi_object_blob *multi;<br>+ struct stasis_message *message;<br> enum stasis_app_user_event_res res = STASIS_APP_USER_INTERNAL_ERROR;<br>- struct ast_json *json_value;<br> int have_channel = 0;<br> int i;<br> <br>@@ -1910,23 +1958,29 @@<br> return res;<br> }<br> <br>- blob = json_variables;<br>- if (!blob) {<br>- blob = ast_json_pack("{}");<br>+ if (json_variables) {<br>+ struct ast_json *json_value = ast_json_string_create(event_name);<br>+<br>+ if (json_value && !ast_json_object_set(json_variables, "eventname", json_value)) {<br>+ blob = ast_json_ref(json_variables);<br>+ }<br> } else {<br>- ast_json_ref(blob);<br>+ blob = ast_json_pack("{s: s}", "eventname", event_name);<br> }<br>- json_value = ast_json_string_create(event_name);<br>- if (!json_value) {<br>- ast_log(LOG_ERROR, "unable to create json string\n");<br>- return res;<br>- }<br>- if (ast_json_object_set(blob, "eventname", json_value)) {<br>- ast_log(LOG_ERROR, "unable to set eventname to blob\n");<br>+<br>+ if (!blob) {<br>+ ast_log(LOG_ERROR, "Failed to initialize blob\n");<br>+<br> return res;<br> }<br> <br> multi = ast_multi_object_blob_create(blob);<br>+ ast_json_unref(blob);<br>+ if (!multi) {<br>+ ast_log(LOG_ERROR, "Failed to initialize multi\n");<br>+<br>+ return res;<br>+ }<br> <br> for (i = 0; i < sources_count; ++i) {<br> const char *uri = source_uris[i];<br>@@ -1945,16 +1999,22 @@<br> snapshot = ast_endpoint_latest_snapshot(uri + 9, NULL);<br> } else {<br> ast_log(LOG_WARNING, "Invalid scheme: %s\n", uri);<br>+ ao2_ref(multi, -1);<br>+<br> return STASIS_APP_USER_EVENT_SOURCE_BAD_SCHEME;<br> }<br> if (!snapshot) {<br> ast_log(LOG_ERROR, "Unable to get snapshot for %s\n", uri);<br>+ ao2_ref(multi, -1);<br>+<br> return STASIS_APP_USER_EVENT_SOURCE_NOT_FOUND;<br> }<br> ast_multi_object_blob_add(multi, type, snapshot);<br> }<br> <br> message = stasis_message_create(ast_multi_user_event_type(), multi);<br>+ ao2_ref(multi, -1);<br>+<br> if (!message) {<br> ast_log(LOG_ERROR, "Unable to create stasis user event message\n");<br> return res;<br>@@ -1971,6 +2031,7 @@<br> if (have_channel) {<br> stasis_publish(ast_manager_get_topic(), message);<br> }<br>+ ao2_ref(message, -1);<br> <br> return STASIS_APP_USER_OK;<br> }<br>@@ -2036,9 +2097,14 @@<br> /* \brief Sanitization callback for channel unique IDs */<br> static int channel_id_sanitizer(const char *id)<br> {<br>- RAII_VAR(struct ast_channel_snapshot *, snapshot, ast_channel_snapshot_get_latest(id), ao2_cleanup);<br>+ struct ast_channel_snapshot *snapshot;<br>+ int ret;<br> <br>- return channel_snapshot_sanitizer(snapshot);<br>+ snapshot = ast_channel_snapshot_get_latest(id);<br>+ ret = channel_snapshot_sanitizer(snapshot);<br>+ ao2_cleanup(snapshot);<br>+<br>+ return ret;<br> }<br> <br> /* \brief Sanitization callbacks for communication to Stasis applications */<br>diff --git a/res/stasis/app.c b/res/stasis/app.c<br>index 667636e..344f2b9 100644<br>--- a/res/stasis/app.c<br>+++ b/res/stasis/app.c<br>@@ -112,20 +112,19 @@<br> static struct app_forwards *forwards_create(struct stasis_app *app,<br> const char *id)<br> {<br>- RAII_VAR(struct app_forwards *, forwards, NULL, ao2_cleanup);<br>+ struct app_forwards *forwards;<br> <br> if (!app || ast_strlen_zero(id)) {<br> return NULL;<br> }<br> <br>- forwards = ao2_alloc(sizeof(*forwards) + strlen(id) + 1, forwards_dtor);<br>+ forwards = ao2_t_alloc(sizeof(*forwards) + strlen(id) + 1, forwards_dtor, id);<br> if (!forwards) {<br> return NULL;<br> }<br> <br>- strcpy(forwards->id, id);<br>+ strcpy(forwards->id, id); /* SAFE */<br> <br>- ao2_ref(forwards, +1);<br> return forwards;<br> }<br> <br>@@ -335,7 +334,7 @@<br> struct stasis_message *message)<br> {<br> struct stasis_app *app = data;<br>- RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);<br>+ struct ast_json *json;<br> <br> if (stasis_subscription_final_message(sub, message)) {<br> ao2_cleanup(app);<br>@@ -352,6 +351,7 @@<br> }<br> <br> app_send(app, json);<br>+ ast_json_unref(json);<br> }<br> <br> /*! \brief Typedef for callbacks that get called on channel snapshot updates */<br>@@ -554,11 +554,12 @@<br> stasis_message_timestamp(message);<br> <br> for (i = 0; i < ARRAY_LEN(channel_monitors); ++i) {<br>- RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref);<br>+ struct ast_json *msg;<br> <br> msg = channel_monitors[i](old_snapshot, new_snapshot, tv);<br> if (msg) {<br> app_send(app, msg);<br>+ ast_json_unref(msg);<br> }<br> }<br> <br>@@ -586,7 +587,7 @@<br> <br> static int message_received_handler(const char *endpoint_id, struct ast_json *json_msg, void *pvt)<br> {<br>- RAII_VAR(struct ast_endpoint_snapshot *, snapshot, NULL, ao2_cleanup);<br>+ struct ast_endpoint_snapshot *snapshot;<br> struct ast_json *json_endpoint;<br> struct ast_json *message;<br> struct stasis_app *app = pvt;<br>@@ -610,6 +611,7 @@<br> }<br> <br> json_endpoint = ast_endpoint_snapshot_to_json(snapshot, stasis_app_get_sanitizer());<br>+ ao2_ref(snapshot, -1);<br> if (!json_endpoint) {<br> return -1;<br> }<br>@@ -631,7 +633,6 @@<br> struct stasis_subscription *sub,<br> struct stasis_message *message)<br> {<br>- RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);<br> struct stasis_app *app = data;<br> struct stasis_cache_update *update;<br> struct ast_endpoint_snapshot *new_snapshot;<br>@@ -648,6 +649,8 @@<br> old_snapshot = stasis_message_data(update->old_snapshot);<br> <br> if (new_snapshot) {<br>+ struct ast_json *json;<br>+<br> tv = stasis_message_timestamp(update->new_snapshot);<br> <br> json = simple_endpoint_event("EndpointStateChange", new_snapshot, tv);<br>@@ -656,6 +659,7 @@<br> }<br> <br> app_send(app, json);<br>+ ast_json_unref(json);<br> }<br> <br> if (!new_snapshot && old_snapshot) {<br>@@ -683,7 +687,7 @@<br> struct stasis_subscription *sub,<br> struct stasis_message *message)<br> {<br>- RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);<br>+ struct ast_json *json = NULL;<br> struct stasis_app *app = data;<br> struct stasis_cache_update *update;<br> struct ast_bridge_snapshot *new_snapshot;<br>@@ -717,6 +721,7 @@<br> <br> if (json) {<br> app_send(app, json);<br>+ ast_json_unref(json);<br> }<br> <br> if (!new_snapshot && old_snapshot) {<br>@@ -1019,7 +1024,7 @@<br> {<br> stasis_app_cb handler;<br> char eid[20];<br>- RAII_VAR(void *, data, NULL, ao2_cleanup);<br>+ void *data;<br> <br> if (ast_json_object_set(message, "asterisk_id", ast_json_string_create(<br> ast_eid_to_str(eid, sizeof(eid), &ast_eid_default)))) {<br>@@ -1028,37 +1033,36 @@<br> }<br> <br> /* Copy off mutable state with lock held */<br>- {<br>- SCOPED_AO2LOCK(lock, app);<br>- handler = app->handler;<br>- if (app->data) {<br>- ao2_ref(app->data, +1);<br>- data = app->data;<br>- }<br>- /* Name is immutable; no need to copy */<br>- }<br>+ ao2_lock(app);<br>+ handler = app->handler;<br>+ data = ao2_bump(app->data);<br>+ ao2_unlock(app);<br>+ /* Name is immutable; no need to copy */<br> <br>- if (!handler) {<br>+ if (handler) {<br>+ handler(data, app->name, message);<br>+ } else {<br> ast_verb(3,<br> "Inactive Stasis app '%s' missed message\n", app->name);<br>- return;<br> }<br>-<br>- handler(data, app->name, message);<br>+ ao2_cleanup(data);<br> }<br> <br> void app_deactivate(struct stasis_app *app)<br> {<br>- SCOPED_AO2LOCK(lock, app);<br>+ ao2_lock(app);<br>+<br> ast_verb(1, "Deactivating Stasis app '%s'\n", app->name);<br> app->handler = NULL;<br> ao2_cleanup(app->data);<br> app->data = NULL;<br>+<br>+ ao2_unlock(app);<br> }<br> <br> void app_shutdown(struct stasis_app *app)<br> {<br>- SCOPED_AO2LOCK(lock, app);<br>+ ao2_lock(app);<br> <br> ast_assert(app_is_finished(app));<br> <br>@@ -1068,27 +1072,37 @@<br> app->bridge_router = NULL;<br> stasis_message_router_unsubscribe(app->endpoint_router);<br> app->endpoint_router = NULL;<br>+<br>+ ao2_unlock(app);<br> }<br> <br> int app_is_active(struct stasis_app *app)<br> {<br>- SCOPED_AO2LOCK(lock, app);<br>- return app->handler != NULL;<br>+ int ret;<br>+<br>+ ao2_lock(app);<br>+ ret = app->handler != NULL;<br>+ ao2_unlock(app);<br>+<br>+ return ret;<br> }<br> <br> int app_is_finished(struct stasis_app *app)<br> {<br>- SCOPED_AO2LOCK(lock, app);<br>+ int ret;<br> <br>- return app->handler == NULL && ao2_container_count(app->forwards) == 0;<br>+ ao2_lock(app);<br>+ ret = app->handler == NULL && ao2_container_count(app->forwards) == 0;<br>+ ao2_unlock(app);<br>+<br>+ return ret;<br> }<br> <br> void app_update(struct stasis_app *app, stasis_app_cb handler, void *data)<br> {<br>- SCOPED_AO2LOCK(lock, app);<br>-<br>+ ao2_lock(app);<br> if (app->handler && app->data) {<br>- RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref);<br>+ struct ast_json *msg;<br> <br> ast_verb(1, "Replacing Stasis app '%s'\n", app->name);<br> <br>@@ -1097,17 +1111,15 @@<br> "application", app->name);<br> if (msg) {<br> app_send(app, msg);<br>+ ast_json_unref(msg);<br> }<br> } else {<br> ast_verb(1, "Activating Stasis app '%s'\n", app->name);<br> }<br> <br> app->handler = handler;<br>- ao2_cleanup(app->data);<br>- if (data) {<br>- ao2_ref(data, +1);<br>- }<br>- app->data = data;<br>+ ao2_replace(app->data, data);<br>+ ao2_unlock(app);<br> }<br> <br> const char *stasis_app_name(const struct stasis_app *app)<br>@@ -1184,68 +1196,72 @@<br> <br> struct ast_json *app_to_json(const struct stasis_app *app)<br> {<br>- RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);<br>+ struct ast_json *json;<br> struct ast_json *channels;<br> struct ast_json *bridges;<br> struct ast_json *endpoints;<br> struct ao2_iterator i;<br>- void *obj;<br>+ struct app_forwards *forwards;<br> <br> json = ast_json_pack("{s: s, s: [], s: [], s: []}",<br> "name", app->name,<br> "channel_ids", "bridge_ids", "endpoint_ids");<br>+ if (!json) {<br>+ return NULL;<br>+ }<br> channels = ast_json_object_get(json, "channel_ids");<br> bridges = ast_json_object_get(json, "bridge_ids");<br> endpoints = ast_json_object_get(json, "endpoint_ids");<br> <br> i = ao2_iterator_init(app->forwards, 0);<br>- while ((obj = ao2_iterator_next(&i))) {<br>- RAII_VAR(struct app_forwards *, forwards, obj, ao2_cleanup);<br>- RAII_VAR(struct ast_json *, id, NULL, ast_json_unref);<br>- int append_res = -1;<br>-<br>- id = ast_json_string_create(forwards->id);<br>+ while ((forwards = ao2_iterator_next(&i))) {<br>+ struct ast_json *array = NULL;<br>+ int append_res;<br> <br> switch (forwards->forward_type) {<br> case FORWARD_CHANNEL:<br>- append_res = ast_json_array_append(channels,<br>- ast_json_ref(id));<br>+ array = channels;<br> break;<br> case FORWARD_BRIDGE:<br>- append_res = ast_json_array_append(bridges,<br>- ast_json_ref(id));<br>+ array = bridges;<br> break;<br> case FORWARD_ENDPOINT:<br>- append_res = ast_json_array_append(endpoints,<br>- ast_json_ref(id));<br>+ array = endpoints;<br> break;<br> }<br>+<br>+ /* If forward_type value is unexpected this will safely return an error. */<br>+ append_res = ast_json_array_append(array, ast_json_string_create(forwards->id));<br>+ ao2_ref(forwards, -1);<br> <br> if (append_res != 0) {<br> ast_log(LOG_ERROR, "Error building response\n");<br> ao2_iterator_destroy(&i);<br>+ ast_json_unref(json);<br>+<br> return NULL;<br> }<br> }<br> ao2_iterator_destroy(&i);<br> <br>- return ast_json_ref(json);<br>+ return json;<br> }<br> <br> int app_subscribe_channel(struct stasis_app *app, struct ast_channel *chan)<br> {<br> struct app_forwards *forwards;<br>- SCOPED_AO2LOCK(lock, app->forwards);<br>- int res;<br> <br> if (!app) {<br> return -1;<br> }<br> <br>+ ao2_lock(app->forwards);<br> /* If subscribed to all, don't subscribe again */<br> forwards = ao2_find(app->forwards, CHANNEL_ALL, OBJ_SEARCH_KEY | OBJ_NOLOCK);<br> if (forwards) {<br>+ ao2_unlock(app->forwards);<br> ao2_ref(forwards, -1);<br>+<br> return 0;<br> }<br> <br>@@ -1253,16 +1269,21 @@<br> chan ? ast_channel_uniqueid(chan) : CHANNEL_ALL,<br> OBJ_SEARCH_KEY | OBJ_NOLOCK);<br> if (!forwards) {<br>+ int res;<br>+<br> /* Forwards not found, create one */<br> forwards = forwards_create_channel(app, chan);<br> if (!forwards) {<br>+ ao2_unlock(app->forwards);<br>+<br> return -1;<br> }<br> <br>- res = ao2_link_flags(app->forwards, forwards,<br>- OBJ_NOLOCK);<br>+ res = ao2_link_flags(app->forwards, forwards, OBJ_NOLOCK);<br> if (!res) {<br>+ ao2_unlock(app->forwards);<br> ao2_ref(forwards, -1);<br>+<br> return -1;<br> }<br> }<br>@@ -1273,7 +1294,9 @@<br> forwards->interested,<br> app->name);<br> <br>+ ao2_unlock(app->forwards);<br> ao2_ref(forwards, -1);<br>+<br> return 0;<br> }<br> <br>@@ -1284,8 +1307,7 @@<br> <br> static int unsubscribe(struct stasis_app *app, const char *kind, const char *id, int terminate)<br> {<br>- RAII_VAR(struct app_forwards *, forwards, NULL, ao2_cleanup);<br>- SCOPED_AO2LOCK(lock, app->forwards);<br>+ struct app_forwards *forwards;<br> <br> if (!id) {<br> if (!strcmp(kind, "bridge")) {<br>@@ -1300,8 +1322,10 @@<br> }<br> }<br> <br>+ ao2_lock(app->forwards);<br> forwards = ao2_find(app->forwards, id, OBJ_SEARCH_KEY | OBJ_NOLOCK);<br> if (!forwards) {<br>+ ao2_unlock(app->forwards);<br> ast_debug(3, "App '%s' not subscribed to %s '%s'\n", app->name, kind, id);<br> return -1;<br> }<br>@@ -1320,6 +1344,8 @@<br> messaging_app_unsubscribe_endpoint(app->name, id);<br> }<br> }<br>+ ao2_unlock(app->forwards);<br>+ ao2_ref(forwards, -1);<br> <br> return 0;<br> }<br>@@ -1344,12 +1370,14 @@<br> <br> int app_is_subscribed_channel_id(struct stasis_app *app, const char *channel_id)<br> {<br>- RAII_VAR(struct app_forwards *, forwards, NULL, ao2_cleanup);<br>+ struct app_forwards *forwards;<br> <br> if (ast_strlen_zero(channel_id)) {<br> channel_id = CHANNEL_ALL;<br> }<br> forwards = ao2_find(app->forwards, channel_id, OBJ_SEARCH_KEY);<br>+ ao2_cleanup(forwards);<br>+<br> return forwards != NULL;<br> }<br> <br>@@ -1369,28 +1397,42 @@<br> int app_subscribe_bridge(struct stasis_app *app, struct ast_bridge *bridge)<br> {<br> struct app_forwards *forwards;<br>- SCOPED_AO2LOCK(lock, app->forwards);<br> <br> if (!app) {<br> return -1;<br> }<br> <br>+ ao2_lock(app->forwards);<br> /* If subscribed to all, don't subscribe again */<br> forwards = ao2_find(app->forwards, BRIDGE_ALL, OBJ_SEARCH_KEY | OBJ_NOLOCK);<br> if (forwards) {<br>+ ao2_unlock(app->forwards);<br> ao2_ref(forwards, -1);<br>+<br> return 0;<br> }<br> <br>- forwards = ao2_find(app->forwards, bridge ? bridge->uniqueid : BRIDGE_ALL,<br>+ forwards = ao2_find(app->forwards,<br>+ bridge ? bridge->uniqueid : BRIDGE_ALL,<br> OBJ_SEARCH_KEY | OBJ_NOLOCK);<br> if (!forwards) {<br>+ int res;<br>+<br> /* Forwards not found, create one */<br> forwards = forwards_create_bridge(app, bridge);<br> if (!forwards) {<br>+ ao2_unlock(app->forwards);<br>+<br> return -1;<br> }<br>- ao2_link_flags(app->forwards, forwards, OBJ_NOLOCK);<br>+<br>+ res = ao2_link_flags(app->forwards, forwards, OBJ_NOLOCK);<br>+ if (!res) {<br>+ ao2_unlock(app->forwards);<br>+ ao2_ref(forwards, -1);<br>+<br>+ return -1;<br>+ }<br> }<br> <br> ++forwards->interested;<br>@@ -1399,7 +1441,9 @@<br> forwards->interested,<br> app->name);<br> <br>+ ao2_unlock(app->forwards);<br> ao2_ref(forwards, -1);<br>+<br> return 0;<br> }<br> <br>@@ -1466,16 +1510,18 @@<br> int app_subscribe_endpoint(struct stasis_app *app, struct ast_endpoint *endpoint)<br> {<br> struct app_forwards *forwards;<br>- SCOPED_AO2LOCK(lock, app->forwards);<br> <br> if (!app) {<br> return -1;<br> }<br> <br>+ ao2_lock(app->forwards);<br> /* If subscribed to all, don't subscribe again */<br> forwards = ao2_find(app->forwards, ENDPOINT_ALL, OBJ_SEARCH_KEY | OBJ_NOLOCK);<br> if (forwards) {<br>+ ao2_unlock(app->forwards);<br> ao2_ref(forwards, -1);<br>+<br> return 0;<br> }<br> <br>@@ -1483,12 +1529,23 @@<br> endpoint ? ast_endpoint_get_id(endpoint) : ENDPOINT_ALL,<br> OBJ_SEARCH_KEY | OBJ_NOLOCK);<br> if (!forwards) {<br>+ int res;<br>+<br> /* Forwards not found, create one */<br> forwards = forwards_create_endpoint(app, endpoint);<br> if (!forwards) {<br>+ ao2_unlock(app->forwards);<br>+<br> return -1;<br> }<br>- ao2_link_flags(app->forwards, forwards, OBJ_NOLOCK);<br>+<br>+ res = ao2_link_flags(app->forwards, forwards, OBJ_NOLOCK);<br>+ if (!res) {<br>+ ao2_unlock(app->forwards);<br>+ ao2_ref(forwards, -1);<br>+<br>+ return -1;<br>+ }<br> <br> /* Subscribe for messages */<br> messaging_app_subscribe_endpoint(app->name, endpoint, &message_received_handler, app);<br>@@ -1500,7 +1557,9 @@<br> forwards->interested,<br> app->name);<br> <br>+ ao2_unlock(app->forwards);<br> ao2_ref(forwards, -1);<br>+<br> return 0;<br> }<br> <br>@@ -1520,12 +1579,14 @@<br> <br> int app_is_subscribed_endpoint_id(struct stasis_app *app, const char *endpoint_id)<br> {<br>- RAII_VAR(struct app_forwards *, forwards, NULL, ao2_cleanup);<br>+ struct app_forwards *forwards;<br> <br> if (ast_strlen_zero(endpoint_id)) {<br> endpoint_id = ENDPOINT_ALL;<br> }<br> forwards = ao2_find(app->forwards, endpoint_id, OBJ_SEARCH_KEY);<br>+ ao2_cleanup(forwards);<br>+<br> return forwards != NULL;<br> }<br> <br>diff --git a/res/stasis/command.c b/res/stasis/command.c<br>index 05ebd7b..83a1a4c 100644<br>--- a/res/stasis/command.c<br>+++ b/res/stasis/command.c<br>@@ -76,21 +76,26 @@<br> <br> void command_complete(struct stasis_app_command *command, int retval)<br> {<br>- SCOPED_MUTEX(lock, &command->lock);<br>-<br>+ ast_mutex_lock(&command->lock);<br> command->is_done = 1;<br> command->retval = retval;<br> ast_cond_signal(&command->condition);<br>+ ast_mutex_unlock(&command->lock);<br> }<br> <br> int command_join(struct stasis_app_command *command)<br> {<br>- SCOPED_MUTEX(lock, &command->lock);<br>+ int ret;<br>+<br>+ ast_mutex_lock(&command->lock);<br> while (!command->is_done) {<br> ast_cond_wait(&command->condition, &command->lock);<br> }<br> <br>- return command->retval;<br>+ ret = command->retval;<br>+ ast_mutex_unlock(&command->lock);<br>+<br>+ return ret;<br> }<br> <br> void command_invoke(struct stasis_app_command *command,<br>diff --git a/res/stasis/control.c b/res/stasis/control.c<br>index 655fc1f..d562877 100644<br>--- a/res/stasis/control.c<br>+++ b/res/stasis/control.c<br>@@ -148,8 +148,9 @@<br> struct stasis_app_control *control,<br> struct app_control_rules *list, struct stasis_app_control_rule *obj)<br> {<br>- SCOPED_AO2LOCK(lock, control->command_queue);<br>+ ao2_lock(control->command_queue);<br> AST_LIST_INSERT_TAIL(list, obj, next);<br>+ ao2_unlock(control->command_queue);<br> }<br> <br> static void app_control_unregister_rule(<br>@@ -157,7 +158,8 @@<br> struct app_control_rules *list, struct stasis_app_control_rule *obj)<br> {<br> struct stasis_app_control_rule *rule;<br>- SCOPED_AO2LOCK(lock, control->command_queue);<br>+<br>+ ao2_lock(control->command_queue);<br> AST_RWLIST_TRAVERSE_SAFE_BEGIN(list, rule, next) {<br> if (rule == obj) {<br> AST_RWLIST_REMOVE_CURRENT(next);<br>@@ -165,6 +167,7 @@<br> }<br> }<br> AST_RWLIST_TRAVERSE_SAFE_END;<br>+ ao2_unlock(control->command_queue);<br> }<br> <br> /*!<br>@@ -508,9 +511,10 @@<br> struct ast_channel *chan, void *data)<br> {<br> struct stasis_app_control_mute_data *mute_data = data;<br>- SCOPED_CHANNELLOCK(lockvar, chan);<br> <br>+ ast_channel_lock(chan);<br> ast_channel_suppress(control->channel, mute_data->direction, mute_data->frametype);<br>+ ast_channel_unlock(chan);<br> <br> return 0;<br> }<br>@@ -535,9 +539,10 @@<br> struct ast_channel *chan, void *data)<br> {<br> struct stasis_app_control_mute_data *mute_data = data;<br>- SCOPED_CHANNELLOCK(lockvar, chan);<br> <br>+ ast_channel_lock(chan);<br> ast_channel_unsuppress(control->channel, mute_data->direction, mute_data->frametype);<br>+ ast_channel_unlock(chan);<br> <br> return 0;<br> }<br>@@ -746,7 +751,7 @@<br> struct ast_channel_snapshot *stasis_app_control_get_snapshot(<br> const struct stasis_app_control *control)<br> {<br>- RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);<br>+ struct stasis_message *msg;<br> struct ast_channel_snapshot *snapshot;<br> <br> msg = stasis_cache_get(ast_channel_cache(), ast_channel_snapshot_type(),<br>@@ -759,6 +764,8 @@<br> ast_assert(snapshot != NULL);<br> <br> ao2_ref(snapshot, +1);<br>+ ao2_ref(msg, -1);<br>+<br> return snapshot;<br> }<br> <br>@@ -767,7 +774,8 @@<br> command_data_destructor_fn data_destructor,<br> app_command_can_exec_cb can_exec_fn)<br> {<br>- RAII_VAR(struct stasis_app_command *, command, NULL, ao2_cleanup);<br>+ int ret;<br>+ struct stasis_app_command *command;<br> <br> if (control == NULL || control->is_done) {<br> /* If exec_command_on_condition fails, it calls the data_destructor.<br>@@ -787,7 +795,10 @@<br> return -1;<br> }<br> <br>- return command_join(command);<br>+ ret = command_join(command);<br>+ ao2_ref(command, -1);<br>+<br>+ return ret;<br> }<br> <br> int stasis_app_send_command(struct stasis_app_control *control,<br>@@ -800,7 +811,7 @@<br> stasis_app_command_cb command_fn, void *data,<br> command_data_destructor_fn data_destructor)<br> {<br>- RAII_VAR(struct stasis_app_command *, command, NULL, ao2_cleanup);<br>+ struct stasis_app_command *command;<br> <br> if (control == NULL || control->is_done) {<br> /* If exec_command fails, it calls the data_destructor. In order to<br>@@ -818,18 +829,24 @@<br> if (!command) {<br> return -1;<br> }<br>+ ao2_ref(command, -1);<br> <br> return 0;<br> }<br> <br> struct ast_bridge *stasis_app_get_bridge(struct stasis_app_control *control)<br> {<br>+ struct ast_bridge *ret;<br>+<br> if (!control) {<br> return NULL;<br>- } else {<br>- SCOPED_AO2LOCK(lock, control);<br>- return control->bridge;<br> }<br>+<br>+ ao2_lock(control);<br>+ ret = control->bridge;<br>+ ao2_unlock(control);<br>+<br>+ return ret;<br> }<br> <br> /*!<br>@@ -970,16 +987,16 @@<br> static int bridge_channel_depart(struct stasis_app_control *control,<br> struct ast_channel *chan, void *data)<br> {<br>- struct ast_bridge_channel *bridge_channel = data;<br>+ struct ast_bridge_channel *bridge_channel;<br> <br>- {<br>- SCOPED_CHANNELLOCK(lock, chan);<br>+ ast_channel_lock(chan);<br>+ bridge_channel = ast_channel_internal_bridge_channel(chan);<br>+ ast_channel_unlock(chan);<br> <br>- if (bridge_channel != ast_channel_internal_bridge_channel(chan)) {<br>- ast_debug(3, "%s: Channel is no longer in departable state\n",<br>- ast_channel_uniqueid(chan));<br>- return -1;<br>- }<br>+ if (bridge_channel != data) {<br>+ ast_debug(3, "%s: Channel is no longer in departable state\n",<br>+ ast_channel_uniqueid(chan));<br>+ return -1;<br> }<br> <br> ast_debug(3, "%s: Channel departing bridge\n",<br>@@ -994,9 +1011,9 @@<br> enum ast_bridge_after_cb_reason reason)<br> {<br> struct stasis_app_control *control = data;<br>- SCOPED_AO2LOCK(lock, control);<br> struct ast_bridge_channel *bridge_channel;<br> <br>+ ao2_lock(control);<br> ast_debug(3, "%s, %s: %s\n",<br> ast_channel_uniqueid(chan), control->bridge ? control->bridge->uniqueid : "unknown",<br> ast_bridge_after_cb_reason_string(reason));<br>@@ -1042,6 +1059,7 @@<br> ast_softhangup_nolock(chan, hangup_flag);<br> ast_channel_unlock(chan);<br> }<br>+ ao2_unlock(control);<br> }<br> <br> static void bridge_after_cb(struct ast_channel *chan, void *data)<br>diff --git a/res/stasis/stasis_bridge.c b/res/stasis/stasis_bridge.c<br>index 7ce675c..d78e59c 100644<br>--- a/res/stasis/stasis_bridge.c<br>+++ b/res/stasis/stasis_bridge.c<br>@@ -250,7 +250,7 @@<br> {<br> if (src->v_table == &bridge_stasis_v_table &&<br> dst->v_table != &bridge_stasis_v_table) {<br>- RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);<br>+ struct stasis_app_control *control;<br> struct ast_channel *chan;<br> <br> chan = bridge_channel->chan;<br>@@ -263,6 +263,7 @@<br> <br> stasis_app_channel_set_stasis_end_published(chan);<br> app_send_end_msg(control_app(control), chan);<br>+ ao2_ref(control, -1);<br> }<br> <br> return -1;<br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/7831">change 7831</a>. To unsubscribe, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/7831"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I4ce67120583a446babf9adeec678b71d37fcd9e5 </div>
<div style="display:none"> Gerrit-Change-Number: 7831 </div>
<div style="display:none"> Gerrit-PatchSet: 5 </div>
<div style="display:none"> Gerrit-Owner: Corey Farrell <git@cfware.com> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins2 </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Richard Mudgett <rmudgett@digium.com> </div>