mirror of
https://github.com/linux-speakup/espeakup.git
synced 2026-08-09 09:19:09 +02:00
espeak: do not call espeak_Cancel() while holding queue_guard
When a flush is requested, the espeak thread called stop_speech() -> espeak_Cancel() with queue_guard held. espeak_Cancel() waits for espeak-ng's internal say thread to acknowledge the cancellation, and that thread can be blocked indefinitely inside a blocking ALSA call (snd_pcm_writei/snd_pcm_drain on a wedged device, as seen with EBUSY errors). In that case queue_guard was held forever, which in turn: - blocked the signal thread on pthread_mutex_lock(), so SIGINT/SIGTERM appeared to be ignored and only SIGKILL could end the process; - left the softsynth thread stuck in request_espeak_stop(), so /dev/softsynth was no longer drained, speakup's kernel buffer filled up, and console output (e.g. dmesg) stalled. Release queue_guard around the espeak_Cancel() call. This is safe because the only queue producer, the softsynth thread, is blocked waiting for stop_acknowledged for as long as stop_requested is set, so the queue cannot be mutated concurrently. Helps: https://github.com/linux-speakup/espeakup/issues/45 Helps: https://github.com/linux-speakup/espeakup/issues/62 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
dc1f1b9efa
commit
d1f7e2384b
1 changed files with 9 additions and 0 deletions
|
|
@ -492,7 +492,16 @@ void *espeak_thread(void *arg)
|
|||
|
||||
if (stop_requested) {
|
||||
current = NULL;
|
||||
/* Call into espeak with queue_guard released: espeak_Cancel
|
||||
* can take time, or even block indefinitely when the audio
|
||||
* output is wedged, and holding the lock here would prevent
|
||||
* the other threads from ever making progress again. The
|
||||
* queue cannot change concurrently: the only producer (the
|
||||
* softsynth thread) is blocked waiting for stop_acknowledged
|
||||
* as long as stop_requested is set. */
|
||||
pthread_mutex_unlock(&queue_guard);
|
||||
stop_speech();
|
||||
pthread_mutex_lock(&queue_guard);
|
||||
synth_queue_clear();
|
||||
stop_requested = 0;
|
||||
pthread_cond_signal(&stop_acknowledged);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue