Merged revisions 206706 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4 ................ r206706 | rmudgett | 2009-07-15 15:44:55 -0500 (Wed, 15 Jul 2009) | 26 lines Merged revision 206700 from https://origsvn.digium.com/svn/asterisk/be/branches/C.2-... .......... Fixed chan_misdn crash because mISDNuser library is not thread safe. With Asterisk the mISDNuser library is driven by two threads concurrently: 1. channels/misdn/isdn_lib.c::manager_event_handler() 2. channels/misdn/isdn_lib.c::misdn_lib_isdn_event_catcher() Calls into the library are done concurrently and recursively from isdn_lib.c. Both threads can fiddle with the master/child layer3_proc_t lists. One thread may traverse the list when the other interrupts it and then removes the list element which the first thread was currently handling. This is exactly what caused the crash. About 60 calls were needed to a Gigaset CX475 before it occurred once. This patch adds locking when calling into the mISDNuser library. This also fixes some cb_log calls with wrong port parameter. JIRA ABE-1913 Patches: misdn-locking.patch (Modified with mostly cosmetic changes) .......... ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@206707 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
parent
3402f34e9b
commit
e9e753d6f3
2 changed files with 38 additions and 11 deletions
|
@ -884,9 +884,10 @@ static int misdn_lib_get_l2_down(struct misdn_stack *stack)
|
||||||
/* L2 */
|
/* L2 */
|
||||||
dmsg = create_l2msg(DL_RELEASE| REQUEST, 0, 0);
|
dmsg = create_l2msg(DL_RELEASE| REQUEST, 0, 0);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&stack->nstlock);
|
||||||
if (stack->nst.manager_l3(&stack->nst, dmsg))
|
if (stack->nst.manager_l3(&stack->nst, dmsg))
|
||||||
free_msg(dmsg);
|
free_msg(dmsg);
|
||||||
|
pthread_mutex_unlock(&stack->nstlock);
|
||||||
} else {
|
} else {
|
||||||
iframe_t act;
|
iframe_t act;
|
||||||
|
|
||||||
|
@ -925,9 +926,10 @@ int misdn_lib_get_l2_up(struct misdn_stack *stack)
|
||||||
/* L2 */
|
/* L2 */
|
||||||
dmsg = create_l2msg(DL_ESTABLISH | REQUEST, 0, 0);
|
dmsg = create_l2msg(DL_ESTABLISH | REQUEST, 0, 0);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&stack->nstlock);
|
||||||
if (stack->nst.manager_l3(&stack->nst, dmsg))
|
if (stack->nst.manager_l3(&stack->nst, dmsg))
|
||||||
free_msg(dmsg);
|
free_msg(dmsg);
|
||||||
|
pthread_mutex_unlock(&stack->nstlock);
|
||||||
} else {
|
} else {
|
||||||
iframe_t act;
|
iframe_t act;
|
||||||
|
|
||||||
|
@ -1427,6 +1429,7 @@ static struct misdn_stack *stack_init(int midev, int port, int ptp)
|
||||||
stack->nst.l2_id = stack->upper_id;
|
stack->nst.l2_id = stack->upper_id;
|
||||||
|
|
||||||
msg_queue_init(&stack->nst.down_queue);
|
msg_queue_init(&stack->nst.down_queue);
|
||||||
|
pthread_mutex_init(&stack->nstlock, NULL);
|
||||||
|
|
||||||
Isdnl2Init(&stack->nst);
|
Isdnl2Init(&stack->nst);
|
||||||
Isdnl3Init(&stack->nst);
|
Isdnl3Init(&stack->nst);
|
||||||
|
@ -1463,6 +1466,7 @@ static void stack_destroy(struct misdn_stack *stack)
|
||||||
if (!stack) return;
|
if (!stack) return;
|
||||||
|
|
||||||
if (stack->nt) {
|
if (stack->nt) {
|
||||||
|
pthread_mutex_destroy(&stack->nstlock);
|
||||||
cleanup_Isdnl2(&stack->nst);
|
cleanup_Isdnl2(&stack->nst);
|
||||||
cleanup_Isdnl3(&stack->nst);
|
cleanup_Isdnl3(&stack->nst);
|
||||||
}
|
}
|
||||||
|
@ -1936,7 +1940,6 @@ static int handle_event_nt(void *dat, void *arg)
|
||||||
struct misdn_stack *stack;
|
struct misdn_stack *stack;
|
||||||
enum event_e event;
|
enum event_e event;
|
||||||
int reject=0;
|
int reject=0;
|
||||||
int port;
|
|
||||||
int l3id;
|
int l3id;
|
||||||
int channel;
|
int channel;
|
||||||
int tmpcause;
|
int tmpcause;
|
||||||
|
@ -1946,7 +1949,13 @@ static int handle_event_nt(void *dat, void *arg)
|
||||||
|
|
||||||
stack = find_stack_by_mgr(mgr);
|
stack = find_stack_by_mgr(mgr);
|
||||||
hh=(mISDNuser_head_t*)msg->data;
|
hh=(mISDNuser_head_t*)msg->data;
|
||||||
port=stack->port;
|
|
||||||
|
/*
|
||||||
|
* When we are called from the mISDNuser lib, the nstlock is held and it
|
||||||
|
* must be held when we return. We unlock here because the lib may be
|
||||||
|
* entered again recursively.
|
||||||
|
*/
|
||||||
|
pthread_mutex_unlock(&stack->nstlock);
|
||||||
|
|
||||||
cb_log(5, stack->port, " --> lib: prim %x dinfo %x\n",hh->prim, hh->dinfo);
|
cb_log(5, stack->port, " --> lib: prim %x dinfo %x\n",hh->prim, hh->dinfo);
|
||||||
switch(hh->prim) {
|
switch(hh->prim) {
|
||||||
|
@ -1994,6 +2003,7 @@ static int handle_event_nt(void *dat, void *arg)
|
||||||
cb_log(4, stack->port, "Bc Not found (after SETUP CONFIRM)\n");
|
cb_log(4, stack->port, "Bc Not found (after SETUP CONFIRM)\n");
|
||||||
}
|
}
|
||||||
free_msg(msg);
|
free_msg(msg);
|
||||||
|
pthread_mutex_lock(&stack->nstlock);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case CC_SETUP | INDICATION:
|
case CC_SETUP | INDICATION:
|
||||||
|
@ -2020,6 +2030,7 @@ static int handle_event_nt(void *dat, void *arg)
|
||||||
cb_log(4, stack->port, "Bc Not found (after REGISTER CONFIRM)\n");
|
cb_log(4, stack->port, "Bc Not found (after REGISTER CONFIRM)\n");
|
||||||
}
|
}
|
||||||
free_msg(msg);
|
free_msg(msg);
|
||||||
|
pthread_mutex_lock(&stack->nstlock);
|
||||||
return 0;
|
return 0;
|
||||||
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
|
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
|
||||||
|
|
||||||
|
@ -2076,6 +2087,7 @@ static int handle_event_nt(void *dat, void *arg)
|
||||||
case CC_SUSPEND|INDICATION:
|
case CC_SUSPEND|INDICATION:
|
||||||
cb_log(4, stack->port, " --> Got Suspend, sending Reject for now\n");
|
cb_log(4, stack->port, " --> Got Suspend, sending Reject for now\n");
|
||||||
dmsg = create_l3msg(CC_SUSPEND_REJECT | REQUEST,MT_SUSPEND_REJECT, hh->dinfo,sizeof(RELEASE_COMPLETE_t), 1);
|
dmsg = create_l3msg(CC_SUSPEND_REJECT | REQUEST,MT_SUSPEND_REJECT, hh->dinfo,sizeof(RELEASE_COMPLETE_t), 1);
|
||||||
|
pthread_mutex_lock(&stack->nstlock);
|
||||||
stack->nst.manager_l3(&stack->nst, dmsg);
|
stack->nst.manager_l3(&stack->nst, dmsg);
|
||||||
free_msg(msg);
|
free_msg(msg);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2097,6 +2109,7 @@ static int handle_event_nt(void *dat, void *arg)
|
||||||
case CC_RELEASE_CR|INDICATION:
|
case CC_RELEASE_CR|INDICATION:
|
||||||
release_cr(stack, hh);
|
release_cr(stack, hh);
|
||||||
free_msg(msg);
|
free_msg(msg);
|
||||||
|
pthread_mutex_lock(&stack->nstlock);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case CC_NEW_CR|INDICATION:
|
case CC_NEW_CR|INDICATION:
|
||||||
|
@ -2107,6 +2120,7 @@ static int handle_event_nt(void *dat, void *arg)
|
||||||
bc = find_bc_by_l3id(stack, hh->dinfo);
|
bc = find_bc_by_l3id(stack, hh->dinfo);
|
||||||
if (!bc) {
|
if (!bc) {
|
||||||
cb_log(0, stack->port, " --> In NEW_CR: didn't found bc ??\n");
|
cb_log(0, stack->port, " --> In NEW_CR: didn't found bc ??\n");
|
||||||
|
pthread_mutex_lock(&stack->nstlock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (((l3id&0xff00)!=0xff00) && ((bc->l3_id&0xff00)==0xff00)) {
|
if (((l3id&0xff00)!=0xff00) && ((bc->l3_id&0xff00)==0xff00)) {
|
||||||
|
@ -2121,6 +2135,7 @@ static int handle_event_nt(void *dat, void *arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
free_msg(msg);
|
free_msg(msg);
|
||||||
|
pthread_mutex_lock(&stack->nstlock);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case DL_ESTABLISH | INDICATION:
|
case DL_ESTABLISH | INDICATION:
|
||||||
|
@ -2145,6 +2160,7 @@ static int handle_event_nt(void *dat, void *arg)
|
||||||
stack->l2upcnt=0;
|
stack->l2upcnt=0;
|
||||||
|
|
||||||
free_msg(msg);
|
free_msg(msg);
|
||||||
|
pthread_mutex_lock(&stack->nstlock);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case DL_RELEASE | INDICATION:
|
case DL_RELEASE | INDICATION:
|
||||||
|
@ -2170,6 +2186,7 @@ static int handle_event_nt(void *dat, void *arg)
|
||||||
|
|
||||||
stack->l2link = 0;
|
stack->l2link = 0;
|
||||||
free_msg(msg);
|
free_msg(msg);
|
||||||
|
pthread_mutex_lock(&stack->nstlock);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -2231,11 +2248,13 @@ static int handle_event_nt(void *dat, void *arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
free_msg(msg);
|
free_msg(msg);
|
||||||
|
pthread_mutex_lock(&stack->nstlock);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ERR_NO_CHANNEL:
|
ERR_NO_CHANNEL:
|
||||||
cb_log(4, stack->port, "Patch from MEIDANIS:Sending RELEASE_COMPLETE %x (No free Chan for you..)\n", hh->dinfo);
|
cb_log(4, stack->port, "Patch from MEIDANIS:Sending RELEASE_COMPLETE %x (No free Chan for you..)\n", hh->dinfo);
|
||||||
dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST, MT_RELEASE_COMPLETE, hh->dinfo, sizeof(RELEASE_COMPLETE_t), 1);
|
dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST, MT_RELEASE_COMPLETE, hh->dinfo, sizeof(RELEASE_COMPLETE_t), 1);
|
||||||
|
pthread_mutex_lock(&stack->nstlock);
|
||||||
stack->nst.manager_l3(&stack->nst, dmsg);
|
stack->nst.manager_l3(&stack->nst, dmsg);
|
||||||
free_msg(msg);
|
free_msg(msg);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2280,7 +2299,9 @@ static int handle_timers(msg_t* msg)
|
||||||
ret = mISDN_write_frame(stack->midev, msg->data, frm->addr,
|
ret = mISDN_write_frame(stack->midev, msg->data, frm->addr,
|
||||||
MGR_TIMER | RESPONSE, 0, 0, NULL, TIMEOUT_1SEC);
|
MGR_TIMER | RESPONSE, 0, 0, NULL, TIMEOUT_1SEC);
|
||||||
test_and_clear_bit(FLG_TIMER_RUNING, (long unsigned int *)&it->Flags);
|
test_and_clear_bit(FLG_TIMER_RUNING, (long unsigned int *)&it->Flags);
|
||||||
|
pthread_mutex_lock(&stack->nstlock);
|
||||||
ret = it->function(it->data);
|
ret = it->function(it->data);
|
||||||
|
pthread_mutex_unlock(&stack->nstlock);
|
||||||
free_msg(msg);
|
free_msg(msg);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -2703,8 +2724,9 @@ static int handle_frm_nt(msg_t *msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pthread_mutex_lock(&stack->nstlock);
|
||||||
if ((err=stack->nst.l1_l2(&stack->nst,msg))) {
|
if ((err=stack->nst.l1_l2(&stack->nst,msg))) {
|
||||||
|
pthread_mutex_unlock(&stack->nstlock);
|
||||||
if (nt_err_cnt > 0 ) {
|
if (nt_err_cnt > 0 ) {
|
||||||
if (nt_err_cnt < 100) {
|
if (nt_err_cnt < 100) {
|
||||||
nt_err_cnt++;
|
nt_err_cnt++;
|
||||||
|
@ -2716,9 +2738,8 @@ static int handle_frm_nt(msg_t *msg)
|
||||||
}
|
}
|
||||||
free_msg(msg);
|
free_msg(msg);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
pthread_mutex_unlock(&stack->nstlock);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2882,8 +2903,10 @@ static int handle_l1(msg_t *msg)
|
||||||
|
|
||||||
if (stack->nt) {
|
if (stack->nt) {
|
||||||
|
|
||||||
|
pthread_mutex_lock(&stack->nstlock);
|
||||||
if (stack->nst.l1_l2(&stack->nst, msg))
|
if (stack->nst.l1_l2(&stack->nst, msg))
|
||||||
free_msg(msg);
|
free_msg(msg);
|
||||||
|
pthread_mutex_unlock(&stack->nstlock);
|
||||||
|
|
||||||
if (stack->ptp)
|
if (stack->ptp)
|
||||||
misdn_lib_get_l2_up(stack);
|
misdn_lib_get_l2_up(stack);
|
||||||
|
@ -2924,8 +2947,10 @@ static int handle_l1(msg_t *msg)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (stack->nt) {
|
if (stack->nt) {
|
||||||
|
pthread_mutex_lock(&stack->nstlock);
|
||||||
if (stack->nst.l1_l2(&stack->nst, msg))
|
if (stack->nst.l1_l2(&stack->nst, msg))
|
||||||
free_msg(msg);
|
free_msg(msg);
|
||||||
|
pthread_mutex_unlock(&stack->nstlock);
|
||||||
} else {
|
} else {
|
||||||
free_msg(msg);
|
free_msg(msg);
|
||||||
}
|
}
|
||||||
|
@ -3014,16 +3039,16 @@ static int handle_mgmt(msg_t *msg)
|
||||||
switch(frm->prim) {
|
switch(frm->prim) {
|
||||||
case MGR_SHORTSTATUS | INDICATION:
|
case MGR_SHORTSTATUS | INDICATION:
|
||||||
case MGR_SHORTSTATUS | CONFIRM:
|
case MGR_SHORTSTATUS | CONFIRM:
|
||||||
cb_log(5, 0, "MGMT: Short status dinfo %x\n",frm->dinfo);
|
cb_log(5, stack->port, "MGMT: Short status dinfo %x\n",frm->dinfo);
|
||||||
|
|
||||||
switch (frm->dinfo) {
|
switch (frm->dinfo) {
|
||||||
case SSTATUS_L1_ACTIVATED:
|
case SSTATUS_L1_ACTIVATED:
|
||||||
cb_log(3, 0, "MGMT: SSTATUS: L1_ACTIVATED \n");
|
cb_log(3, stack->port, "MGMT: SSTATUS: L1_ACTIVATED \n");
|
||||||
stack->l1link=1;
|
stack->l1link=1;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case SSTATUS_L1_DEACTIVATED:
|
case SSTATUS_L1_DEACTIVATED:
|
||||||
cb_log(3, 0, "MGMT: SSTATUS: L1_DEACTIVATED \n");
|
cb_log(3, stack->port, "MGMT: SSTATUS: L1_DEACTIVATED \n");
|
||||||
stack->l1link=0;
|
stack->l1link=0;
|
||||||
#if 0
|
#if 0
|
||||||
clear_l3(stack);
|
clear_l3(stack);
|
||||||
|
@ -4216,9 +4241,10 @@ static void manager_event_handler(void *arg)
|
||||||
|
|
||||||
while ( (msg=msg_dequeue(&stack->downqueue)) ) {
|
while ( (msg=msg_dequeue(&stack->downqueue)) ) {
|
||||||
if (stack->nt ) {
|
if (stack->nt ) {
|
||||||
|
pthread_mutex_lock(&stack->nstlock);
|
||||||
if (stack->nst.manager_l3(&stack->nst, msg))
|
if (stack->nst.manager_l3(&stack->nst, msg))
|
||||||
cb_log(0, stack->port, "Error@ Sending Message in NT-Stack.\n");
|
cb_log(0, stack->port, "Error@ Sending Message in NT-Stack.\n");
|
||||||
|
pthread_mutex_unlock(&stack->nstlock);
|
||||||
} else {
|
} else {
|
||||||
iframe_t *frm = (iframe_t *)msg->data;
|
iframe_t *frm = (iframe_t *)msg->data;
|
||||||
struct misdn_bchannel *bc = find_bc_by_l3id(stack, frm->dinfo);
|
struct misdn_bchannel *bc = find_bc_by_l3id(stack, frm->dinfo);
|
||||||
|
|
|
@ -65,6 +65,7 @@ struct misdn_stack {
|
||||||
/** is first element because &nst equals &mISDNlist **/
|
/** is first element because &nst equals &mISDNlist **/
|
||||||
net_stack_t nst;
|
net_stack_t nst;
|
||||||
manager_t mgr;
|
manager_t mgr;
|
||||||
|
pthread_mutex_t nstlock;
|
||||||
|
|
||||||
/*! \brief D Channel mISDN driver stack ID (Parent stack ID) */
|
/*! \brief D Channel mISDN driver stack ID (Parent stack ID) */
|
||||||
int d_stid;
|
int d_stid;
|
||||||
|
|
Loading…
Reference in a new issue