<p>Corey Farrell has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/7833">View Change</a></p><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, 297 insertions(+), 182 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/33/7833/1</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..52a7072 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>@@ -1587,6 +1612,7 @@<br>        }<br> <br>  app_deactivate(app);<br>+ ao2_ref(app, -1);<br> <br>  /* There's a decent chance that app is ready for cleanup. Go ahead<br>         * and clean up, just in case<br>@@ -1596,19 +1622,21 @@<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_RDLOCK(&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 +1647,7 @@<br>               }<br>     }<br>     AST_RWLIST_TRAVERSE_SAFE_END;<br>+        AST_RWLIST_UNLOCK(&event_sources);<br> }<br> <br> /*!<br>@@ -1637,12 +1666,16 @@<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>+<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,9 @@<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>+       enum stasis_app_subscribe_res res = STASIS_ASR_OK;<br> <br>         if (!app) {<br>           return STASIS_ASR_APP_NOT_FOUND;<br>@@ -1726,32 +1766,34 @@<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> <br>              if (!(event_source = app_event_source_find(uri))) {<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>-                     return res;<br>+          if (handler) {<br>+                       res = handler(app, uri, event_source);<br>                }<br>     }<br> <br>- if (json) {<br>+  if (res == STASIS_ASR_OK && json) {<br>           ast_debug(3, "%s: Successful; setting results\n", app_name);<br>                *json = stasis_app_object_to_json(app);<br>       }<br> <br>- return STASIS_ASR_OK;<br>+        ao2_ref(app, -1);<br>+<br>+ return res;<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 +1803,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 +1907,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 +1923,24 @@<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(blob, "eventname", json_value)) {<br>+                   blob = ast_json_ref(json_variables);<br>+         }<br>     } else {<br>-             ast_json_ref(blob);<br>+          blob = ast_json_pack("{ss}", "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> <br>      for (i = 0; i < sources_count; ++i) {<br>              const char *uri = source_uris[i];<br>@@ -1916,16 +1959,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 +1991,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 +2055,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 5366819..cbeedd7 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>@@ -926,7 +931,7 @@<br> <br> struct stasis_app *app_create(const char *name, stasis_app_cb handler, void *data, enum stasis_app_subscription_model subscription_model)<br> {<br>- RAII_VAR(struct stasis_app *, app, NULL, ao2_cleanup);<br>+       struct stasis_app *app;<br>       size_t size;<br>  int res = 0;<br> <br>@@ -945,17 +950,12 @@<br>        app->forwards = ao2_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_MUTEX,<br>               AO2_CONTAINER_ALLOC_OPT_DUPS_OBJ_REJECT,<br>              forwards_sort, NULL);<br>-        if (!app->forwards) {<br>-             return NULL;<br>- }<br>-<br>  app->topic = stasis_topic_create(name);<br>-   if (!app->topic) {<br>-                return NULL;<br>- }<br>-<br>  app->bridge_router = stasis_message_router_create(ast_bridge_topic_all());<br>-        if (!app->bridge_router) {<br>+<br>+     if (!app->forwards || !app->topic || !app->bridge_router) {<br>+         ao2_ref(app, -1);<br>+<br>          return NULL;<br>  }<br> <br>@@ -972,13 +972,17 @@<br>           bridge_default_handler, app);<br> <br>      if (res != 0) {<br>+              ao2_ref(app, -1);<br>+<br>          return NULL;<br>  }<br>     /* Bridge router holds a reference */<br>-        ao2_ref(app, +1);<br>+    ao2_t_ref(app, +1, "app->bridge_router");<br> <br>     app->router = stasis_message_router_create(app->topic);<br>         if (!app->router) {<br>+               ao2_ref(app, -1);<br>+<br>          return NULL;<br>  }<br> <br>@@ -995,16 +999,17 @@<br>           sub_default_handler, app);<br> <br>         if (res != 0) {<br>+              ao2_ref(app, -1);<br>+<br>          return NULL;<br>  }<br>     /* Router holds a reference */<br>-       ao2_ref(app, +1);<br>+    ao2_t_ref(app, +1, "app->router");<br> <br>    strncpy(app->name, name, size - sizeof(*app));<br>     app->handler = handler;<br>    app->data = ao2_bump(data);<br> <br>-    ao2_ref(app, +1);<br>     return app;<br> }<br> <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 = NULL;<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,40 @@<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>+     ao2_lock(app);<br>+       handler = app->handler;<br>+   if (app->data) {<br>+          ao2_ref(app->data, +1);<br>+           data = app->data;<br>  }<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>+    ao2_ref(data, -1);<br> <br>-        handler(data, app->name, message);<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 +1079,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,6 +1118,7 @@<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>@@ -1111,6 +1130,7 @@<br>           ao2_ref(data, +1);<br>    }<br>     app->data = data;<br>+ ao2_unlock(app);<br> }<br> <br> const char *stasis_app_name(const struct stasis_app *app)<br>@@ -1187,52 +1207,59 @@<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>+     if (!channels || !bridges || !endpoints) {<br>+           ast_json_unref(json);<br>+<br>+             return NULL;<br>+ }<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>+       while ((forwards = ao2_iterator_next(&i))) {<br>+             struct ast_json *id;<br>          int append_res = -1;<br> <br>               id = ast_json_string_create(forwards->id);<br> <br>              switch (forwards->forward_type) {<br>          case FORWARD_CHANNEL:<br>-                        append_res = ast_json_array_append(channels,<br>-                         ast_json_ref(id));<br>+                   append_res = ast_json_array_append(channels, id);<br>                     break;<br>                case FORWARD_BRIDGE:<br>-                 append_res = ast_json_array_append(bridges,<br>-                          ast_json_ref(id));<br>+                   append_res = ast_json_array_append(bridges, id);<br>                      break;<br>                case FORWARD_ENDPOINT:<br>-                       append_res = ast_json_array_append(endpoints,<br>-                                ast_json_ref(id));<br>+                   append_res = ast_json_array_append(endpoints, id);<br>                    break;<br>                }<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>@@ -1287,8 +1314,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,6 +1329,7 @@<br>               }<br>     }<br> <br>+ ao2_lock(app->forwards);<br>   forwards = ao2_find(app->forwards, id, OBJ_SEARCH_KEY | OBJ_NOLOCK);<br>       if (!forwards) {<br>              ast_debug(3, "App '%s' not subscribed to %s '%s'\n", app->name, kind, id);<br>@@ -1323,6 +1350,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 +1376,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,16 +1403,18 @@<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>@@ -1391,10 +1424,13 @@<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>+    ao2_unlock(app->forwards);<br> <br>      ++forwards->interested;<br>    ast_debug(3, "Bridge '%s' is %d interested in %s\n",<br>@@ -1403,6 +1439,7 @@<br>                 app->name);<br> <br>     ao2_ref(forwards, -1);<br>+<br>     return 0;<br> }<br> <br>@@ -1432,25 +1469,15 @@<br> int app_is_subscribed_bridge_id(struct stasis_app *app, const char *bridge_id)<br> {<br>        struct app_forwards *forwards;<br>-       SCOPED_AO2LOCK(lock, app->forwards);<br>-<br>-   forwards = ao2_find(app->forwards, BRIDGE_ALL, OBJ_SEARCH_KEY | OBJ_NOLOCK);<br>-      if (forwards) {<br>-              ao2_ref(forwards, -1);<br>-               return 1;<br>-    }<br> <br>  if (ast_strlen_zero(bridge_id)) {<br>             bridge_id = BRIDGE_ALL;<br>       }<br> <br>- forwards = ao2_find(app->forwards, bridge_id, OBJ_SEARCH_KEY | OBJ_NOLOCK);<br>-       if (forwards) {<br>-              ao2_ref(forwards, -1);<br>-               return 1;<br>-    }<br>+    forwards = ao2_find(app->forwards, bridge_id, OBJ_SEARCH_KEY);<br>+    ao2_cleanup(forwards);<br> <br>-    return 0;<br>+    return forwards != NULL;<br> }<br> <br> static void *bridge_find(const struct stasis_app *app, const char *id)<br>@@ -1475,10 +1502,13 @@<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>@@ -1489,6 +1519,8 @@<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>@@ -1496,6 +1528,7 @@<br>                /* Subscribe for messages */<br>          messaging_app_subscribe_endpoint(app->name, endpoint, &message_received_handler, app);<br>         }<br>+    ao2_unlock(app->forwards);<br> <br>      ++forwards->interested;<br>    ast_debug(3, "Endpoint '%s' is %d interested in %s\n",<br>@@ -1504,6 +1537,7 @@<br>               app->name);<br> <br>     ao2_ref(forwards, -1);<br>+<br>     return 0;<br> }<br> <br>@@ -1523,12 +1557,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..8a2a696 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>+      ao2_lock(chan);<br>+      bridge_channel = ast_channel_internal_bridge_channel(chan);<br>+  ao2_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: newchange </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: 1 </div>
<div style="display:none"> Gerrit-Owner: Corey Farrell <git@cfware.com> </div>