summaryrefslogtreecommitdiffstats
path: root/firmware/target/hosted/pcm-alsa.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/hosted/pcm-alsa.c')
-rw-r--r--firmware/target/hosted/pcm-alsa.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/firmware/target/hosted/pcm-alsa.c b/firmware/target/hosted/pcm-alsa.c
index 7daf485f18..02cb34ea5b 100644
--- a/firmware/target/hosted/pcm-alsa.c
+++ b/firmware/target/hosted/pcm-alsa.c
@@ -27,6 +27,11 @@
* This driver uses the so-called unsafe async callback method and hardcoded device
* names. It fails when the audio device is busy by other apps.
*
+ * To make the async callback safer, an alternative stack is installed, since
+ * it's run from a signal hanlder (which otherwise uses the user stack). If
+ * tick tasks are run from a signal handler too, please install
+ * an alternative stack for it too.
+ *
* TODO: Rewrite this to do it properly with multithreading
*
* Alternatively, a version using polling in a tick task is provided. While
@@ -76,6 +81,7 @@ static size_t pcm_size = 0;
#ifdef USE_ASYNC_CALLBACK
static snd_async_handler_t *ahandler;
static pthread_mutex_t pcm_mtx;
+static char signal_stack[SIGSTKSZ];
#else
static int recursion;
#endif
@@ -271,12 +277,37 @@ static int async_rw(snd_pcm_t *handle)
short *samples;
#ifdef USE_ASYNC_CALLBACK
+ /* assign alternative stack for the signal handlers */
+ stack_t ss = {
+ .ss_sp = signal_stack,
+ .ss_size = sizeof(signal_stack),
+ .ss_flags = 0
+ };
+ struct sigaction sa;
+
+ err = sigaltstack(&ss, NULL);
+ if (err < 0)
+ {
+ DEBUGF("Unable to install alternative signal stack: %s", strerror(err));
+ return err;
+ }
+
err = snd_async_add_pcm_handler(&ahandler, handle, async_callback, NULL);
if (err < 0)
{
DEBUGF("Unable to register async handler: %s\n", snd_strerror(err));
return err;
}
+
+ /* only modify the stack the handler runs on */
+ sigaction(SIGIO, NULL, &sa);
+ sa.sa_flags |= SA_ONSTACK;
+ err = sigaction(SIGIO, &sa, NULL);
+ if (err < 0)
+ {
+ DEBUGF("Unable to install alternative signal stack: %s", strerror(err));
+ return err;
+ }
#endif
/* fill buffer with silence to initiate playback without noisy click */