[Asterisk-bsd] How to implement locking in channel drivers
Soren Telfer
soren.telfer at gmail.com
Mon Aug 8 10:24:17 CDT 2005
Use your own mutex, and don't rely on the channel mutex for anything.
Did you get an answer on the dev list?
Asterisk has a way of making things disappear. For instance, why oh
why does asterisk do this?
if (chan->tech_pvt) {
ast_log(LOG_WARNING, "Channel '%s' may not have been
hung up pr\operly\n", chan->name);
free(chan->tech_pvt);
}
On 8/2/05, Hans Petter Selasky <hselasky at c2i.net> wrote:
> Hi,
>
> I sent this mail to "asterisk-dev at lists.digium.com", but it hasn't passed the
> moderator yet, so I'm posting it here meanwhile:
>
>
> I'm writing a channel driver for asterisk and I have hit some problems.
>
> 1)
>
> I want to have my channel driver under a BSD license, but I see no
> ASTERISK_BSD_KEY. Must all code be under GPL or is BSD also allowed?
>
>
> 2)
>
> From what I see, "ast_hangup()" does not perform any race condition checks. It
> is not impossible that two threads can call this function in parallell, and
> succeed until "ast_channel_free()" is called, which handle races.
>
> I'm trying to stay straight with mutexes, and as you probably know, locking
> order cannot be reversed. That will lead to a deadlock. My code looks like
> this:
>
> struct call_desc { // private structure associated with ast_channel
>
> struct ast_channel *p_ch;
> astmutex_t *p_mtx;
>
> } *cd;
>
>
> When I setup things I do like this:
>
> cd->p_ch = ast_channel_alloc(1);
>
> cd->p_mtx = &cd->p_ch->lock;
>
>
> Then I have a routine to lookup call descriptors by number:
>
> /*---------------------------------------------------------------------------*
> * cd_by_cid - find call descriptor by ID;
> *
> * NOTE: returns with "cd->mtx" locked
> *---------------------------------------------------------------------------*/
> static struct call_desc *
> cd_by_cid(u_int32_t cid)
> {
> struct call_desc *cd;
>
> ast_mutex_lock(&cd_global_lock);
> cd = cd_root;
> ast_mutex_unlock(&cd_global_lock);
>
> while(cd)
> {
> ast_mutex_lock(&cd->p_mtx);
>
> if((cd->cid != 0) &&
> (((cd->cid ^ cid) & 0xFFFF) == 0))
> {
> break;
> }
>
> ast_mutex_unlock(&cd->p_mtx);
> cd = cd->next;
> }
> return cd;
> }
>
>
> The problem is that asterisk destroys it's channel mutex when "ast_hangup()"
> is called. But this mutex must be present even after that the channel has
> been freed, hence code might be about to lock that mutex and access struct
> ast_channel. Also struct ast_channel must be static and not freed by free().
>
> One solution is to use a single lock for all of my channel driver, but that is
> not what I want. Does anyone have a solution for this problem?
>
> Another solution is to allocate my own mutex, but then I end up with locking
> order reversal between my mutex and "p_ch->lock".
>
> --HPS
> _______________________________________________
> Asterisk-BSD mailing list
> Asterisk-BSD at lists.digium.com
> http://lists.digium.com/mailman/listinfo/asterisk-bsd
>
More information about the Asterisk-BSD
mailing list