StreamingPlayback crash

HAL9000HAL9000 FRMember

Hello,

I'm making an app to stream audio, it's a radio streaming where user can his channel. So, works perfectly, but when i change the channel, i have anytime a crash but not the same time. (sorry for my english)

This is the report : need help to understand what going on and how fixe it

`Process: RadioScoopiOS [545]
Path: /Users/USER/Library/Application Support/iPhone Simulator/*/RadioScoopiOS.app/RadioScoopiOS
Identifier: RadioScoopiOS
Version: 0
Code Type: X86 (Native)
Parent Process: launchd_sim [517]
Responsible: launchd_sim [517]
User ID: 501

Date/Time: 2014-06-29 09:28:48.512 +0200
OS Version: Mac OS X 10.9.3 (13D65)
Report Version: 11
Anonymous UUID: 34B0E7DD-E5AC-E52F-B9D0-3FA38FCC360B

Crashed Thread: 14

Exception Type: EXC_BAD_ACCESS (SIGABRT)
Exception Codes: KERN_PROTECTION_FAILURE at 0x0000000000000034

VM Regions Near 0x34:
--> __PAGEZERO 0000000000000000-0000000000001000 [ 4K] ---/--- SM=NUL /Users/USER/Library/Application Support/iPhone Simulator/*/RadioScoopiOS.app/RadioScoopiOS
VM_ALLOCATE 0000000000001000-00000000000bd000 [ 752K] ---/--- SM=NUL

Application Specific Information:
iPhone Simulator 463.9.41, iPhone OS 7.1 (iPhone Retina (4-inch)/11D167)

Thread 0:: Dispatch queue: com.apple.main-thread
0 libsystem_kernel.dylib 0x05d82fb6 semaphore_wait_trap + 10
1 libdispatch.dylib 0x059dd81c _dispatch_semaphore_wait_slow + 265
2 libdispatch.dylib 0x059dd70a dispatch_semaphore_wait + 37
3 CFNetwork 0x004ee49d CFURLConnectionSendSynchronousRequest + 408
4 Foundation 0x01aab498 +[NSURLConnection sendSynchronousRequest:returningResponse:error:] + 158
5 Foundation 0x01ae8a02 -[NSData(NSData) initWithContentsOfURL:] + 213
6 Foundation 0x01abdb01 +[NSData(NSData) dataWithContentsOfURL:] + 67
`

