From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1HZ0sJ-0000yz-7A for qemu-devel@nongnu.org; Wed, 04 Apr 2007 04:29:51 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1HZ0sF-0000yf-Gr for qemu-devel@nongnu.org; Wed, 04 Apr 2007 04:29:50 -0400 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1HZ0sF-0000yc-9u for qemu-devel@nongnu.org; Wed, 04 Apr 2007 04:29:47 -0400 Received: from wx-out-0506.google.com ([66.249.82.229]) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1HZ0oy-0007AK-I9 for qemu-devel@nongnu.org; Wed, 04 Apr 2007 04:26:25 -0400 Received: by wx-out-0506.google.com with SMTP id i30so206775wxd for ; Wed, 04 Apr 2007 01:26:16 -0700 (PDT) Message-ID: Date: Wed, 4 Apr 2007 10:26:15 +0200 From: "andrzej zaborowski" Sender: balrogg@gmail.com In-Reply-To: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Content-Disposition: inline References: Subject: [Qemu-devel] Re: SDL audio and AIO hogging each other's signals Reply-To: balrogg@gmail.com, qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: malc Cc: qemu-devel@nongnu.org Hi, thanks for quick response! On 03/04/07, malc 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 + 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