signal: wake all condition-variable waiters on shutdown

On SIGINT/SIGTERM, the signal thread only set should_run to 0 and
relied on a wake-up chain to propagate the shutdown: the self-pipe
wakes the softsynth thread out of select(), which on exit signals
runner_awake to wake the espeak thread.

That chain breaks whenever the softsynth thread is not sitting in
select() but waiting on stop_acknowledged in request_espeak_stop():
nobody ever signals that condition variable on shutdown, so the thread
never re-evaluates should_run and the process never exits.

Broadcast all three condition variables after clearing should_run, so
that every parked thread re-checks its predicate, whichever wait it is
blocked in.

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:
Alexander Epaneshnikov 2026-06-11 11:05:56 +03:00 committed by Samuel Thibault
commit 2b959e874e

View file

@ -58,6 +58,14 @@ void *signal_thread(void *arg)
case SIGTERM: case SIGTERM:
pthread_mutex_lock(&queue_guard); pthread_mutex_lock(&queue_guard);
should_run = 0; should_run = 0;
/* Wake up any thread waiting on a condition variable so
* that it notices the shutdown request: the softsynth
* thread may be waiting for a stop acknowledgement, and
* the espeak thread may be waiting for work or throttling
* before a retry. */
pthread_cond_broadcast(&runner_awake);
pthread_cond_broadcast(&wake_stop);
pthread_cond_broadcast(&stop_acknowledged);
pthread_mutex_unlock(&queue_guard); pthread_mutex_unlock(&queue_guard);
break; break;
default: default: