• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Guardmalloc breaks after AudioQueueDispose
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Guardmalloc breaks after AudioQueueDispose


  • Subject: Re: Guardmalloc breaks after AudioQueueDispose
  • From: Bankim Bhavsar <email@hidden>
  • Date: Thu, 07 Apr 2011 12:41:06 -0700

In case someone runs into the double free problem while stopping
AudioQueue. (abort_report_np() in AudioToolbox)

Observed with AudioQueueReset() in step 3, at times the audio queue
won't stop running for as long as 2 seconds.
After hitting time-out of 2 seconds, regardless of whether
kAudioQueueProperty_IsRunning returned running or not
AudioQueueDispose() was invoked.

We removed call to AudioQueueReset(), and observed that audio queue
would stop running within total configured buffer size of 80-120
milliseconds after call to AudioQueueStop(). Ensuring that audio queue
was stopped completely before calling AudioQueueDispose() made the
double free problem go away.

Can this be considered a bug in AudioQueue implementation or incorrect
use of the AudioQueue API?

Thanks,
Bankim.

On Mon, Mar 28, 2011 at 10:53 AM, Bankim Bhavsar
<email@hidden> wrote:
> We are sometimes hitting a double free while calling
> AudioQueueDispose(queue, true).
> This is more likely when short sounds are played continuously.
>
> Mac OS 10.6.7
>
> Here is pseudo-code of the application
>
> 1.) Create output audio queue on main thread and let the callbacks be
> invoked on audio queue's internal thread.
>      AudioQueueNewOutput(
>      &format,
>      SoundAQOutputCB,      // Callback
>      stream, // Client data
>      NULL, // Use CoreAudio's internal thread
>      kCFRunLoopCommonModes,
>      0,
>      &stream->audioQueue);
>
> 2.) Stop the output audio queue asynchronously.
>   AudioQueueStop(stream->audioQueue,
>                                false);              // asynchronous stop
>
> 3.) Since we are playing short sounds and another stream has to be
> started we reset the audio queue and wait for the audio queue
> to stop. However we can't wait for as long as 1 sec as seen in the
> sample code. We currently max out at 200 milliseconds.
>
>   AudioQueueReset(stream->audioQueue);
>
>   Poll for 200 msecs max (by sleep()'ing for 20 msecs) and wait for
> the audio queue to stop using kAudioQueueProperty_IsRunning property.
>   AudioQueueGetProperty(
>   stream->audioQueue,
>   kAudioQueueProperty_IsRunning,
>   &isRunning,
>   &size);
>
>  Dispose queue synchronously
>  AudioQueueDispose(stream->audioQueue, true);
>
>  Sometimes after 35-80 successful attempts, we hit a double free in
> Audio Queue code:
>  Thread 5 Crashed:
>  0 libSystem.B.dylib 0x00007fff800a8e4e __semwait_signal_nocancel + 10
>  1 libSystem.B.dylib 0x00007fff800a8d50 nanosleep$NOCANCEL + 129
>  2 libSystem.B.dylib 0x00007fff801056a2 usleep$NOCANCEL + 57
>  3 libSystem.B.dylib 0x00007fff80124c75 __abort + 113
>  4 libSystem.B.dylib 0x00007fff80124cd9 abort_report_np + 0
>  5 libSystem.B.dylib 0x00007fff8003c6f5 free + 128
>  6 ....audio.toolbox.AudioToolbox 0x00007fff80bfd7c4
>  AQNodeAllocator::~AQNodeAllocator() + 50
>  7 ....audio.toolbox.AudioToolbox 0x00007fff80bfeb59
>  AudioQueueObject::WorkQueue::~WorkQueue() + 49
>  8 ....audio.toolbox.AudioToolbox 0x00007fff80bfa494
>  AudioQueueObject::~AudioQueueObject() + 780
>  9 ....audio.toolbox.AudioToolbox 0x00007fff80c12198 AQServer_DisposeQueue + 63
>  10 ....audio.toolbox.AudioToolbox 0x00007fff80c1556e AudioQueueDispose + 132
>
>
> Help will be appreciated in this regard.
>
> Thanks,
> Bankim.
>
> On Sun, Mar 27, 2011 at 3:44 PM, Bankim Bhavsar
> <email@hidden> wrote:
>> Hi Greg,
>>
>> Did you ever get a response to this question? Did you file a bug with
>> Apple regarding this issue?
>>
>> I'm facing a similar situation wherein playing small sounds repeatedly
>> (after about 35 or 80 times)
>> sometimes causes AudioQueueDispose(queue, true) to double free a pointer
>> in AQNodeAllocator::~AQNodeAllocator().
>>
>> Thread 5 Crashed:
>> 0 libSystem.B.dylib 0x00007fff800a8e4e __semwait_signal_nocancel + 10
>> 1 libSystem.B.dylib 0x00007fff800a8d50 nanosleep$NOCANCEL + 129
>> 2 libSystem.B.dylib 0x00007fff801056a2 usleep$NOCANCEL + 57
>> 3 libSystem.B.dylib 0x00007fff80124c75 __abort + 113
>> 4 libSystem.B.dylib 0x00007fff80124cd9 abort_report_np + 0
>> 5 libSystem.B.dylib 0x00007fff8003c6f5 free + 128
>> 6 ....audio.toolbox.AudioToolbox 0x00007fff80bfd7c4
>> AQNodeAllocator::~AQNodeAllocator() + 50
>> 7 ....audio.toolbox.AudioToolbox 0x00007fff80bfeb59
>> AudioQueueObject::WorkQueue::~WorkQueue() + 49
>> 8 ....audio.toolbox.AudioToolbox 0x00007fff80bfa494
>> AudioQueueObject::~AudioQueueObject() + 780
>> 9 ....audio.toolbox.AudioToolbox 0x00007fff80c12198 AQServer_DisposeQueue + 63
>> 10 ....audio.toolbox.AudioToolbox 0x00007fff80c1556e AudioQueueDispose + 132
>>
>> I'll try enabling guard malloc next...
>>
>> Thanks,
>> Bankim.
>>
>> On Mon, Dec 8, 2008 at 9:06 AM, Greg Wilson <email@hidden> wrote:
>>> I've been trying to convert the simple sound play routines in my app to use
>>> the AudioQueue routines. I play either very short sounds or loop some longer
>>> ones (and both types can be playing at once). Following the
>>> aqplay/AudioQueueTest example,  I got my sounds to play but eventually my
>>> program crashes, sometimes after playing 20+ sounds successfully.
>>>
>>> After much headbanging I went back to the example code (aqplay from
>>> Developer/Examples/Core Audio/SimpleSDK/AudioQueueTools)) and altered it to
>>> play the same sound a number of times.  Basically, when GuardMalloc is
>>> enabled, the program gets a EXC_BAD_ACCESS in a different thread than my
>>> program loop in a routine OSAtomicOr32Barrier called by AQConverterManager
>>> when attempting to play the sound the second time.
>>>
>>> If GuardMalloc is not enabled, things can go to go normally for a while,
>>> sometimes even playing 20+ sounds successfully. However, it will usually
>>> crashes after playing the sound a number of times. Occasionally I get a note
>>>  to  set a breakpoint in malloc_error_break. When set, the debugger breaks
>>> during a calls to either AudioQueueDispose or to AduioQueueStart.
>>>
>>>
>>> (here's what I did to alter the aqplay program. It doesn't require much to
>>> alter the program to play sounds one after the other. Basically, I created a
>>> routine (playFile )and moved the AudioQueue functions which played the file
>>> into this routine from the main routine
>>>
>>> void playFile (const char *fpath, Float32 volume )
>>>
>>> {
>>>        //copy everything from here
>>>        printf ("Playing file: %s\n", fpath);
>>>
>>>        try {
>>>                AQTestInfo myInfo;
>>>
>>> ... etc
>>>        // down to here
>>>        catch (CAXException e) {
>>>                char buf[256];
>>>                fprintf(stderr, "Error: %s (%s)\n", e.mOperation,
>>> e.FormatError(buf));
>>>        }
>>>
>>> }
>>>
>>> then this code was replaced in the main routine to call it repeatedly:
>>>
>>> int main (int argc, const char * argv[])
>>> {
>>>        const char *fpath = NULL;
>>>        Float32 volume = 1;
>>>
>>>        for (int i = 1; i < argc; ++i) {
>>>                const char *arg = argv[i];
>>>                if (arg[0] != '-') {
>>>                        if (fpath != NULL) {
>>>                                fprintf(stderr, "may only specify one file to
>>> play\n");
>>>                                usage();
>>>                        }
>>>                        fpath = arg;
>>>                } else {
>>>                        arg += 1;
>>>                        if (arg[0] == 'v' || !strcmp(arg, "-volume")) {
>>>                                if (++i == argc)
>>>                                        MissingArgument();
>>>                                arg = argv[i];
>>>                                sscanf(arg, "%f", &volume);
>>>                        } else if (arg[0] == 'h' || !strcmp(arg, "-help")) {
>>>                                usage();
>>>                        } else {
>>>                                fprintf(stderr, "unknown argument: %s\n\n",
>>> arg - 1);
>>>                                usage();
>>>                        }
>>>                }
>>>        }
>>>
>>>        if (fpath == NULL)
>>>                usage();
>>>
>>>        // these few lines replace the code moved to playfile, and play the
>>> same sound file over and over
>>>        for (int j = 1; j< 200; ++j)
>>>                playFile(fpath, volume);
>>>
>>>
>>>    return 0;
>>> }
>>>
>>> I put Submarine.aiff from System/Library/Sounds into the build directory and
>>> added  Submarine.aiff as an argument to the active executable.
>>>
>>> I later changed the lines
>>>                CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1, false);
>>>                XThrowIfError(AudioQueueDispose(myInfo.mQueue, true),
>>> "AudioQueueDispose(true) failed");
>>>                XThrowIfError(AudioFileClose(myInfo.mAudioFile),
>>> "AudioQueueDispose(false) failed");
>>>                delete [] myInfo.mPacketDescs;
>>>
>>> to
>>>                do {
>>>                        CFRunLoopRunInMode(kCFRunLoopDefaultMode, 5, false);
>>>                } while (gIsRunning);
>>>
>>>                XThrowIfError(AudioQueueDispose(myInfo.mQueue, true),
>>> "AudioQueueDispose(true) failed");
>>>                XThrowIfError(AudioFileClose(myInfo.mAudioFile),
>>> "AudioQueueDispose(false) failed");
>>>                delete [] myInfo.mPacketDescs;
>>>                gIsRunning = 1;
>>>
>>> and set the gIsRunningFlag to 1 when it was defined, ie
>>> static UInt32 gIsRunning = 1;
>>>
>>> (The program sets this to 0 when the queue calls it's listener proc,
>>> although it didn't use it )
>>>
>>> This serves to ensure AudioStopQueue has really stopped the queue and it
>>> even gives it an extra bit of time to finish anything it might be doing.
>>> However, that didn't change anything. With GuardMalloc enabled, the program
>>> still broke during the second attempt at playing the sound (and after about
>>> 12 successful plays with GuardMalloc off)
>>>
>>> Can anyone help me? I've replicated this on a PPC G5, an original intel iMac
>>> and a intel macbook all running 10.5.5 using xcode 3.1.1.
>>>
>>>
>>> _______________________________________________
>>> Do not post admin requests to the list. They will be ignored.
>>> Coreaudio-api mailing list      (email@hidden)
>>> Help/Unsubscribe/Update your Subscription:
>>>
>>> This email sent to email@hidden
>>>
>>
>
 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:

This email sent to email@hidden

  • Prev by Date: AU Threading Question
  • Next by Date: Re: Reverb algorithm/source for RemoteIO on iPhone
  • Previous by thread: Re: AU Threading Question
  • Next by thread: what should a host do when ....
  • Index(es):
    • Date
    • Thread