[PATCH 0/1] MR2887: winegstreamer: Make sure threads are not waiting for event_cond object.
First we set the EOS state, so the wait_parser_stream_buffer function doesn't call pthread_cond_wait again. Then we must call pthread_cond_signal to make sure that no one is waiting for it, if we don't do that, there is the possibility of hanging wg_parser_disconnect at the free_stream call, because pthread_cond_destroy will hang when the cond object is being waited by other threads. Specifically this helps to fix a hang in some applications, specially Unreal Engine games when changing sources too fast in a MediaPlayer. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/2887
From: Santino Mazza <smazza(a)codeweavers.com> First we set the EOS state, so the wait_parser_stream_buffer function doesn't call pthread_cond_wait again. Then we must call pthread_cond_signal to make sure that no one is waiting for it, if we don't do that, there is the possibility of hanging wg_parser_disconnect at the free_stream call, because pthread_cond_destroy will hang when the cond object is being waited by other threads. Specifically this helps to fix a hang in some applications, specially Unreal Engine games when changing sources too fast in a MediaPlayer. --- dlls/winegstreamer/wg_parser.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index ef274b1dc27..b99ef9dbe31 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -1708,6 +1708,8 @@ static NTSTATUS wg_parser_disconnect(void *args) for (i = 0; i < parser->stream_count; ++i) { parser->streams[i]->flushing = true; + parser->streams[i]->eos = true; + pthread_cond_signal(&parser->streams[i]->event_cond); pthread_cond_signal(&parser->streams[i]->event_empty_cond); } pthread_mutex_unlock(&parser->mutex); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/2887
The intended API contract is that streaming threads can't still be running when we call wg_parser_destroy(). In quartz and wmvcore they should have been stopped already. From reading mfplat code it doesn't look like it should be possible to hit this case either: source_async_commands_Invoke() grabs the source cs and checks its state inside that cs; media_source_Shutdown() also grabs the cs and sets the state inside that CS. How exactly are you seeing this deadlock? What's the backtrace look like? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/2887#note_33610
Mmm, I just realized that the hangs happens when the game calls media_source_Shutdown and the source is in the running state. Like this ``` 0288:trace:mfplat:media_source_Shutdown 00000000117942F0 state 1. 0288:trace:mfplat:media_source_Shutdown returning wg_parser_disconnect 0288:trace:mfplat:media_source_Shutdown 00000000117942F0 state 4. 0134:trace:mfplat:media_source_Shutdown 0000000011B1EFD0 state 1. 0134:trace:mfplat:media_source_Shutdown returning wg_parser_disconnect 0134:trace:mfplat:media_source_Shutdown 0000000011B1EFD0 state 4. 0134:trace:mfplat:media_source_Shutdown 0000000001F28C00 state 1. 0134:trace:mfplat:media_source_Shutdown returning wg_parser_disconnect 0134:trace:mfplat:media_source_Shutdown 0000000001F28C00 state 4. 01f8:trace:mfplat:media_source_Shutdown 0000000011794370 state 3. 01f8:trace:mfplat:media_source_Shutdown returning wg_parser_disconnect 0218:trace:mfplat:media_source_Shutdown 0000000011B1EFD0 state 1. 0218:trace:mfplat:media_source_Shutdown returning wg_parser_disconnect 0218:trace:mfplat:media_source_Shutdown 0000000011B1EFD0 state 4. 01e8:trace:mfplat:media_source_Shutdown 000000007844FC50 state 1. 01e8:trace:mfplat:media_source_Shutdown returning wg_parser_disconnect 01e8:trace:mfplat:media_source_Shutdown 000000007844FC50 state 4. 021c:trace:mfplat:media_source_Shutdown 0000000001F28C00 state 1. 021c:trace:mfplat:media_source_Shutdown returning wg_parser_disconnect 021c:trace:mfplat:media_source_Shutdown 0000000001F28C00 state 4. 0200:trace:mfplat:media_source_Shutdown 0000000011794870 state 3. ``` Normally it calls Shutdown when the source is in the 1 state (Stopped), in that state it calls wg_parser_disconnect, which in turn calls free_stream. When it's in the 4 state (Shutdown) it doesn't do anything, but at the end it's in the 3 state (Running), and there it calls wg_parser_disconnect but never returns, because it hangs at free_stream. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/2887#note_33737
I've tried to reproduce the bug, but apprently if I call IMFMediaSource::Shutdown after the session starts in windows it will hang when trying to Close the session, but in wine it only crashes. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/2887#note_33739
This merge request was closed by Santino Mazza. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/2887
Already fixed in upstream. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/2887#note_35193
participants (3)
-
Santino Mazza -
Santino Mazza (@tati1454) -
Zebediah Figura (@zfigura)