[svn-commits] russell: branch russell/messaging r311292 - /team/russell/messaging/main/
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Thu Mar 17 17:10:40 CDT 2011
Author: russell
Date: Thu Mar 17 17:10:35 2011
New Revision: 311292
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=311292
Log:
Use a new mechanism for ensuring that message techs are unload safe.
This is now handled in the same way as format attribute interfaces in format.c.
Modified:
team/russell/messaging/main/message.c
Modified: team/russell/messaging/main/message.c
URL: http://svnview.digium.com/svn/asterisk/team/russell/messaging/main/message.c?view=diff&rev=311292&r1=311291&r2=311292
==============================================================================
--- team/russell/messaging/main/message.c (original)
+++ team/russell/messaging/main/message.c Thu Mar 17 17:10:35 2011
@@ -97,16 +97,16 @@
<variable name="MESSAGE_SEND_STATUS">
<para>This is the time from dialing a channel until when it is disconnected.</para>
<value name="INVALID_PROTOCOL">
- <para>No handler for the technology part of the URI was found.</para>
+ No handler for the technology part of the URI was found.
</value>
<value name="INVALID_URI">
- <para>The protocol handler reported that the URI was not valid.</para>
+ The protocol handler reported that the URI was not valid.
</value>
<value name="SUCCESS">
- <para>Successfully passed on to the protocol handler, but delivery has not necessarily been guaranteed.</para>
+ Successfully passed on to the protocol handler, but delivery has not necessarily been guaranteed.
</value>
<value name="FAILURE">
- <para>The protocol handler reported that it was unabled to deliver the message for some reason.</para>
+ The protocol handler reported that it was unabled to deliver the message for some reason.
</value>
</variable>
</variablelist>
@@ -128,6 +128,13 @@
struct ast_msg_tech_holder {
const struct ast_msg_tech *tech;
+ /*!
+ * \brief A rwlock for this object
+ *
+ * a read/write lock must be used to protect the wrapper instead
+ * of the ao2 lock. A rdlock must be held to read tech_holder->tech.
+ */
+ ast_rwlock_t tech_lock;
};
static struct ao2_container *msg_techs;
@@ -621,31 +628,34 @@
static int msg_tech_hash(const void *obj, const int flags)
{
- const struct ast_msg_tech_holder *tech_holder = obj;
-
- return ast_str_case_hash(tech_holder->tech->name);
+ struct ast_msg_tech_holder *tech_holder = (struct ast_msg_tech_holder *) obj;
+ int res = 0;
+
+ ast_rwlock_rdlock(&tech_holder->tech_lock);
+ if (tech_holder->tech) {
+ res = ast_str_case_hash(tech_holder->tech->name);
+ }
+ ast_rwlock_unlock(&tech_holder->tech_lock);
+
+ return res;
}
static int msg_tech_cmp(void *obj, void *arg, int flags)
{
- const struct ast_msg_tech_holder *tech_holder = obj;
+ struct ast_msg_tech_holder *tech_holder = obj;
const struct ast_msg_tech_holder *tech_holder2 = arg;
-
- return strcasecmp(tech_holder->tech->name, tech_holder2->tech->name) ? 0 : CMP_MATCH | CMP_STOP;
-}
-
-static int msg_tech_cmp_locked(void *obj, void *arg, int flags)
-{
- int res;
- struct ast_msg_tech_holder *tech_holder = obj;
-
- res = msg_tech_cmp(obj, arg, flags);
-
- if (res == (CMP_MATCH | CMP_STOP)) {
- ao2_lock(tech_holder);
- }
-
- return res;
+ int res = 1;
+
+ ast_rwlock_rdlock(&tech_holder->tech_lock);
+ /*
+ * tech_holder2 is a temporary fake tech_holder.
+ */
+ if (tech_holder->tech) {
+ res = strcasecmp(tech_holder->tech->name, tech_holder2->tech->name) ? 0 : CMP_MATCH | CMP_STOP;
+ }
+ ast_rwlock_unlock(&tech_holder->tech_lock);
+
+ return res ? 0 : CMP_MATCH | CMP_STOP;
}
/*!
@@ -659,7 +669,7 @@
char *tech_name;
struct ast_msg_tech_holder *tech_holder = NULL;
char *parse;
- int res;
+ int res = -1;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(to);
AST_APP_ARG(from);
@@ -704,8 +714,7 @@
.tech = &tmp_msg_tech,
};
- tech_holder = ao2_callback(msg_techs, OBJ_POINTER,
- msg_tech_cmp_locked, &tmp_tech_holder);
+ tech_holder = ao2_find(msg_techs, &tmp_tech_holder, OBJ_POINTER);
}
if (!tech_holder) {
@@ -720,14 +729,17 @@
* that they could change.
*/
ao2_lock(msg);
- res = tech_holder->tech->msg_send(msg, args.to, args.from);
+ ast_rwlock_rdlock(&tech_holder->tech_lock);
+ if (tech_holder->tech) {
+ res = tech_holder->tech->msg_send(msg, args.to, args.from);
+ }
+ ast_rwlock_unlock(&tech_holder->tech_lock);
ao2_unlock(msg);
pbx_builtin_setvar_helper(chan, "MESSAGE_SEND_STATUS", res ? "FAILURE" : "SUCCESS");
exit_cleanup:
if (tech_holder) {
- ao2_unlock(tech_holder);
ao2_ref(tech_holder, -1);
tech_holder = NULL;
}
@@ -755,6 +767,7 @@
return -1;
}
+ ast_rwlock_init(&tech_holder->tech_lock);
tech_holder->tech = tech;
ao2_link(msg_techs, tech_holder);
@@ -781,15 +794,9 @@
return -1;
}
- /*
- * The code that sends messages using a message technology ensures that it
- * locks the tech_holder before it returns a reference to it from the
- * container. By just grabbing and releasing the lock here, we ensure that
- * we wait until any currently running message send code finishes before
- * we proceed with unregistration.
- */
- ao2_lock(tech_holder);
- ao2_unlock(tech_holder);
+ ast_rwlock_wrlock(&tech_holder->tech_lock);
+ tech_holder->tech = NULL;
+ ast_rwlock_unlock(&tech_holder->tech_lock);
ao2_ref(tech_holder, -1);
tech_holder = NULL;
More information about the svn-commits
mailing list