Skip to content
This repository has been archived by the owner on Aug 22, 2018. It is now read-only.

DynamicSoundEffectInstance AccessViolationException #34

Closed
gitfool opened this issue Oct 5, 2014 · 14 comments
Closed

DynamicSoundEffectInstance AccessViolationException #34

gitfool opened this issue Oct 5, 2014 · 14 comments
Assignees
Milestone

Comments

@gitfool
Copy link

gitfool commented Oct 5, 2014

Following up from Paradox Answers.

I've managed to create a reasonably minimal repro project that exhibits the crash behaviour. Since this involves a race condition, I've also created a PowerShell script that I used to loop until the crash appears (and captures a crash dump). This can take a few thousand iterations, which in real time could take an hour or more.

You'll need the following files:

Then to repro the crash:

  • Compile the DseiRepro solution
  • Extract Test-Process.ps1 and Sysinternals ProcDump into a directory
    • Put procdump.exe in the same directory as the script
  • Open a PowerShell prompt in that directory
  • Run Test-Process, specifying the path and iterations parameters
    • I used the sleep parameter default value (1 second)
    • ./Test-Process.ps1 -path {PathToDseiReproExe} -iterations 1000000

Since the crash happens during application shutdown, the script loops over the following:

  • Create a new process for the executable under test
  • Create a new process for ProcDump to monitor the test
  • Sleep the specified number of seconds
  • Close the test window (to shutdown gracefully)
  • Check process exit codes to look for anomalies

The number of iterations is just the maximum. It will stop as soon as it repros the crash and generate a dump file in the same directory as the executable under test.

@gitfool
Copy link
Author

gitfool commented Oct 5, 2014

I really want to get this crash dump file to you guys, just in case you have trouble with the repro, so let's try a split archive file:

@xenux xenux added the bug label Oct 6, 2014
@xenux xenux self-assigned this Oct 6, 2014
@xenux
Copy link

xenux commented Oct 6, 2014

ok thanks a lot, I will check that.

@gitfool
Copy link
Author

gitfool commented Oct 10, 2014

I haven't heard back from you guys, so here's my analysis using WinDbg and SOSEX:

There are two threads of interest; thread 0 is waiting for the DynamicSoundEffectInstance worker task (a long running thread) to complete (in DynamicSoundEffectInstance.DestroyImpl):

Thread 0:
     ESP      EIP
