[XAudio2] Deadlock

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Benutzeravatar
Krishty
Establishment
Beiträge: 8350
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

[XAudio2] Deadlock

Beitrag von Krishty »

Hi,

Das hier verursacht einen Deadlock in XAudio2, der – falls ich Glück habe – nach zehn Minuten mit einer Zugriffsverletzung endet. Zwei Internets für den, der mir sagen kann, was ich falsch mache. Bin scheinbar seit Tagen im Wald-vor-lauter-Bäumen-Modus.

Code: Alles auswählen

CoInitializeEx(nullptr, COINIT_MULTITHREADED);
IXAudio2 * audio = nullptr;
XAudio2Create(&audio);
IXAudio2MasteringVoice * voice;
audio->CreateMasteringVoice(&voice);
// Hier scheint alles bestens; ich könnte sogar schön Source Voices erzeugen und damit Sounds abspielen, unterbrechen und blablah
voice->DestroyVoice(); // DEADLOCK
Falls ich im Debug-Modus arbeite, gibt es keine Meldungen außer

Unloaded 'C:\Windows\SysWOW64\avrt.dll'
The thread 'Win32 Thread' (0x1018) has exited with code 0 (0x0).


Gruß, Ky
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: [XAudio2] Deadlock

Beitrag von eXile »

Nope, Chuck Testa.

Leeres Projekt angelegt, Code so in die main gehauen, kein Deadlock. Auf x86 und x64, Debug und Release.
Benutzeravatar
Krishty
Establishment
Beiträge: 8350
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [XAudio2] Deadlock

Beitrag von Krishty »

Wtf. Im Release-Build geht alles; selbst, wenn ich XAudio2 mit Debug-Features initialisiere.

Im Debug-Build geht nichts; egal, ob mit oder ohne Debug-Features und mit oder ohne IDE.

Debug-Symbole sagen während des Deadlocks:

Code: Alles auswählen

 	ntdll.dll!_ZwWaitForSingleObject@12()  + 0x15 bytes	
 	ntdll.dll!_ZwWaitForSingleObject@12()  + 0x15 bytes	
 	kernel32.dll!_WaitForSingleObjectExImplementation@12()  + 0x43 bytes	
 	MMDevAPI.dll!AXB::WaitForOperations()  + 0x1504d bytes	
 	MMDevAPI.dll!CMediaNotifications::UnregisterMediaCallback()  + 0x78 bytes	
 	MMDevAPI.dll!_UnregisterMediaCallback@4()  + 0x25 bytes	
 	AudioSes.dll!CAudioClient::FinalRelease()  + 0x315 bytes	
 	AudioSes.dll!ATL::CComObject<CAudioClient>::~CComObject<CAudioClient>()  + 0x33 bytes	
 	AudioSes.dll!ATL::CComObject<CAudioClient>::`vector deleting destructor'()  + 0xd bytes	
 	AudioSes.dll!ATL::CComObject<CAudioClient>::Release()  + 0x27 bytes	
 	XAudio2_7.dll!RELEASE<IAudioSessionControl>()  + 0x1f bytes	
 	XAudio2_7.dll!LEAPCORE::CEngineRendererConnection::~CEngineRendererConnection()  + 0x91 bytes	
 	XAudio2_7.dll!LEAPCORE::CEngineRendererConnection::`vector deleting destructor'()  + 0x11 bytes	
 	XAudio2_7.dll!CMemoryHelper::Delete<LEAPCORE::CRendererConnection>()  + 0x35 bytes	
 	XAudio2_7.dll!LEAPCORE::CLeapSystem::DisconnectRenderer()  + 0x82 bytes	
 	XAudio2_7.dll!XAUDIO2::CX2OutputVoice::Destroy()  + 0xba bytes	
 	XAudio2_7.dll!XAUDIO2::CX2Voice::DestroyVoice()  + 0xf0 bytes	
 	XAudio2_7.dll!XAUDIO2::CX2SourceVoice::DestroyVoice()  + 0x11 bytes	
>	XXX.exe!main()  Line 25 + 0x10 bytes	C++
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8350
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [XAudio2] Deadlock

Beitrag von Krishty »

Ich habe die Ursache:

Die Zeit, die XAudio2 zum Zerstören der Mastering Voice braucht, ist linear abhängig von der Menge reservierten Stapelspeichers. Wenn ich 1 GiB reserviere (/STACK:1073741824; die Einstellung hatte ich noch als Überbleibsel von meinen _alloca()-Experimenten), dauert die Zerstörung halt zehn Minuten. Bei einem MiB ist es kaum mehr spürbar.

Dieser Stapelspeicher ist zwar reserviert, wird aber zu keiner Zeit genutzt. Darum in aller Deutlichkeit:

WTF?!?

Mir ist klar, dass XAudio2 einen Thread für meine Mastering Voice erstellt, und der mit aller Wahrscheinlichkeit genauso viel Stapel zugesichert bekommt. Aber der wird ja auch nicht benutzt, sonst würde das im Task-Manager auftauchen. Warum beschäftigt sowas minutenlang WaitForSingleObject()? Was zur …?!?
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
dot
Establishment
Beiträge: 1746
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [XAudio2] Deadlock

Beitrag von dot »

Vielleicht fehlt ihm der Adressraum!?
Benutzeravatar
Krishty
Establishment
Beiträge: 8350
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [XAudio2] Deadlock

Beitrag von Krishty »

Und das nur beim Runterfahren, vorher alles ruck-zuck?

Werden Seiten eigentlich beim Lesen comitted? Falls nicht, haben die bestimmt irgendeinen Debugging-Scheiß in der DLL vergessen und suchen den kompletten Stapel einmal von oben nach unten nach Magic Numbers ab oder so … Copy on Write?
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
dot
Establishment
Beiträge: 1746
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [XAudio2] Deadlock

Beitrag von dot »

Ja, vermutlich ist irgendsowas. Schau mal ob er dir da nicht vielleicht anfängt wie wild zu swappen!?
Benutzeravatar
Krishty
Establishment
Beiträge: 8350
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [XAudio2] Deadlock

Beitrag von Krishty »

Keine Datenträgeraktivität, keine CPU-Auslastung, keine Seitenfehler, nichts. Er hängt einfach nur in WaitForSingleObject() irgendwo in den Annalen von XAudio2.

Ich muss auch das „linear“ zurücknehmen. Bis kurz vor 1 GB merkt man quasi nichts; bei 900.000.000 B sind es 2 s; bei 1.000.000.000 B schon 8 s; bei 1.073.741.824 zehn Minuten und 1.200.000.000 habe ich eben abgebrochen.

Es nervt auch, dass Visual C++ nach Ändern des Werts nicht neu linken will. Ich muss immer Rebuild’en, damit er übernommen wird …


Was habe ich nur wieder für ein Glück. Die absolut unscheinbarste Linker-Einstellung lässt einen API-Aufruf länger dauern, und auch nur, weil ich in einer Mixtur aus Zufall und Wahn eine Zahl der richtigen Größenordnung getroffen habe. Derweil funktionierte mein Programmtext, den ich die letzten vier Tage bis ins letzte Byte gedebuggt habe, natürlich seit jeher fehlerfrei.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Antworten