freetdm: Fix segfault due to race condition in ftmod_r2 processing loop
Added SIGEVENT_PROCEED for ftmod_r2 Cleaned up code in main loop to use channel iterators
This commit is contained in:
parent
1b7e4a0df9
commit
87d5826142
|
@ -1303,6 +1303,10 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Notifying progress\n");
|
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Notifying progress\n");
|
||||||
|
sigev.event_id = FTDM_SIGEVENT_PROCEED;
|
||||||
|
if (ftdm_span_send_signal(ftdmchan->span, &sigev) != FTDM_SUCCESS) {
|
||||||
|
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
|
||||||
|
}
|
||||||
sigev.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA;
|
sigev.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA;
|
||||||
if (ftdm_span_send_signal(ftdmchan->span, &sigev) != FTDM_SUCCESS) {
|
if (ftdm_span_send_signal(ftdmchan->span, &sigev) != FTDM_SUCCESS) {
|
||||||
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
|
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
|
||||||
|
@ -1417,6 +1421,7 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
|
||||||
int res, ms;
|
int res, ms;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
struct timeval start, end;
|
struct timeval start, end;
|
||||||
|
ftdm_iterator_t *chaniter = NULL;
|
||||||
short *poll_events = ftdm_malloc(sizeof(short) * span->chan_count);
|
short *poll_events = ftdm_malloc(sizeof(short) * span->chan_count);
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
@ -1436,6 +1441,7 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
|
||||||
|
|
||||||
memset(&start, 0, sizeof(start));
|
memset(&start, 0, sizeof(start));
|
||||||
memset(&end, 0, sizeof(end));
|
memset(&end, 0, sizeof(end));
|
||||||
|
chaniter = ftdm_span_get_chan_iterator(span, NULL);
|
||||||
while (ftdm_running() && ftdm_test_flag(r2data, FTDM_R2_RUNNING)) {
|
while (ftdm_running() && ftdm_test_flag(r2data, FTDM_R2_RUNNING)) {
|
||||||
res = gettimeofday(&end, NULL);
|
res = gettimeofday(&end, NULL);
|
||||||
if (start.tv_sec) {
|
if (start.tv_sec) {
|
||||||
|
@ -1457,9 +1463,10 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
|
||||||
/* figure out what event to poll each channel for. POLLPRI when the channel is down,
|
/* figure out what event to poll each channel for. POLLPRI when the channel is down,
|
||||||
* POLLPRI|POLLIN|POLLOUT otherwise */
|
* POLLPRI|POLLIN|POLLOUT otherwise */
|
||||||
memset(poll_events, 0, sizeof(short)*span->chan_count);
|
memset(poll_events, 0, sizeof(short)*span->chan_count);
|
||||||
for (i = 0; i < span->chan_count; i++) {
|
chaniter = ftdm_span_get_chan_iterator(span, chaniter);
|
||||||
r2chan = R2CALL(span->channels[(i+1)])->r2chan;
|
for (i = 0; chaniter; chaniter = ftdm_iterator_next(chaniter), i++) {
|
||||||
ftdmchan = openr2_chan_get_client_data(r2chan);
|
ftdmchan = ftdm_iterator_current(chaniter);
|
||||||
|
r2chan = R2CALL(ftdmchan)->r2chan;
|
||||||
poll_events[i] = POLLPRI;
|
poll_events[i] = POLLPRI;
|
||||||
if (openr2_chan_get_read_enabled(r2chan)) {
|
if (openr2_chan_get_read_enabled(r2chan)) {
|
||||||
poll_events[i] |= POLLIN;
|
poll_events[i] |= POLLIN;
|
||||||
|
@ -1481,29 +1488,36 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX
|
/* this main loop takes care of MF and CAS signaling during call setup and tear down
|
||||||
* when ftdm_span_poll_event() returns FTDM_SUCCESS, means there are events pending on the span.
|
* for every single channel in the span, do not perform blocking operations here! */
|
||||||
* is it possible to know on which channels those events are pending, without traversing the span?
|
chaniter = ftdm_span_get_chan_iterator(span, chaniter);
|
||||||
* XXX */
|
for ( ; chaniter; chaniter = ftdm_iterator_next(chaniter)) {
|
||||||
for (i = 1; i <= span->chan_count; i++) {
|
ftdmchan = ftdm_iterator_current(chaniter);
|
||||||
r2chan = R2CALL(span->channels[i])->r2chan;
|
|
||||||
ftdmchan = openr2_chan_get_client_data(r2chan);
|
|
||||||
r2call = R2CALL(ftdmchan);
|
|
||||||
|
|
||||||
ftdm_mutex_lock(ftdmchan->mutex);
|
ftdm_mutex_lock(ftdmchan->mutex);
|
||||||
|
|
||||||
|
r2chan = R2CALL(span->channels[i])->r2chan;
|
||||||
|
|
||||||
ftdm_r2_state_advance_all(ftdmchan);
|
ftdm_r2_state_advance_all(ftdmchan);
|
||||||
|
|
||||||
openr2_chan_process_signaling(r2chan);
|
openr2_chan_process_signaling(r2chan);
|
||||||
|
|
||||||
ftdm_r2_state_advance_all(ftdmchan);
|
ftdm_r2_state_advance_all(ftdmchan);
|
||||||
|
|
||||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||||
}
|
}
|
||||||
|
/* deliver the actual events to the user now without any channel locking */
|
||||||
ftdm_span_trigger_signals(span);
|
ftdm_span_trigger_signals(span);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 1; i <= span->chan_count; i++) {
|
chaniter = ftdm_span_get_chan_iterator(span, chaniter);
|
||||||
r2chan = R2CALL(span->channels[i])->r2chan;
|
for ( ; chaniter; chaniter = ftdm_iterator_next(chaniter)) {
|
||||||
|
ftdmchan = ftdm_iterator_current(chaniter);
|
||||||
|
r2chan = R2CALL(ftdmchan)->r2chan;
|
||||||
openr2_chan_set_blocked(r2chan);
|
openr2_chan_set_blocked(r2chan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ftdm_iterator_free(chaniter);
|
||||||
ftdm_safe_free(poll_events);
|
ftdm_safe_free(poll_events);
|
||||||
|
|
||||||
ftdm_clear_flag(r2data, FTDM_R2_RUNNING);
|
ftdm_clear_flag(r2data, FTDM_R2_RUNNING);
|
||||||
|
|
Loading…
Reference in New Issue