00:U 0109ee28 7797aaac ntdll!NtWaitForMultipleObjects+0xc
01:U 0109ee2c 76ee0927 KERNELBASE!WaitForMultipleObjectsEx+0xcc
02:U 0109efb0 728b6e26 clr!WaitForMultipleObjectsEx_SO_TOLERANT+0x3c
03:U 0109f000 728b6b85 clr!Thread::DoAppropriateWaitWorker+0x237
04:U 0109f08c 728b6c76 clr!Thread::DoAppropriateWait+0x64
05:U 0109f0f8 728b6dcc clr!CLREventBase::WaitEx+0x128
06:U 0109f144 727f8861 clr!CLREventBase::Wait+0x1a
07:U 0109f158 728f9691 clr!Thread::Block+0x25
08:U 0109f16c 728f97cf clr!SyncBlock::Wait+0x18d
09:U 0109f21c 728f98b0 clr!ObjectNative::WaitTimeout+0xcb
0a:M 0109f2b8 719498ea System.Threading.Monitor.Wait(System.Object, Int32, Boolean)(+0xfffffffd IL)(+0x16 Native)
0b:M 0109f2c8 7195bcdb System.Threading.Monitor.Wait(System.Object, Int32)(+0x0 IL)(+0x7 Native)
0c:M 0109f2d0 719641c6 System.Threading.ManualResetEventSlim.Wait(Int32, System.Threading.CancellationToken)(+0x11b IL)(+0x182 Native)
0d:M 0109f320 71963f0e System.Threading.Tasks.Task.SpinThenBlockingWait(Int32, System.Threading.CancellationToken)(+0x51 IL)(+0xe2 Native)
0e:M 0109f360 71994bd4 System.Threading.Tasks.Task.InternalWait(Int32, System.Threading.CancellationToken)(+0x7c IL)(+0x148 Native)
0f:M 0109f3b8 71963d72 System.Threading.Tasks.Task.Wait(Int32, System.Threading.CancellationToken)(+0x1c IL)(+0x2a Native)
10:M 0109f3cc 098925ed SiliconStudio.Paradox.Audio.DynamicSoundEffectInstance.DestroyImpl()(+0x2f IL)(+0x4d Native)
11:M 0109f3d8 0989248b SiliconStudio.Paradox.Audio.SoundInstanceBase.Destroy()(+0x0 IL)(+0x2b Native)
12:M 0109f3e4 09892305 SiliconStudio.Core.ComponentBase.Dispose()(+0x20 IL)(+0x1d Native)
13:M 0109f3f0 0989242c DseiRepro.ParadoxAudioService.Dispose(Boolean)(+0x23 IL)(+0x5c Native)
14:M 0109f404 098923ae DseiRepro.DisposableBase.Dispose()(+0x8 IL)(+0x26 Native)
15:M 0109f410 09892367 DseiRepro.DseiReproGame.Destroy()(+0xc IL)(+0x27 Native)
16:M 0109f428 01447a3c DseiRepro.DseiReproApp.Main(System.String[])(+0x21 IL)(+0x94 Native)
17:U 0109f460 72772652 clr!CallDescrWorkerInternal+0x34
18:U 0109f46c 72781580 clr!CallDescrWorkerWithHandler+0x6b
19:U 0109f4c0 7278e670 clr!MethodDescCallSite::CallTargetWorker+0x152
1a:U 0109f538 728e2955 clr!RunMain+0x1aa
1b:U 0109f65c 728e2891 clr!Assembly::ExecuteMainMethod+0x124
1c:U 0109f8d0 7289ec8b clr!SystemDomain::ExecuteMainMethod+0x63c
1d:U 0109fdd0 7289ed2e clr!ExecuteEXE+0x4c
1e:U 0109fe28 7289ee42 clr!_CorExeMainInternal+0xdc
1f:U 0109fe68 728a2370 clr!_CorExeMain+0x4d
20:U 0109fea4 72e1ec94 mscoreei!_CorExeMain+0x10a
21:U 0109fee0 72e9bbcc mscoree!_CorExeMain_Exported+0x8c
22:U 0109fef0 7713919f kernel32!BaseThreadInitThunk+0xe
23:U 0109fefc 77990bbb ntdll!__RtlUserThreadStart+0x20
24:U 0109ff40 77990b91 ntdll!_RtlUserThreadStart+0x1b

and thread 10 is the DynamicSoundEffectInstance worker thread that threw the AccessViolationException:

Thread 10:
     ESP      EIP
