mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-11-09 21:22:39 -05:00
hosted/pcm/alsa: Use alternate signal stack for the async callback.
Signals are by default executed on the user stack, i.e. the stack of the currently active thread. This has two problems: 1) The stack size of the current stack is likely insufficient (unless using sigaltstack threads) because our stack sizes are normally below MINSIGSTKSIZE which is needed to deliver a signal. 2) Some of our asm code does nasty tricks with the stack pointer. When a signal comes in during this bad things can happen, e.g. random memory being overwritten or simply a crash. Using a well defined stack fixes this. This is comparable with the separate irq stack on native targets.
This commit is contained in:
parent
109084d5cb
commit
34b0311d0e
1 changed files with 31 additions and 0 deletions
|
|
@ -27,6 +27,11 @@
|
||||||
* This driver uses the so-called unsafe async callback method and hardcoded device
|
* 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.
|
* 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
|
* TODO: Rewrite this to do it properly with multithreading
|
||||||
*
|
*
|
||||||
* Alternatively, a version using polling in a tick task is provided. While
|
* 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
|
#ifdef USE_ASYNC_CALLBACK
|
||||||
static snd_async_handler_t *ahandler;
|
static snd_async_handler_t *ahandler;
|
||||||
static pthread_mutex_t pcm_mtx;
|
static pthread_mutex_t pcm_mtx;
|
||||||
|
static char signal_stack[SIGSTKSZ];
|
||||||
#else
|
#else
|
||||||
static int recursion;
|
static int recursion;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -271,12 +277,37 @@ static int async_rw(snd_pcm_t *handle)
|
||||||
short *samples;
|
short *samples;
|
||||||
|
|
||||||
#ifdef USE_ASYNC_CALLBACK
|
#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);
|
err = snd_async_add_pcm_handler(&ahandler, handle, async_callback, NULL);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
{
|
{
|
||||||
DEBUGF("Unable to register async handler: %s\n", snd_strerror(err));
|
DEBUGF("Unable to register async handler: %s\n", snd_strerror(err));
|
||||||
return 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
|
#endif
|
||||||
|
|
||||||
/* fill buffer with silence to initiate playback without noisy click */
|
/* fill buffer with silence to initiate playback without noisy click */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue