Ik zit met een lastig probleem waar ik niet uit kom. Ik ben bezig met het maken van een Windows DSP plugin. Hierbij loop ik tegen het volgende aan:
Winamp gebruikt voor het afspelen van muziek 3 plugins: Een input-plugin die (meestal) een file van disk leest, de DSP plugin (processing), en de output plugin die (meestal) het geluid naar een geluidskaart stuurt.
Als een gebruiker bijv. op Stop drukt, dan moet de message die daarvoor verstuurd wordt ergens worden afgehandeld. Probleem: Bij bepaalde combinaties van input en output plugins gebeurt dat niet, en hangt Winamp na enkele seconden.
Na wat puzzelen ben ik erachter gekomen dat regelmatig vanuit mijn plugin SleepEx(0, true) aanroepen, wat ervoor zorgt dat gequeuede APC's (Asynchronous Procedure Calls) worden uitgevoerd, deze hangers oplost (dat had Winamp dus eigenlijk zelf moeten doen; als je een combinatie van input/DSP/output plugin neemt waarbij geen van drieen APC calls laat afhandelen krijg je dus hangers). Alle hangers zijn hiermee verdwenen.
Ok, opgelost. Nou ja, nee dus.
Een van de input-plugins is in_wm.dll, die WMA bestanden afspeelt. Deze input-plugin bevat een rare bug; als ik SleepEx aanroep en op Stop druk dan crasht Winamp met een NULL-pointer exceptie in in_wm.dll. Ik vermoed dat in_wm.dll zelf ergens SleepEx aanroept (zonder mijn SleepEx veroorzaakt in_wm.dll ook geen hangers) en ervoor zorgt dat op dat moment de benodigde data beschikbaar is, maar dat er geen rekening gehouden is met SleepEx calls elders.
Het oplossen van de bug in in_wm.dll is geen optie (staat op miljoenen PC's geinstalleerd). Er zijn trouwens wel redelijk wat klachten over de stabiliteit ervan te vinden.
Wat ik wil:
- Kijken in de APC queue of er iets gequeued is
- Als dat gedurende langere tijd het geval is (dus niemand anders leegt 'm), SleepEx() aanroepen.
Ik heb een testje gedaan waarbij ik SleepEx veel minder vaak aanroep, en Winamp crasht nu ook bijna niet meer. Dus deze oplossing zou zeker helpen.
Maar: Hoe weet ik of er iets in de APC queue zit? Ik heb nog een mogelijke oplossing gevonden die gebruik maakt van een aantal 'undocumented features' van Windows, nl. het Win32 Thread Information Block (TIB), waarin op adres 0x0124 een pointer staat naar een KTHREAD struct, waarin een boolean zit die aangeeft of de APC queue gevuld is. Maar als ik in het TIB kijk vind ik op positie 0x0124 alleen nullen. (De rest van het TIB klopt wel, dus ik zit niet op de verkeerde plek te kijken). Daarmee lukt het me dus niet om bij de KTHREAD-info te komen.
Ik ben een beetje lost. Mijn beste oplossing op dit moment is om dan maar minder vaak SleepEx aan te roepen om de kans op een crash te verminderen - maar een echte oplossing zou zeer welkom zijn.
Winamp gebruikt voor het afspelen van muziek 3 plugins: Een input-plugin die (meestal) een file van disk leest, de DSP plugin (processing), en de output plugin die (meestal) het geluid naar een geluidskaart stuurt.
Als een gebruiker bijv. op Stop drukt, dan moet de message die daarvoor verstuurd wordt ergens worden afgehandeld. Probleem: Bij bepaalde combinaties van input en output plugins gebeurt dat niet, en hangt Winamp na enkele seconden.
Na wat puzzelen ben ik erachter gekomen dat regelmatig vanuit mijn plugin SleepEx(0, true) aanroepen, wat ervoor zorgt dat gequeuede APC's (Asynchronous Procedure Calls) worden uitgevoerd, deze hangers oplost (dat had Winamp dus eigenlijk zelf moeten doen; als je een combinatie van input/DSP/output plugin neemt waarbij geen van drieen APC calls laat afhandelen krijg je dus hangers). Alle hangers zijn hiermee verdwenen.
Ok, opgelost. Nou ja, nee dus.
Een van de input-plugins is in_wm.dll, die WMA bestanden afspeelt. Deze input-plugin bevat een rare bug; als ik SleepEx aanroep en op Stop druk dan crasht Winamp met een NULL-pointer exceptie in in_wm.dll. Ik vermoed dat in_wm.dll zelf ergens SleepEx aanroept (zonder mijn SleepEx veroorzaakt in_wm.dll ook geen hangers) en ervoor zorgt dat op dat moment de benodigde data beschikbaar is, maar dat er geen rekening gehouden is met SleepEx calls elders.
Het oplossen van de bug in in_wm.dll is geen optie (staat op miljoenen PC's geinstalleerd). Er zijn trouwens wel redelijk wat klachten over de stabiliteit ervan te vinden.
Wat ik wil:
- Kijken in de APC queue of er iets gequeued is
- Als dat gedurende langere tijd het geval is (dus niemand anders leegt 'm), SleepEx() aanroepen.
Ik heb een testje gedaan waarbij ik SleepEx veel minder vaak aanroep, en Winamp crasht nu ook bijna niet meer. Dus deze oplossing zou zeker helpen.
Maar: Hoe weet ik of er iets in de APC queue zit? Ik heb nog een mogelijke oplossing gevonden die gebruik maakt van een aantal 'undocumented features' van Windows, nl. het Win32 Thread Information Block (TIB), waarin op adres 0x0124 een pointer staat naar een KTHREAD struct, waarin een boolean zit die aangeeft of de APC queue gevuld is. Maar als ik in het TIB kijk vind ik op positie 0x0124 alleen nullen. (De rest van het TIB klopt wel, dus ik zit niet op de verkeerde plek te kijken). Daarmee lukt het me dus niet om bij de KTHREAD-info te komen.
Ik ben een beetje lost. Mijn beste oplossing op dit moment is om dan maar minder vaak SleepEx aan te roepen om de kans op een crash te verminderen - maar een echte oplossing zou zeer welkom zijn.