00:U 0663f448 5d33c6e3 XAudio2_7!XAUDIO2::CX2SourceVoice::SubmitSourceBuffer+0x173
01:M 0663f494 06100c55 SharpDX.XAudio2.SourceVoice.SubmitSourceBuffer(SharpDX.XAudio2.AudioBuffer, IntPtr)(+0x32 IL)(+0x9d Native)
02:M 0663f500 06100b95 SharpDX.XAudio2.SourceVoice.SubmitSourceBuffer(SharpDX.XAudio2.AudioBuffer, UInt32[])(+0xfffffffd IL)(+0x5d Native)
03:M 0663f51c 06100b11 SiliconStudio.Paradox.Audio.DynamicSoundEffectInstance.SubmitBufferImpl(Byte[], Int32, Int32)(+0x48 IL)(+0x71 Native)
04:M 0663f53c 061009a8 SiliconStudio.Paradox.Audio.DynamicSoundEffectInstance.SubmitBuffer(Byte[], Int32, Int32)(+0x73 IL)(+0x70 Native)
05:M 0663f558 061008d5 DseiRepro.ParadoxAudioService.OnDynamicSoundEffectBufferNeeded(System.Object, System.EventArgs)(+0x18 IL)(+0x4d Native)
06:M 0663f574 0144f095 SiliconStudio.Paradox.Audio.DynamicSoundEffectInstance.WorkerThread()(+0x34 IL)(+0x4d Native)
07:M 0663f580 719604e5 System.Threading.Tasks.Task.InnerInvoke()(+0x0 IL)(+0x49 Native)
08:M 0663f58c 7196044a System.Threading.Tasks.Task.Execute()(+0x10 IL)(+0x2e Native)
09:M 0663f5b0 71960419 System.Threading.Tasks.Task.ExecutionContextCallback(System.Object)(+0x0 IL)(+0x15 Native)
0a:M 0663f5b4 7192df17 System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)(+0x72 IL)(+0xa7 Native)
0b:M 0663f618 7192de66 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)(+0x0 IL)(+0x16 Native)
0c:M 0663f62c 71960238 System.Threading.Tasks.Task.ExecuteWithThreadLocal(System.Threading.Tasks.Task ByRef)(+0xd8 IL)(+0xd8 Native)
0d:M 0663f698 71960157 System.Threading.Tasks.Task.ExecuteEntry(Boolean)(+0x96 IL)(+0xb3 Native)
0e:M 0663f6a8 719600a3 System.Threading.Tasks.Task.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()(+0x0 IL)(+0x7 Native)
0f:M 0663f6ac 7198894a System.Threading.ThreadPoolWorkQueue.Dispatch()(+0xa2 IL)(+0x10a Native)
10:M 0663f6fc 71988835 System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()(+0x0 IL)(+0x5 Native)
11:U 0663f70c 72781580 clr!CallDescrWorkerWithHandler+0x6b
12:U 0663f760 7278e670 clr!MethodDescCallSite::CallTargetWorker+0x152
13:U 0663f7d4 72858b39 clr!QueueUserWorkItemManagedCallback+0x23
14:U 0663f84c 7798612a ntdll!LdrGetProcedureAddressForCaller+0x201
15:U 0663f96c 728b5984 clr!ManagedThreadBase_FullTransitionWithAD+0x2f
16:U 0663f990 72858a78 clr!ManagedPerAppDomainTPCount::DispatchWorkItem+0xc5
17:U 0663fa40 727f5f40 clr!ThreadpoolMgr::ExecuteWorkRequest+0x42
18:U 0663fa54 727f607f clr!ThreadpoolMgr::WorkerThreadStart+0x36c
19:U 0663fabc 7286814d clr!Thread::intermediateThreadProc+0x4d
1a:U 0663fbe0 7713919f kernel32!BaseThreadInitThunk+0xe
1b:U 0663fbec 77990bbb ntdll!__RtlUserThreadStart+0x20
1c:U 0663fc30 77990b91 ntdll!_RtlUserThreadStart+0x1b

The faulting IP was at 0x5d33c6e3, which is near the end of XAudio2_7!XAUDIO2::CX2SourceVoice::SubmitSourceBuffer:

...
XAudio2_7!XAUDIO2::CX2SourceVoice::SubmitSourceBuffer+0x15b:
5d33c6cb 6a00            push    0
5d33c6cd 8d55d4          lea     edx,[ebp-2Ch]
5d33c6d0 52              push    edx
5d33c6d1 8b4508          mov     eax,dword ptr [ebp+8]
5d33c6d4 8b8890000000    mov     ecx,dword ptr [eax+90h]
5d33c6da 8b5508          mov     edx,dword ptr [ebp+8]
5d33c6dd 8b8290000000    mov     eax,dword ptr [edx+90h]
5d33c6e3 8b09            mov     ecx,dword ptr [ecx]
5d33c6e5 50              push    eax
5d33c6e6 8b511c          mov     edx,dword ptr [ecx+1Ch]
5d33c6e9 ffd2            call    edx
5d33c6eb 8945d0          mov     dword ptr [ebp-30h],eax
5d33c6ee 837dd000        cmp     dword ptr [ebp-30h],0
5d33c6f2 7c23            jl      XAudio2_7!XAUDIO2::CX2SourceVoice::SubmitSourceBuffer+0x1a7 (5d33c717)
...

Here the plot thickens because [EBP+8] was used throughout IXAudio2SourceVoice::SubmitSourceBuffer up to this point. Looking more closely at thread 0, I suspect a race condition caused by DynamicSoundEffectInstance.DestroyImpl with the help of .NET Reflector:

internal override void DestroyImpl()
{
    base.AudioEngine.UnregisterSound(this);
    base.DestroyImpl();
    Interlocked.Decrement(ref numberOfInstances);
    if (numberOfInstances == 0)
    {
        awakeWorkerThread.Set();
        if (!workerTask.Wait(500))
        {
            throw new AudioSystemInternalException("The DynamicSoundEffectInstance worker did not complete in allowed time.");
        }
        awakeWorkerThread.Dispose();
    }
}

calls base.DestroyImpl just before waiting for the DynamicSoundEffectInstance worker task to complete:

internal override void DestroyImpl()
{
    if (this.soundEffect != null)
    {
        this.soundEffect.UnregisterInstance(this);
    }
    this.PlatformSpecificDisposeImpl();
}

