mirror of
https://github.com/asterisk/asterisk.git
synced 2025-11-07 18:38:02 +00:00
Fix crash in chanspy (bug #5332)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@6768 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -255,8 +255,9 @@ static int spy_generate(struct ast_channel *chan, void *data, int len, int sampl
|
|||||||
short buf0[1280], buf1[1280], buf[1280];
|
short buf0[1280], buf1[1280], buf[1280];
|
||||||
|
|
||||||
if (csth->spy.status == CHANSPY_DONE) {
|
if (csth->spy.status == CHANSPY_DONE) {
|
||||||
|
/* Channel is already gone more than likely */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_mutex_lock(&csth->spy.lock);
|
ast_mutex_lock(&csth->spy.lock);
|
||||||
while((f = csth->spy.queue[0])) {
|
while((f = csth->spy.queue[0])) {
|
||||||
@@ -326,7 +327,6 @@ static int spy_generate(struct ast_channel *chan, void *data, int len, int sampl
|
|||||||
frame.datalen = x * 2;
|
frame.datalen = x * 2;
|
||||||
|
|
||||||
if (ast_write(chan, &frame)) {
|
if (ast_write(chan, &frame)) {
|
||||||
csth->spy.status = CHANSPY_DONE;
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,24 +373,12 @@ static void stop_spying(struct ast_channel *chan, struct ast_channel_spy *spy)
|
|||||||
struct ast_channel_spy *cptr=NULL, *prev=NULL;
|
struct ast_channel_spy *cptr=NULL, *prev=NULL;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
while(ast_mutex_trylock(&chan->lock)) {
|
/* If our status has changed, then the channel we're spying on is gone....
|
||||||
/* if its locked already it's almost surely hanging up and we are too late
|
DON'T TOUCH IT!!! RUN AWAY!!! */
|
||||||
we can safely remove the head pointer if it points at us without needing a lock.
|
if (spy->status != CHANSPY_RUNNING)
|
||||||
since everybody spying will be in the same boat whomever is pointing at the head
|
return;
|
||||||
will surely erase it which is all we really need since it's a linked list of
|
|
||||||
staticly declared structs that belong to each spy.
|
|
||||||
*/
|
|
||||||
if (chan->spiers == spy) {
|
|
||||||
chan->spiers = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
count++;
|
|
||||||
if (count > 10) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sched_yield();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
ast_mutex_lock(&chan->lock);
|
||||||
for(cptr=chan->spiers; cptr; cptr=cptr->next) {
|
for(cptr=chan->spiers; cptr; cptr=cptr->next) {
|
||||||
if (cptr == spy) {
|
if (cptr == spy) {
|
||||||
if (prev) {
|
if (prev) {
|
||||||
|
|||||||
10
channel.c
10
channel.c
@@ -939,22 +939,14 @@ void ast_channel_free(struct ast_channel *chan)
|
|||||||
static void ast_spy_detach(struct ast_channel *chan)
|
static void ast_spy_detach(struct ast_channel *chan)
|
||||||
{
|
{
|
||||||
struct ast_channel_spy *chanspy;
|
struct ast_channel_spy *chanspy;
|
||||||
int to=3000;
|
|
||||||
int sleepms = 100;
|
|
||||||
|
|
||||||
|
/* Marking the spies as done is sufficient. Chanspy or spy users will get the picture. */
|
||||||
for (chanspy = chan->spiers; chanspy; chanspy = chanspy->next) {
|
for (chanspy = chan->spiers; chanspy; chanspy = chanspy->next) {
|
||||||
if (chanspy->status == CHANSPY_RUNNING) {
|
if (chanspy->status == CHANSPY_RUNNING) {
|
||||||
chanspy->status = CHANSPY_DONE;
|
chanspy->status = CHANSPY_DONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* signal all the spys to get lost and allow them time to unhook themselves
|
|
||||||
god help us if they don't......
|
|
||||||
*/
|
|
||||||
while (chan->spiers && to >= 0) {
|
|
||||||
ast_safe_sleep(chan, sleepms);
|
|
||||||
to -= sleepms;
|
|
||||||
}
|
|
||||||
chan->spiers = NULL;
|
chan->spiers = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user