Skip to content

Commit 0ab5dea

Browse files
chan_console: Fix deadlock caused by unclean thread exit.
To terminate a console channel, stop_stream causes pthread_cancel to make stream_monitor exit. However, commit 5b8fea9 added locking to this function which results in deadlock due to the stream_monitor thread being killed while it's holding the pvt lock. To resolve this, a flag is now set and read to indicate abort, so the use of pthread_cancel and pthread_kill can be avoided altogether. Resolves: #308
1 parent 67fd66e commit 0ab5dea

File tree

1 file changed

+10
-6
lines changed

1 file changed

+10
-6
lines changed

channels/chan_console.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ static struct console_pvt {
152152
struct ast_frame fr;
153153
/*! Running = 1, Not running = 0 */
154154
unsigned int streamstate:1;
155+
/*! Abort stream processing? */
156+
unsigned int abort:1;
155157
/*! On-hook = 0, Off-hook = 1 */
156158
unsigned int hookstate:1;
157159
/*! Unmuted = 0, Muted = 1 */
@@ -275,18 +277,19 @@ static void *stream_monitor(void *data)
275277
};
276278

277279
for (;;) {
278-
pthread_testcancel();
279280
console_pvt_lock(pvt);
280281
res = Pa_ReadStream(pvt->stream, buf, sizeof(buf) / sizeof(int16_t));
281282
console_pvt_unlock(pvt);
282-
pthread_testcancel();
283283

284-
if (!pvt->owner) {
284+
if (!pvt->owner || pvt->abort) {
285285
return NULL;
286286
}
287287

288-
if (res == paNoError)
288+
if (res == paNoError) {
289289
ast_queue_frame(pvt->owner, &f);
290+
} else {
291+
ast_log(LOG_WARNING, "Console ReadStream failed: %s\n", Pa_GetErrorText(res));
292+
}
290293
}
291294

292295
return NULL;
@@ -401,8 +404,9 @@ static int stop_stream(struct console_pvt *pvt)
401404
if (!pvt->streamstate || pvt->thread == AST_PTHREADT_NULL)
402405
return 0;
403406

404-
pthread_cancel(pvt->thread);
405-
pthread_kill(pvt->thread, SIGURG);
407+
pvt->abort = 1;
408+
/* Wait for pvt->thread to exit cleanly, to avoid killing it while it's holding a lock. */
409+
pthread_kill(pvt->thread, SIGURG); /* Wake it up if needed, but don't cancel it */
406410
pthread_join(pvt->thread, NULL);
407411

408412
console_pvt_lock(pvt);

0 commit comments

Comments
 (0)