which calls PlatformSpecificDisposeImpl:

internal void PlatformSpecificDisposeImpl()
{
    if (this.SourceVoice != null)
    {
        this.SourceVoice.DestroyVoice();
        this.SourceVoice.Dispose();
    }
}

which destroys the SourceVoice.

@xen2
Copy link
Contributor

xen2 commented Oct 10, 2014

Thanks, look very useful/helpful!
Sorry that we prioritized a few other things first on our side, but we should get to it soon.

@gitfool
Copy link
Author

gitfool commented Oct 10, 2014

The worker thread is as follows:

private static void WorkerThread()
{
    while (true)
    {
        DynamicSoundEffectInstance instance;
        awakeWorkerThread.WaitOne();
        if (numberOfInstances == 0)
        {
            return;
        }
        while (instancesNeedingBuffer.TryDequeue(out instance))
        {
            if (!instance.IsDisposed && (instance.BufferNeeded != null))
            {
                instance.BufferNeeded(instance, EventArgs.Empty);
            }
        }
    }
}

and is normally signalled by CheckAndThrowBufferNeededEvent:

private void CheckAndThrowBufferNeededEvent()
{
    if ((this.internalPendingBufferCount <= 2) && (this.BufferNeeded != null))
    {
        instancesNeedingBuffer.Enqueue(this);
        awakeWorkerThread.Set();
    }
}

The signalling from DestroyImpl is just for shutdown.

So to test this theory, a suspected race condition can be flushed out by adding a 'sleep' in just the right place. In this case, it looks like adding a small sleep to the BufferNeeded callback (to delay the worker thread from exiting) could do the trick.

Indeed, I get a crash within just a few iterations after doing this...

@gitfool
Copy link
Author

gitfool commented Oct 10, 2014

Specifically, I changed ParadoxAudioService.OnDynamicSoundEffectBufferNeeded in the repro to:

private void OnDynamicSoundEffectBufferNeeded(object sender, EventArgs e) // audio thread
{
    Task.Delay(10).Wait();
    ...
}

@gitfool
Copy link
Author

gitfool commented Oct 10, 2014

@gitfool
Copy link
Author

gitfool commented Oct 10, 2014

Analysis using WinDbg and SOSEX:

This time the DynamicSoundEffectInstance worker thread is not in the stack traces. The reason seems to be because it threw a NullReferenceException and exited. This was observed by the DynamicSoundEffectInstance worker task (via Wait) and rethrown from this context:

EXCEPTION_OBJECT: !pe 2e7e0b0
Exception object: 02e7e0b0
Exception type:   System.AggregateException
Message:          One or more errors occurred.
InnerException:   System.NullReferenceException, Use !PrintException 02e7c870 to see more.
StackTrace (generated):
    SP       IP       Function
    0115F01C 71A66D92 mscorlib_ni!System.Threading.Tasks.Task.ThrowIfExceptional(Boolean)+0x3a823a
    0115F02C 71A2D9EE mscorlib_ni!System.Threading.Tasks.Task.Wait(Int32, System.Threading.CancellationToken)+0xa69ca6
    0115F03C 097A9B6D UNKNOWN!SiliconStudio.Paradox.Audio.DynamicSoundEffectInstance.DestroyImpl()+0x4d
    0115F048 097A9A0B UNKNOWN!SiliconStudio.Paradox.Audio.SoundInstanceBase.Destroy()+0x2b
    0115F054 097A9885 UNKNOWN!SiliconStudio.Core.ComponentBase.Dispose()+0x1d
    0115F060 097A99AC UNKNOWN!DseiRepro.ParadoxAudioService.Dispose(Boolean)+0x5c
    0115F074 097A992E UNKNOWN!DseiRepro.DisposableBase.Dispose()+0x26
    0115F080 097A98E7 UNKNOWN!DseiRepro.DseiReproGame.Destroy()+0x27
    0115F08C 097A9885 UNKNOWN!SiliconStudio.Core.ComponentBase.Dispose()+0x1d
    0115F098 01437C1C DseiRepro!DseiRepro.DseiReproApp.Main(System.String[])+0x94

StackTraceString: <none>
HResult: 80131500

