[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