Posts

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    Good morning.

    Taking a look at the call stack, the following appears to be happening:

    On the main UI thread, we are pumping messages and get a gesture recognizer. We call performSelector:withObject:withObject to invoke some code, and then end up in NSData(NSData) dataWithContentsOfURL which calls NSURLConnection sendSynchronousRequest:returningResponse:error.

    More interestingly is thread 14. We are in some RadioScoopiOS code and call:

    AudioFileStreamWrapper::ParseBytes
    MP3AudioStream::GeneratePackets
    AudioFileStreamWrapper::CallPacketsProc
    and run into: "??? 0xffffffff"

    Without a small test case that shows the problem, I would suggest looking through your application for all AudioFileStreamWrapper::ParseBytes \ CallPacketsProc calls and have them print out their arguments (or look at them in a debugger) as the application runs. My initial guess is that you are passing some invalid arguments to one of them (or there is a bug in the bindings).

  • HAL9000HAL9000 FRMember

    Hello,

    this is the Xamarin report, I tried to print my parseBytes params method but nothing appending, thanks for your help

    `mono-rt: Stacktrace:

    mono-rt: at <0xffffffff>

    mono-rt: at (wrapper managed-to-native) MonoTouch.AudioToolbox.AudioQueue.memcpy (byte,byte,int)

    mono-rt: at MonoTouch.AudioToolbox.AudioQueue.FillAudioData (intptr,int,intptr,int,int) [0x00016] in /Developer/MonoTouch/Source/maccore/src/AudioToolbox/AudioQueue.cs:472

    2014-07-08 09:37:22.860 RadioScoopiOS[985:70b] http://stream.radioscoop.com/scoop2.mp3
    mono-rt: at StreamingAudio.StreamingPlayback.AudioPacketDecoded (object,MonoTouch.AudioToolbox.PacketReceivedEventArgs) [0x00090] in /Users/[email protected]/Documents/ionWeb_app/RadioScoop/RadioScoop.iOS/Streaming/StreamingPlayback.cs:206

    mono-rt: at MonoTouch.AudioToolbox.AudioFileStream.OnPacketDecoded (int,intptr,MonoTouch.AudioToolbox.AudioStreamPacketDescription[]) [0x0000d] in /Developer/MonoTouch/Source/maccore/src/AudioToolbox/AudioFileStream.cs:190

    mono-rt: at MonoTouch.AudioToolbox.AudioFileStream.InPackets (intptr,int,int,intptr,intptr) [0x0001d] in /Developer/MonoTouch/Source/maccore/src/AudioToolbox/AudioFileStream.cs:182

    mono-rt: at (wrapper native-to-managed) MonoTouch.AudioToolbox.AudioFileStream.InPackets (intptr,int,int,intptr,intptr)

    mono-rt: at <0xffffffff>

    mono-rt: at (wrapper managed-to-native) MonoTouch.AudioToolbox.AudioFileStream.AudioFileStreamParseBytes (intptr,int,intptr,uint)

    mono-rt: at MonoTouch.AudioToolbox.AudioFileStream.ParseBytes (byte[],int,int,bool) [0x00053] in /Developer/MonoTouch/Source/maccore/src/AudioToolbox/AudioFileStream.cs:261

    mono-rt: at StreamingAudio.StreamingPlayback.ParseBytes (byte[],int,bool,bool) [0x0001f] in /Users/[email protected]/Documents/ionWeb_app/RadioScoop/RadioScoop.iOS/Streaming/StreamingPlayback.cs:147

    mono-rt: at RadioScoop.iOS.PlayerViewController.StreamDownloadedHandler (System.IAsyncResult) [0x00090] in /Users/[email protected]/Documents/ionWeb_app/RadioScoop/RadioScoop.iOS/PlayerViewController.cs:610

    mono-rt: at System.Net.SimpleAsyncResult/c__AnonStorey0.<>m__0 (System.Net.SimpleAsyncResult) [0x0000b] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/SimpleAsyncResult.cs:62

    mono-rt: at System.Net.SimpleAsyncResult.DoCallback_internal () [0x0001d] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/SimpleAsyncResult.cs:165

    mono-rt: at System.Net.WebAsyncResult.DoCallback () [0x00000] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/WebAsyncResult.cs:96

    mono-rt: at System.Net.HttpWebRequest.SetResponseData (System.Net.WebConnectionData) [0x00212] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/HttpWebRequest.cs:1503

    mono-rt: at System.Net.WebConnection.ReadDone (System.IAsyncResult) [0x002bc] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/WebConnection.cs:612

    mono-rt: at (wrapper runtime-invoke) .runtime_invoke_void__this___object (object,intptr,intptr,intptr)

    mono-rt:
    Native stacktrace:

    mono-rt:

    Got a SIGSEGV while executing native code. This usually indicates
    a fatal error in the mono runtime or one of the native libraries
    used by your application.
    =================================================================`

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    On the top line of your call stack:

    mono-rt: at MonoTouch.AudioToolbox.AudioQueue.FillAudioData (intptr,int,intptr,int,int) [0x00016] in /Developer/MonoTouch/Source/maccore/src/AudioToolbox/AudioQueue.cs:472

    We are calling this method (From what I can tell):

        public static void FillAudioData (IntPtr audioQueueBuffer, int offset, IntPtr source, int sourceOffset, nint size)
    

    but it appears the arguments are invalid. Please break in a debugger here or otherwise check your arguments, I believe the problem can be found here.

  • HAL9000HAL9000 FRMember

    I print the FillAudioData arguments but the app crash without log. I think my StreamingPlayback configuration are wrong.
    this is my args
    `public OutputAudioQueue OutputQueue;
    // the AudioToolbox decoder
    private AudioFileStream fileStream;
    private int bufferSize = 22050; //128 * 256;
    private List outputBuffers;
    private AudioBuffer currentBuffer;
    // Maximum buffers
    private int maxBufferCount = 1;
    // Keep track of all queued up buffers, so that we know that the playback finished
    private int queuedBufferCount = 0;
    // Current Filestream Position - if we don't keep track we don't know when to push the last uncompleted buffer
    private long currentByteCount = 0;
    //Used to trigger a dump of the last buffer.
    private bool lastPacket;

        public event EventHandler Finished;
        public event Action<OutputAudioQueue> OutputReady;`
    

    and the void
    `///


    /// Saving the decoded Packets to our active Buffer, if the Buffer is full queue it into the OutputQueue
    /// and wait until another buffer gets freed up
    ///

    private void AudioPacketDecoded (object sender, PacketReceivedEventArgs args)
    {
    try {

                foreach (var p in args.PacketDescriptions) {
                    currentByteCount += p.DataByteSize;
    
                    AudioStreamPacketDescription pd = p;
    
                    int left = bufferSize - currentBuffer.CurrentOffset;
                    if (left < pd.DataByteSize) {
                        EnqueueBuffer ();
                        WaitForBuffer ();
                    }
    
                    Console.WriteLine("{0}; {1}; {2}; {3}; {4};", currentBuffer.Buffer, currentBuffer.CurrentOffset, args.InputData, (int)pd.StartOffset, pd.DataByteSize);
    
                    AudioQueue.FillAudioData (currentBuffer.Buffer, currentBuffer.CurrentOffset, args.InputData, (int)pd.StartOffset, pd.DataByteSize);
                    // Set new offset for this packet
                    pd.StartOffset = currentBuffer.CurrentOffset;
                    // Add the packet to our Buffer
                    currentBuffer.PacketDescriptions.Add (pd);
                    // Add the Size so that we know how much is in the buffer
                    currentBuffer.CurrentOffset += pd.DataByteSize;
    
                }
    
                if ((fileStream != null && currentByteCount == fileStream.DataByteCount) || lastPacket)
                    EnqueueBuffer ();
    
            } catch (Exception ex) {
                Console.WriteLine ("FillAudioData : {0}", ex.Message);
            }
        }`
    
  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    I'm going to take a look at your example today and will get back to you.

    As a side note, I've run into the problem of a print too close to a crash not showing up on the console as well. One way I've gotten around it is to change the print into write to a file. As long as you close the file before the crash, you should be able to read the lines post crash.

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    A few comments:

    • I'm not sure it would ever happen, but i don't think this code would handle getting a single packet bigger than bufferSize. You would queue an empty buffer, and blit your packet (which is too big) and crash.
    • A non-trivial chunk of logic isn't in your post. I'm assuming somewhere you reset the current buffer offset and like (EnqueueBuffer \ WaitForBuffer).
    • Is there a reason you can't just put a breakpoint on AudioQueue.FillAudioData and see in a debugger the arguments?
    • If not, try changing that CWL to writing to a file \ sending to a server \ something that will output even during a crash. I bet it will become pretty obvious the problem.
  • HAL9000HAL9000 FRMember

    Hello,

    This is my Xamarin log crach
    `mono-rt: Stacktrace:

    mono-rt: at <0xffffffff>

    mono-rt: at (wrapper managed-to-native) MonoTouch.AudioToolbox.AudioQueue.memcpy (byte,byte,int)

    mono-rt: at MonoTouch.AudioToolbox.AudioQueue.FillAudioData (intptr,int,intptr,int,int) [0x00016] in /Developer/MonoTouch/Source/maccore/src/AudioToolbox/AudioQueue.cs:472

    mono-rt: at StreamingAudio.StreamingPlayback.AudioPacketDecoded (object,MonoTouch.AudioToolbox.PacketReceivedEventArgs) [0x00090] in /Users/[email protected]/Documents/ionWeb_app/RadioScoop/RadioScoop.iOS/Streaming/StreamingPlayback.cs:206

    mono-rt: at MonoTouch.AudioToolbox.AudioFileStream.OnPacketDecoded (int,intptr,MonoTouch.AudioToolbox.AudioStreamPacketDescription[]) [0x0000d] in /Developer/MonoTouch/Source/maccore/src/AudioToolbox/AudioFileStream.cs:190

    mono-rt: at MonoTouch.AudioToolbox.AudioFileStream.InPackets (intptr,int,int,intptr,intptr) [0x0001d] in /Developer/MonoTouch/Source/maccore/src/AudioToolbox/AudioFileStream.cs:182

    mono-rt: at (wrapper native-to-managed) MonoTouch.AudioToolbox.AudioFileStream.InPackets (intptr,int,int,intptr,intptr)

    mono-rt: at <0xffffffff>

    mono-rt: at (wrapper managed-to-native) MonoTouch.AudioToolbox.AudioFileStream.AudioFileStreamParseBytes (intptr,int,intptr,uint)

    mono-rt: at MonoTouch.AudioToolbox.AudioFileStream.ParseBytes (byte[],int,int,bool) [0x00053] in /Developer/MonoTouch/Source/maccore/src/AudioToolbox/AudioFileStream.cs:261

    mono-rt: at StreamingAudio.StreamingPlayback.ParseBytes (byte[],int,bool,bool) [0x0001f] in /Users/[email protected]/Documents/ionWeb_app/RadioScoop/RadioScoop.iOS/Streaming/StreamingPlayback.cs:147

    mono-rt: at RadioScoop.iOS.PlayerViewController.StreamDownloadedHandler (System.IAsyncResult) [0x00090] in /Users/[email protected]/Documents/ionWeb_app/RadioScoop/RadioScoop.iOS/PlayerViewController.cs:561

    mono-rt: at System.Net.SimpleAsyncResult/c__AnonStorey0.<>m__0 (System.Net.SimpleAsyncResult) [0x0000b] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/SimpleAsyncResult.cs:62

    mono-rt: at System.Net.SimpleAsyncResult.DoCallback_internal () [0x0001d] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/SimpleAsyncResult.cs:165

    mono-rt: at System.Net.WebAsyncResult.DoCallback () [0x00000] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/WebAsyncResult.cs:96

    mono-rt: at System.Net.HttpWebRequest.SetResponseData (System.Net.WebConnectionData) [0x00212] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/HttpWebRequest.cs:1503

    mono-rt: at System.Net.WebConnection.ReadDone (System.IAsyncResult) [0x002bc] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/WebConnection.cs:612

    mono-rt: at (wrapper runtime-invoke) .runtime_invoke_void__this___object (object,intptr,intptr,intptr)

    mono-rt:
    Native stacktrace:

    mono-rt:

    Got a SIGSEGV while executing native code. This usually indicates
    a fatal error in the mono runtime or one of the native libraries
    used by your application.
    =================================================================`

    I try to print ParseBytes \ CallPacketsProc arguments but the app crash before to print, and same thing in debugging.

  • HAL9000HAL9000 FRMember

    Hello,

    This is my Xamarin log crach
    `mono-rt: Stacktrace:

    mono-rt: at <0xffffffff>

    mono-rt: at (wrapper managed-to-native) MonoTouch.AudioToolbox.AudioQueue.memcpy (byte,byte,int)

    mono-rt: at MonoTouch.AudioToolbox.AudioQueue.FillAudioData (intptr,int,intptr,int,int) [0x00016] in /Developer/MonoTouch/Source/maccore/src/AudioToolbox/AudioQueue.cs:472

    mono-rt: at StreamingAudio.StreamingPlayback.AudioPacketDecoded (object,MonoTouch.AudioToolbox.PacketReceivedEventArgs) [0x00090] in /Users/[email protected]/Documents/ionWeb_app/RadioScoop/RadioScoop.iOS/Streaming/StreamingPlayback.cs:206

    mono-rt: at MonoTouch.AudioToolbox.AudioFileStream.OnPacketDecoded (int,intptr,MonoTouch.AudioToolbox.AudioStreamPacketDescription[]) [0x0000d] in /Developer/MonoTouch/Source/maccore/src/AudioToolbox/AudioFileStream.cs:190

    mono-rt: at MonoTouch.AudioToolbox.AudioFileStream.InPackets (intptr,int,int,intptr,intptr) [0x0001d] in /Developer/MonoTouch/Source/maccore/src/AudioToolbox/AudioFileStream.cs:182

    mono-rt: at (wrapper native-to-managed) MonoTouch.AudioToolbox.AudioFileStream.InPackets (intptr,int,int,intptr,intptr)

    mono-rt: at <0xffffffff>

    mono-rt: at (wrapper managed-to-native) MonoTouch.AudioToolbox.AudioFileStream.AudioFileStreamParseBytes (intptr,int,intptr,uint)

    mono-rt: at MonoTouch.AudioToolbox.AudioFileStream.ParseBytes (byte[],int,int,bool) [0x00053] in /Developer/MonoTouch/Source/maccore/src/AudioToolbox/AudioFileStream.cs:261

    mono-rt: at StreamingAudio.StreamingPlayback.ParseBytes (byte[],int,bool,bool) [0x0001f] in /Users/[email protected]/Documents/ionWeb_app/RadioScoop/RadioScoop.iOS/Streaming/StreamingPlayback.cs:147

    mono-rt: at RadioScoop.iOS.PlayerViewController.StreamDownloadedHandler (System.IAsyncResult) [0x00090] in /Users/[email protected]/Documents/ionWeb_app/RadioScoop/RadioScoop.iOS/PlayerViewController.cs:561

    mono-rt: at System.Net.SimpleAsyncResult/c__AnonStorey0.<>m__0 (System.Net.SimpleAsyncResult) [0x0000b] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/SimpleAsyncResult.cs:62

    mono-rt: at System.Net.SimpleAsyncResult.DoCallback_internal () [0x0001d] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/SimpleAsyncResult.cs:165

    mono-rt: at System.Net.WebAsyncResult.DoCallback () [0x00000] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/WebAsyncResult.cs:96

    mono-rt: at System.Net.HttpWebRequest.SetResponseData (System.Net.WebConnectionData) [0x00212] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/HttpWebRequest.cs:1503

    mono-rt: at System.Net.WebConnection.ReadDone (System.IAsyncResult) [0x002bc] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/WebConnection.cs:612

    mono-rt: at (wrapper runtime-invoke) .runtime_invoke_void__this___object (object,intptr,intptr,intptr)

    mono-rt:
    Native stacktrace:

    mono-rt:

    Got a SIGSEGV while executing native code. This usually indicates
    a fatal error in the mono runtime or one of the native libraries
    used by your application.
    =================================================================`

    I try to print ParseBytes \ CallPacketsProc arguments but the app crash before to print, and same thing in debugging.

  • KristianLoekkegaardKristianLoekkegaard DKMember ✭✭
    edited March 2016

    In case anyone else runs into this issue, the problem for me was that sometimes an audio packet would be decoded while the StreamingPlayback instance was being disposed, which would result in the event handler for the PacketDecoded event calling the FillAudioData method passing in an audio buffer that had been freed. That causes the low level error @HAL9000 also experienced, which I was unable to catch and handle anywhere in my code. This only happens if you continue to pass in audio data for playback from one thread, while trying to dispose the StreamingPlayback instance from another thread.

    This is the ParseBytes method on the StreamingPlayback class, which passes audio data to an AudioFileStream instance, that will in turn raise the PacketDecoded event with decoded audio:

    public void ParseBytes (byte[] buffer, int count, bool discontinuity, bool lastPacket)
    {
        this.lastPacket = lastPacket;
        fileStream.ParseBytes (buffer, 0, count, discontinuity);
    }
    

    The PacketDecoded event handler of the StreamingPlayback class looks like this and calls FillAudioData passing in the decoded audio to be queued for playback using an allocated audio buffer:

    void AudioPacketDecoded (object sender, PacketReceivedEventArgs args)
    {
        foreach (var p in args.PacketDescriptions) {
            currentByteCount += p.DataByteSize;
    
            AudioStreamPacketDescription pd = p;
    
            int left = bufferSize - currentBuffer.CurrentOffset;
            if (left < pd.DataByteSize) {
                EnqueueBuffer ();
                WaitForBuffer ();
            }
    
            AudioQueue.FillAudioData (currentBuffer.Buffer, currentBuffer.CurrentOffset, args.InputData, (int)pd.StartOffset, pd.DataByteSize);
    
            // Set new offset for this packet
            pd.StartOffset = currentBuffer.CurrentOffset;
    
            // Add the packet to our Buffer
            currentBuffer.PacketDescriptions.Add (pd);
    
            // Add the Size so that we know how much is in the buffer
            currentBuffer.CurrentOffset += pd.DataByteSize;
        }
    
        if ((fileStream != null && currentByteCount == fileStream.DataByteCount) || lastPacket)
            EnqueueBuffer ();
    }
    

    And the Dispose method of the same class:

    protected virtual void Dispose (bool disposing)
    {
        if (disposing) {
            if (OutputQueue != null)
                OutputQueue.Stop(true);
    
            if (outputBuffers != null) {
                foreach (var b in outputBuffers)
                    OutputQueue.FreeBuffer (b.Buffer);
    
                outputBuffers.Clear ();
                outputBuffers = null;
            }
    
            if (fileStream != null) {
                fileStream.Close ();
                fileStream = null;
            }
    
            if (OutputQueue != null) {
                OutputQueue.Dispose ();
                OutputQueue = null;
            }
        }
    }
    

    Since the buffers are being freed before the AudioFileStream instance is being closed, there is a possibility that the PacketDecoded event will be raised after the buffers are freed. In other words, if you keep passing more audio data to the ParseBytes method from one thread, while another thread tries to dispose the StreamingPlayback instance, you might experience this crash. As a side note, I suppose you might also get a NullReferenceException in the ParseBytes method after the fileStream variable is set to null in the Dispose method.

    Long story short: make sure to stop passing audio data in via the ParseBytes method before disposing the StreamingPlayback instance.

    Here is the link to StreamingPlayback class by @MigueldeIcaza on GitHub for reference: https://github.com/xamarin/monotouch-samples/blob/master/StreamingAudio/StreamingPlayback.cs

Sign In or Register to comment.