EXCEPTION_OBJECT: !pe 2e7c870
Exception object: 02e7c870
Exception type:   System.NullReferenceException
Message:          Object reference not set to an instance of an object.
InnerException:   <none>
StackTrace (generated):
    SP       IP       Function
    066FF23C 05CF12F6 UNKNOWN!SharpDX.XAudio2.SourceVoice.SubmitSourceBuffer(SharpDX.XAudio2.AudioBuffer, IntPtr)+0x7e
    066FF29C 05CF1255 UNKNOWN!SharpDX.XAudio2.SourceVoice.SubmitSourceBuffer(SharpDX.XAudio2.AudioBuffer, UInt32[])+0x5d
    066FF2B8 05CF11D1 UNKNOWN!SiliconStudio.Paradox.Audio.DynamicSoundEffectInstance.SubmitBufferImpl(Byte[], Int32, Int32)+0x71
    066FF2D8 05CF1068 UNKNOWN!SiliconStudio.Paradox.Audio.DynamicSoundEffectInstance.SubmitBuffer(Byte[], Int32, Int32)+0x70
    066FF2F4 05CF0AF0 UNKNOWN!DseiRepro.ParadoxAudioService.OnDynamicSoundEffectBufferNeeded(System.Object, System.EventArgs)+0x68
    066FF314 0143F275 UNKNOWN!SiliconStudio.Paradox.Audio.DynamicSoundEffectInstance.WorkerThread()+0x4d
    066FF320 70FC04E5 mscorlib_ni!System.Threading.Tasks.Task.InnerInvoke()+0x49
    066FF32C 70FC044A mscorlib_ni!System.Threading.Tasks.Task.Execute()+0x2e

@gitfool
Copy link
Author

gitfool commented Oct 10, 2014

@xen2 No need to apologise, you guys have been very response for everything else and are awesome as far as I'm concerned! ;)

I had some time and have had more than my share of experience dealing with nasty crashes, so hopefully this analysis helps others learn too.

@xen2
Copy link
Contributor

xen2 commented Oct 10, 2014

Thanks, should be able to fix it easily with all this info :)

@gitfool
Copy link
Author

gitfool commented Oct 10, 2014

I have some more 'evidence'.

I wanted to know more about the NullReferenceException on the DynamicSoundEffectInstance worker thread, and I noticed after the fact that ProcDump was indicating there was still an access violation exception, but the only way to catch this in action this was to catch first chance exceptions. You can change the arguments passed to ProcDump in the Test-Process.ps1 script to:

$dumpStartInfo.Arguments = "-accepteula -ma -g -e 1 $($test.Id)"

