<p>Joshua Colp <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/7833">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 9a06a52..5067ca7 100644<br>--- a/res/res_stasis.c<br>+++ b/res/res_stasis.c<br>@@ -500,7 +500,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>@@ -509,7 +510,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>@@ -601,23 +605,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>@@ -626,6 +634,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>@@ -833,25 +842,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>@@ -930,9 +944,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>@@ -957,8 +971,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>@@ -968,13 +985,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>@@ -991,9 +1009,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>@@ -1003,10 +1021,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>@@ -1449,7 +1470,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>@@ -1465,6 +1486,8 @@<br> return -1;<br> }<br> app_send(app, message);<br>+ ao2_ref(app, -1);<br>+<br> return 0;<br> }<br> <br>@@ -1499,7 +1522,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>@@ -1512,12 +1535,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>@@ -1529,24 +1552,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>@@ -1554,6 +1578,7 @@<br> */<br> cleanup();<br> ao2_unlock(apps_registry);<br>+ ao2_ref(app, -1);<br> return 0;<br> }<br> <br>@@ -1569,7 +1594,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>@@ -1592,23 +1617,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>@@ -1619,6 +1648,7 @@<br> }<br> }<br> AST_RWLIST_TRAVERSE_SAFE_END;<br>+ AST_RWLIST_UNLOCK(&event_sources);<br> }<br> <br> /*!<br>@@ -1637,12 +1667,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>@@ -1657,9 +1690,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>@@ -1676,13 +1712,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>@@ -1717,8 +1756,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>@@ -1726,16 +1767,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>@@ -1745,13 +1791,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>@@ -1761,6 +1809,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>@@ -1863,12 +1913,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>@@ -1881,23 +1929,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>@@ -1916,16 +1970,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>@@ -1942,6 +2002,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>@@ -2005,9 +2066,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 91b0065..ccb93bc 100644<br>--- a/res/stasis/app.c<br>+++ b/res/stasis/app.c<br>@@ -114,20 +114,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>@@ -338,7 +337,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>@@ -355,6 +354,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>@@ -557,11 +557,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>@@ -589,7 +590,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>@@ -613,6 +614,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>@@ -634,7 +636,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>@@ -651,6 +652,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>@@ -659,6 +662,7 @@<br> }<br> <br> app_send(app, json);<br>+ ast_json_unref(json);<br> }<br> <br> if (!new_snapshot && old_snapshot) {<br>@@ -686,7 +690,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>@@ -720,6 +724,7 @@<br> <br> if (json) {<br> app_send(app, json);<br>+ ast_json_unref(json);<br> }<br> <br> if (!new_snapshot && old_snapshot) {<br>@@ -1022,7 +1027,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>@@ -1031,37 +1036,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>@@ -1071,27 +1075,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>@@ -1100,17 +1114,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>@@ -1187,68 +1199,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>@@ -1256,16 +1272,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>@@ -1276,7 +1297,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>@@ -1287,8 +1310,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>@@ -1303,8 +1325,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>@@ -1323,6 +1347,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>@@ -1347,12 +1373,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>@@ -1372,28 +1400,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>@@ -1402,7 +1444,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>@@ -1459,16 +1503,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>@@ -1476,12 +1522,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>@@ -1493,7 +1550,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>@@ -1513,12 +1572,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 534e434..024f02b 100644<br>--- a/res/stasis/command.c<br>+++ b/res/stasis/command.c<br>@@ -78,21 +78,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 7e8ea91..df97931 100644<br>--- a/res/stasis/control.c<br>+++ b/res/stasis/control.c<br>@@ -137,8 +137,9 @@<br> const 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>@@ -146,7 +147,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>@@ -154,6 +156,7 @@<br> }<br> }<br> AST_RWLIST_TRAVERSE_SAFE_END;<br>+ ao2_unlock(control->command_queue);<br> }<br> <br> /*!<br>@@ -580,9 +583,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>@@ -607,9 +611,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>@@ -818,7 +823,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>@@ -831,6 +836,8 @@<br> ast_assert(snapshot != NULL);<br> <br> ao2_ref(snapshot, +1);<br>+ ao2_ref(msg, -1);<br>+<br> return snapshot;<br> }<br> <br>@@ -839,7 +846,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>@@ -859,7 +867,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>@@ -872,7 +883,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>@@ -890,33 +901,39 @@<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> 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>@@ -931,9 +948,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>@@ -979,6 +996,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 81b35e3..701cbae 100644<br>--- a/res/stasis/stasis_bridge.c<br>+++ b/res/stasis/stasis_bridge.c<br>@@ -252,7 +252,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>@@ -265,6 +265,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/7833">change 7833</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/7833"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 13 </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: 7833 </div>
<div style="display:none"> Gerrit-PatchSet: 4 </div>
<div style="display:none"> Gerrit-Owner: Corey Farrell <git@cfware.com> </div>
<div style="display:none"> Gerrit-Reviewer: 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>