https://bugs.winehq.org/show_bug.cgi?id=53475
Bug ID: 53475 Summary: Hang: underrun of data / failed to create thread Product: Wine Version: 7.14 Hardware: x86-64 OS: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: dsound Assignee: wine-bugs@winehq.org Reporter: ilkka.prusi@gmail.com Distribution: ---
Playing Alansya Chronicles in some situations the game will hang and needs to be forcibly closed. This happens on all Wine 7.x versions and I haven't tested with older versions of Wine.
There are specific log entries to note when this hang occurs:
(wine:3413): GStreamer-WARNING **: 22:20:23.968: failed to create thread: Error creating thread: Resource temporarily unavailable
028c:fixme:quartz:DSoundRender_UpdatePositions Underrun of data occurred!
Game uses many short audio samples during playback so perhaps thread pool is exhausted? Second entry would indicate that there is synchronization issue in the playback.
But there is another indication that the dsound code is iffy: 01a0:err:quartz:DSoundRender_SendSampleData WaitForSingleObject() returned 0.
This log entry is triggered when This->flush_event is signalled and the code is expecting timeout. This by itself is already strange looking code (from Win32-style standpoint), but what the code does next is even stranger.
Flush event looks like it is meant as signal that code trying to write should exit, the comment says that much: /* Signaled when a flush or state change occurs, i.e. anything that needs * to immediately unblock the streaming thread. */
But when DSoundRender_SendSampleData() gets the signalled event it goes back and tries to continue the loop instead of exiting.
I suspect the code expects that This->sink.flushing would have been set already when the event is signalled but apparently it isn't.
However, having DSoundRender_SendSampleData() bail out on the event does not fix the hang, which would indicate there is more to the issue than just one part.
So, maybe DSoundRender_SendSampleData() could check that if WaitForSingleObject() returns 0 (event signalled) it could just exit and log that instead of trying to repeat? It seems to be normal occurrence instead of error?
The state management seems oddly complicated and like it was added later than by design initially? I suspect this could be made much simpler to avoid the issue.
If there is race condition in state management, is it possible the code will hang indefinitely in DSoundRender_HandleEndOfStream()? That looks like a possible place that would explain the hang I'm seeing.