From b101c87d1e592d5cf2a018e8739f70b0bf4fd0ef Mon Sep 17 00:00:00 2001 From: Alexander Epaneshnikov Date: Thu, 11 Jun 2026 11:08:16 +0300 Subject: [PATCH] espeak: do not call espeak functions after a failed reinitialization When resuming from CMD_PAUSE, queue_process_entry ignored the result of reinitialize_espeak: if espeak_Initialize failed, paused_espeak remained set, yet the entry was processed anyway, calling espeak_Synth & co on a terminated engine. Combined with the busy-retry loop, this produced an endless stream of failing calls against a dead engine. Make reinitialize_espeak report failure, and when espeak is unavailable, leave the entry queued and back off before trying to reinitialize again. Co-Authored-By: Claude --- src/espeak.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/espeak.c b/src/espeak.c index f6b4d1e..a77fcf3 100644 --- a/src/espeak.c +++ b/src/espeak.c @@ -321,7 +321,7 @@ static void synth_queue_clear() } } -static void reinitialize_espeak(struct synth_t *s) +static int reinitialize_espeak(struct synth_t *s) { int rate; @@ -329,7 +329,7 @@ static void reinitialize_espeak(struct synth_t *s) rate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, NULL, 0); if (rate < 0) { fprintf(stderr, "Unable to initialize espeak.\n"); - return; + return -1; } espeak_SetSynthCallback(callback); @@ -342,7 +342,7 @@ static void reinitialize_espeak(struct synth_t *s) espeak_SetParameter(espeakVOLUME, (s->volume + 1) * volumeMultiplier, 0); espeak_SetParameter(espeakCAPITALS, 0, 0); paused_espeak = 0; - return; + return 0; } /* Wait for up to a second before retrying an entry which could not be @@ -372,7 +372,15 @@ static void queue_process_entry(struct synth_t *s) pthread_mutex_unlock(&queue_guard); if (current->cmd != CMD_PAUSE && paused_espeak) { - reinitialize_espeak(s); + if (reinitialize_espeak(s) < 0) { + /* Espeak is unavailable, so the entry cannot be processed. + * Calling espeak functions on a terminated engine would + * just fail (or worse). Leave the entry queued and retry + * after a small pause. */ + pthread_mutex_lock(&queue_guard); + espeak_wait_retry(); + return; + } } switch (current->cmd) {