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>
When espeak returns EE_BUFFER_FULL we should just wait a bit before
retrying. Also, we don't want to lose the current entry. We however want
to wake up as soon as possible on stop request.
This permits --pid-file to be specified.
The getopt_long option was looking for a lowercase p,
and the pid-file option used an uppercase P.
This meant that pid-file was never settable.
This allows to make sure to reach the maximum volume permitted by the
hardware. This makes the default volume (5) set ALSA volume to 80%, like
the default ALSA scripts do.
This is not enabled by default, since users will probably want to use a
mixer to fine-tune their volume. But for e.g. installation images, this
allows to spare the use of a mixer and just use the speakup volume
control.
When the Linux console is e.g. switched to a graphical VT, the kernel
emits \x01P to notify that it is not able to read the screen any more,
and the software synthesis can thus release the audio card, for other
screen readers to take over.
This implements it by adding a paused_espeak variable that tracks
whether we have suspended espeak. When more text comes, we can simply
reinitialize espeak.
This fixes#10.