[Asterisk-Dev] how to get requested channel if p->call not NULL

Abhishek Tiwari abhitiwari at gmail.com
Fri Apr 29 07:25:36 MST 2005


Hi,
   I am facing a problem that my pbx side sometimes doesnt respond to
the DISCONNECT sent to it and while requesting that channel the
available() function in chan_zap.c returns 0 since p->call is not
NULL. Repetitive attempts for the same fail. I tried to do a fix so
that I send RELEASE on that channel, do a destroycall and set p->call
to NULL. This alone does not work in my case since the next time
available() returns 1 and SETUP is sent on this channel, but
pri_fixup_channel moves this call to some other channel, which is not
acceptable to me. So in addition I also do a reset on that channel in
available(), so that the channel is available when it is used. Works
fine and does the job, for some time.

This is the code that i added in available() (attached is the patch
for CVS HEAD chan_zap.c)
======================================================
if (!p->owner) {
        /* Trust PRI */
#ifdef ZAPATA_PRI
        if (p->pri) {
                               /****** my code starts here *******/
                if(p->call)
                {
                        ast_log(LOG_WARNING, "************ Call not
null for %d channel on span %d, Foring Restart
************\n",PRI_CHANNEL(channelmatch), p->pri->span);

                        ast_mutex_lock(&p->lock);
                        if (p->pri && p->pri->pri) {
                                if (!pri_grab(p, p->pri)) {
                                        // 26 as casue to send
release, though call state would do the same
                                        pri_hangup(p->pri->pri, p->call, 26);
                                        pri_destroycall(p->pri->pri, p->call);
                                        pri_rel(p->pri);
                                } else
                                        ast_log(LOG_WARNING, "Failed
to grab PRI!\n");
                        } else
                                ast_log(LOG_WARNING, "The PRI Call
have not been destroyed\n");

                        p->call = NULL;

                        pri_reset(p->pri->pri, PVT_TO_CHANNEL(p));
                        p->resetting = 1;
                        ast_mutex_unlock(&p->lock);
                        return 0;
                }
                               /****** my code ends here *******/

                if (p->resetting || p->call)
                        return 0;
                else
                        return 1;
        }

======================================================

    This frees up the channels as wanted, the next time it is
requested, but the problem is that after 3-4 hours of smooth running
asterisk crashes. all the crashes have been in or around
pri_disconnect_timeout or pri_release_timeout (depeding whether I use
-1 or 26 in pri_hangup). Mark had pointed out that this is because of
double freeing occuring, though I could not find out where. Will
taking p->lock earlier help ? when ? will decreasing the t305 and t308
timers instead of this fix be of any help ? (havent tried that yet,
will try tomorrow)

    Below is the "bt full" of the thread for the last crash. I have
been trying this for some time now, but nothing works for long. Any
solutions ?

sorry, cant get the bt full, m/c remote and inaccessible now, though
here's "bt" from the screen
==================================================
#0  0xb6f6776b in q921_transmit_iframe (pri=0x825dfd8, buf=0xb6ebd704,
len=9, cr=1) at q921.c:385
385             for (f=pri->txqueue; f; f = f->next) prev = f;
(gdb) bt
#0  0xb6f6776b in q921_transmit_iframe (pri=0x825dfd8, buf=0xb6ebd704,
len=9, cr=1) at q921.c:385
#1  0xb6f6dbaf in q931_xmit (pri=0x825dfd8, h=0xb6ebd704, len=9, cr=1)
at q931.c:2476
#2  0xb6f6deb4 in send_message (pri=0x825dfd8, c=0x8244ef8,
msgtype=77, ies=0xb6f7bd78) at q931.c:2537
#3  0xb6f6e7bd in q931_release (pri=0x825dfd8, c=0x8244ef8, cause=16)
at q931.c:2800
#4  0xb6f6e587 in pri_disconnect_timeout (data=0x8244ef8) at q931.c:2751
#5  0xb6f6907f in __pri_schedule_run (pri=0x81e9d18, tv=0xb6ebdbbc) at
prisched.c:97
#6  0xb6f690e4 in pri_schedule_run (pri=0x81e9d18) at prisched.c:109
#7  0xb6fb425b in pri_dchannel (vpri=0xb6fcff50) at chan_zap.c:7691
#8  0xb7589e51 in pthread_start_thread () from /lib/i686/libpthread.so.0
#9  0xb747cd8a in clone () from /lib/i686/libc.so.6
(gdb) p pri
$1 = (struct pri *) 0x825dfd8
(gdb) p pri->txqueue
$2 = (struct q921_frame *) 0xb7
=========================================================

regards,
Abhishek

Drishti-Soft Solutions Pvt Ltd
http://www.drishti-soft.com
-------------- next part --------------
--- chan_zap.c	2005-04-22 13:39:47.000000000 +0530
+++ chan_zap.c.modified	2005-04-29 19:40:04.462463001 +0530
@@ -6867,6 +6867,30 @@
 		/* Trust PRI */
 #ifdef ZAPATA_PRI
 		if (p->pri) {
+
+			if(p->call)
+			{
+				ast_log(LOG_WARNING, "************ Call not null for %d channel on span %d, Forcing Restart ************\n",PRI_CHANNEL(channelmatch), p->pri->span);
+
+				ast_mutex_lock(&p->lock);
+				if (p->pri && p->pri->pri) {
+					if (!pri_grab(p, p->pri)) {
+						pri_hangup(p->pri->pri, p->call, -1);
+						pri_destroycall(p->pri->pri, p->call);
+						pri_rel(p->pri);
+					} else
+						ast_log(LOG_WARNING, "Failed to grab PRI!\n");
+				} else
+					ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
+
+				p->call = NULL;
+
+				pri_reset(p->pri->pri, PVT_TO_CHANNEL(p));
+				p->resetting = 1;
+				ast_mutex_unlock(&p->lock);
+				return 0;
+			}
+
 			if (p->resetting || p->call)
 				return 0;
 			else


More information about the asterisk-dev mailing list