qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "andrzej zaborowski" <balrog@zabor.org>
To: malc <av1474@comtv.ru>
Cc: qemu-devel@nongnu.org
Subject: [Qemu-devel] Re: SDL audio and AIO hogging each other's signals
Date: Wed, 4 Apr 2007 10:26:15 +0200	[thread overview]
Message-ID: <fb249edb0704040126u64e051f6j5c4c76abebf9eb18@mail.gmail.com> (raw)
In-Reply-To: <Pine.LNX.4.64.0704040143540.5785@linmac.oyster.ru>

Hi, thanks for quick response!

On 03/04/07, malc <av1474@comtv.ru> wrote:
> On Tue, 3 Apr 2007, andrzej zaborowski wrote:
>
> > Hi,
> > with QEMU_AUDIO_DRV set to "sdl" and booting from CD-ROM with AIO on
> > a Linux host and with SDL 1.2.11, qemu locks up in sigwait() (the main
> > thread) and SDL_SemWait() (the audio thread) as soon as music is
> > playing and CD-ROM is being read at the same time. It appears that
> > audio/sdlaudio.c:sdl_callback is called by SDL when it shouldn't be
> > called, and block-raw.c is trying to flush the AIO operations, so it
> > would seem that the SIGUSR2 which is intended to wake up the sigwait
> > is instead captured by SDL and SDL tries to be smart and calls
> > sdl_callback. sdl_callback has a sanity check but this check is
> > *after* SDL_SemWait() so it is not triggered. The strange thing is
> > that using a different signal (tried SIGUSR1 and SIGPOLL) for AIO
> > doesn't help. Does SDL catch all signals?
> > I could be totally wrong because I don't know SDLAudio at all.
>
> If my reading of SDLs sources are correct then it shouldn't be trying
> to catch any signals when explicitly instructed not to do so (which is
> done in sdl.c (SDL_INIT_NOPARACHUTE flag)).
>
> >
> > Any ideas about the exact reason why this is happening and how to fix it?
> >
>
> Given the semantics of signal delivery in POSIX what you describe
> might happen, what is a little surprising is that SDL (btw. which
> backend SDL uses?) doesn't complain.

It should be using ALSA.

>
> Here's my theory: signal will be delivered to the arbitrary thread
> that happens to not block it, for whatever reason, the thread SDL
> created to do audio processing is picked up, which leads to some
> system call being interrupted(eventually) and -1 (errno == EINTR), SDL
> happily continues calling stuff.

Yes, reading the PTHREAD_SIGNAL(3) note, this sounds very likely.

>
> One solution would be to explicitly block everything upon entering
> sdl_callback for the first time. This is ugly and can have any
> consequences one cares to imagine, but that's SDL for you (any
> particular reason why you are using it?)

Not really - just had only OSS and SDL compiled into qemu at this moment.

Yes, the suggested solution works. Unfortunately it's neither pretty
nor correct, because at the time sdl_callback runs, the signal which
was supposed to wake up sigwait() is already lost and I can't find any
way to prevent that - we can add a kill(0, SIGUSR2) but this is even
uglier and again we don't know when sdl_callback is called as a result
of this signal and when legally. (That's also why I didn't put a
"return" after pthread_sigmask().)

diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c
index f2a6896..efeb3c0 100644
--- a/audio/sdlaudio.c
+++ b/audio/sdlaudio.c
@@ -46,6 +46,7 @@ struct SDLAudioState {
     SDL_mutex *mutex;
     SDL_sem *sem;
     int initialized;
+    int threadstart;
 } glob_sdl;
 typedef struct SDLAudioState SDLAudioState;

@@ -197,13 +198,25 @@ static void sdl_close (SDLAudioState *s)
     }
 }

+#ifdef __sun__
+#define _POSIX_PTHREAD_SEMANTICS 1
+#endif
+#include <signal.h>
+
 static void sdl_callback (void *opaque, Uint8 *buf, int len)
 {
     SDLVoiceOut *sdl = opaque;
     SDLAudioState *s = &glob_sdl;
     HWVoiceOut *hw = &sdl->hw;
     int samples = len >> hw->info.shift;
+    sigset_t set;

+    if (s->threadstart) {
+        /* QEMU uses sigwait() so all threads should block signals.  */
+        s->threadstart = 0;
+        sigfillset(&set);
+        pthread_sigmask(SIG_BLOCK, &set, 0);
+    }
     if (s->exit) {
         return;
     }
@@ -313,6 +326,8 @@ static int sdl_init_out (HWVoiceOut *hw, audsettings_t *as)
     audfmt_e effective_fmt;
     audsettings_t obt_as;

+    s->threadstart = 1;
+
     shift <<= as->nchannels == 2;

     req.freq = as->freq;

What POSIX needs is a way to set the default signal mask for new threads :-/
Regards,
Andrzej

  reply	other threads:[~2007-04-04  8:29 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-04-03 21:12 [Qemu-devel] SDL audio and AIO hogging each other's signals andrzej zaborowski
2007-04-03 21:56 ` [Qemu-devel] " malc
2007-04-04  8:26   ` andrzej zaborowski [this message]
2007-04-04 11:49     ` malc
2007-04-04 12:23       ` andrzej zaborowski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=fb249edb0704040126u64e051f6j5c4c76abebf9eb18@mail.gmail.com \
    --to=balrog@zabor.org \
    --cc=av1474@comtv.ru \
    --cc=balrogg@gmail.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).