[asterisk-dev] Locking, coding guidelines addition
Stephen Davies
stephen.l.davies at gmail.com
Fri Jul 4 13:17:13 CDT 2008
2008/7/4 Russell Bryant <russell at digium.com>:
>
> ----- "Stephen Davies" <stephen.l.davies at gmail.com> wrote:
> > I think the discussion reveals that the magic trylock while loop looks
> > neato but doesn't really solve the problem. Tzafrir and Luigi pointed
> > out some flaws.
>
> It doesn't just look neato. It does actually work, except for when the
> recursive property of the locks are used.
>
OK point taken. Ish. Because interestingly I've fixed a deadlock recently
in chan_local that was to do with the fact that a mutex had two outstanding
locks. So when the magic trylock look in local_queue_frame tried to do its
thing, the underlying lock never got released and you STILL end up with a
deadlock (or livelock)
Here was the fix for that:
Index: channels/chan_local.c
===================================================================
--- channels/chan_local.c (revision 105553)
+++ channels/chan_local.c (working copy)
@@ -153,6 +153,7 @@
static int local_queue_frame(struct local_pvt *p, int isoutbound, struct
ast_frame *f, struct ast_channel *us)
{
struct ast_channel *other = NULL;
+ int doublelock = 0;
/* Recalculate outbound channel */
other = isoutbound ? p->owner : p->chan;
@@ -175,11 +176,23 @@
/* Ensure that we have both channels locked */
while (other && ast_channel_trylock(other)) {
ast_mutex_unlock(&p->lock);
- if (us)
+ if (us) {
ast_channel_unlock(us);
+ /* SLD: In some circumstances with generators running on the local channel
it is possible
+ for there to be two locks on the us channel. Essential to drop them
both to avoid a
+ deadlock */
+ if (!ast_channel_unlock(us)) {
+ doublelock = 1;
+ if (option_debug > 2)
+ ast_log(LOG_VERBOSE, "local_queue_frame had to unlock \"us\" twice\n");
+ }
+ }
usleep(1);
- if (us)
+ if (us) {
ast_channel_lock(us);
+ if (doublelock)
+ ast_mutex_lock(us);
+ }
ast_mutex_lock(&p->lock);
other = isoutbound ? p->owner : p->chan;
}
Thinking back, there was a point in the past when the use of recursive locks
was started. Or maybe I'm remembering wrong and it was a point at which
they became mandatory.
Anyway - I guess that the magic trylock look technique was used way back
before the recursive mutexes came in.
<goes to look at 1.0.9...>
Yep - I can see it in there; though often without the while.
But even 1.0.9 Asterisk required recursive mutexes - so it was before
then...
Steve
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.digium.com/pipermail/asterisk-dev/attachments/20080704/ef8f8a59/attachment.htm
More information about the asterisk-dev
mailing list