But with the delay introduced above flushing out the crash within just a few iterations, it was easier to run the process directly via WinDbg. (Visual Studio doesn't quite cut it for debugging this sort of stuff, which is a shame because I prefer it to the arcane mysteries of WinDbg.) Quick and dirty analysis using WinDbg and SOSEX:

Both our suspect threads are in the stack traces when the debugger stops with a first chance access violation exception at IP 0x05611186. Then digging deeper into the worker thread, which takes a bit more effort, we find the exception is occurring in the middle of the JIT generated code for SharpDX.XAudio2.SourceVoice.SubmitSourceBuffer:

0:010> !u 05611108
Normal JIT generated code
SharpDX.XAudio2.SourceVoice.SubmitSourceBuffer(SharpDX.XAudio2.AudioBuffer, IntPtr)
Begin 05611108, size d3
>>> 05611108 55              push    ebp
05611109 8bec            mov     ebp,esp
0561110b 57              push    edi
0561110c 56              push    esi
0561110d 53              push    ebx
0561110e 83ec48          sub     esp,48h
05611111 8bf1            mov     esi,ecx
05611113 8d7dcc          lea     edi,[ebp-34h]
05611116 b90a000000      mov     ecx,0Ah
0561111b 33c0            xor     eax,eax
0561111d f3ab            rep stos dword ptr es:[edi]
0561111f 8bce            mov     ecx,esi
05611121 648b35300e0000  mov     esi,dword ptr fs:[0E30h]
05611128 c745b0c88bdd71  mov     dword ptr [ebp-50h],offset clr!InlinedCallFrame::`vftable' (71dd8bc8)
0561112f c745ac7b5bd4e1  mov     dword ptr [ebp-54h],0E1D45B7Bh
05611136 8b460c          mov     eax,dword ptr [esi+0Ch]
05611139 8945b4          mov     dword ptr [ebp-4Ch],eax
0561113c 896dc4          mov     dword ptr [ebp-3Ch],ebp
0561113f c745c000000000  mov     dword ptr [ebp-40h],0
05611146 8d45b0          lea     eax,[ebp-50h]
05611149 89460c          mov     dword ptr [esi+0Ch],eax
0561114c 8955c8          mov     dword ptr [ebp-38h],edx
0561114f 8bd9            mov     ebx,ecx
05611151 8d7dd0          lea     edi,[ebp-30h]
05611154 33c0            xor     eax,eax
05611156 0f57c0          xorps   xmm0,xmm0
05611159 660fd607        movq    mmword ptr [edi],xmm0
0561115d 660fd64708      movq    mmword ptr [edi+8],xmm0
05611162 660fd64710      movq    mmword ptr [edi+10h],xmm0
05611167 660fd64718      movq    mmword ptr [edi+18h],xmm0
0561116c 83c720          add     edi,20h
0561116f ab              stos    dword ptr es:[edi]
05611170 8d55d0          lea     edx,[ebp-30h]
05611173 8b4dc8          mov     ecx,dword ptr [ebp-38h]
05611176 3909            cmp     dword ptr [ecx],ecx
05611178 ff1530c0eb04    call    dword ptr ds:[4EBC030h] (SharpDX.XAudio2.AudioBuffer.__MarshalTo(__Native ByRef), mdToken: 06000012)
0561117e 8b5314          mov     edx,dword ptr [ebx+14h]
05611181 8d4dd0          lea     ecx,[ebp-30h]
05611184 8b02            mov     eax,dword ptr [edx]
05611186 8b7854          mov     edi,dword ptr [eax+54h]
05611189 ff7508          push    dword ptr [ebp+8]
0561118c 51              push    ecx
0561118d 52              push    edx
0561118e c745b80c000000  mov     dword ptr [ebp-48h],0Ch
05611195 8965bc          mov     dword ptr [ebp-44h],esp
05611198 c745c0a5116105  mov     dword ptr [ebp-40h],56111A5h
0561119f c6460800        mov     byte ptr [esi+8],0
056111a3 ffd7            call    edi
056111a5 c6460801        mov     byte ptr [esi+8],1
056111a9 833d1c73407200  cmp     dword ptr [clr!g_TrapReturningThreads (7240731c)],0
056111b0 7407            je      056111b9
056111b2 50              push    eax
056111b3 e846a3946c      call    clr!JIT_RareDisableHelper (71f5b4fe)
056111b8 58              pop     eax
056111b9 c745c000000000  mov     dword ptr [ebp-40h],0
056111c0 8945cc          mov     dword ptr [ebp-34h],eax
056111c3 8d4dcc          lea     ecx,[ebp-34h]
056111c6 e8ada255fb      call    00b6b478 (SharpDX.Result.CheckError(), mdToken: 06000a49)
056111cb 8b7db4          mov     edi,dword ptr [ebp-4Ch]
056111ce 897e0c          mov     dword ptr [esi+0Ch],edi
056111d1 8d65f4          lea     esp,[ebp-0Ch]
056111d4 5b              pop     ebx
056111d5 5e              pop     esi
056111d6 5f              pop     edi
056111d7 5d              pop     ebp
056111d8 c20400          ret     4

i.e. just after the call to SharpDX.XAudio2.AudioBuffer.__MarshalTo.

  • EAX was 0x00000000 when using indirect addressing. Boom!

Looking at the code with Reflector:

internal unsafe void SubmitSourceBuffer(AudioBuffer bufferRef, IntPtr bufferWMARef)
{
    AudioBuffer.__Native native = new AudioBuffer.__Native();
    bufferRef.__MarshalTo(ref native);
    Result result = (Result) **(((IntPtr*) base._nativePointer))[(int) (((IntPtr) 0x15) * sizeof(void*))](base._nativePointer, (IntPtr) &native, (void*) bufferWMARef);
    bufferRef.__MarshalFree(ref native);
    result.CheckError();
}

reveals more clearly the intent; it's preparing to jump through the function table for SharpDX.XAudio2.SourceVoice!

More evidence that destroying the SourceVoice (on the other thread) is most likely the root cause.

@xen2
Copy link
Contributor

xen2 commented Oct 22, 2014

Fixed in newly released beta02.

@xen2 xen2 closed this as completed Oct 22, 2014
@gitfool
Copy link
Author

gitfool commented Oct 23, 2014

Verified as fixed; I eyeballed the commit and then for extra peace of mind I put beta02 through 1000 iterations with my test script. Nice work!

@xenux
Copy link

xenux commented Oct 23, 2014

Good :) thanks!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants