diff options
Diffstat (limited to 'media/libcubeb/bug1302231_emergency_bailout.patch')
-rw-r--r-- | media/libcubeb/bug1302231_emergency_bailout.patch | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/media/libcubeb/bug1302231_emergency_bailout.patch b/media/libcubeb/bug1302231_emergency_bailout.patch new file mode 100644 index 000000000..82152c23f --- /dev/null +++ b/media/libcubeb/bug1302231_emergency_bailout.patch @@ -0,0 +1,140 @@ +From 37ce70d4400a2ab6b59ee432b41d4ffcc9d136ff Mon Sep 17 00:00:00 2001 +From: Paul Adenot <paul@paul.cx> +Date: Thu, 10 Nov 2016 21:45:14 +0100 +Subject: [PATCH] Bail out safely from the rendering loop if we could not join + the rendering thread in time (#187) + +Bail out safely from the rendering loop if we could not join the rendering thread in time. +--- + src/cubeb_wasapi.cpp | 41 ++++++++++++++++++++++++++++++++++++----- + 1 file changed, 36 insertions(+), 5 deletions(-) + +diff --git a/src/cubeb_wasapi.cpp b/src/cubeb_wasapi.cpp +index 9e689b9..519d5ca 100644 +--- a/src/cubeb_wasapi.cpp ++++ b/src/cubeb_wasapi.cpp +@@ -22,6 +22,7 @@ + #include <algorithm> + #include <memory> + #include <limits> ++#include <atomic> + + #include "cubeb/cubeb.h" + #include "cubeb-internal.h" +@@ -220,9 +221,11 @@ struct cubeb_stream + float volume; + /* True if the stream is draining. */ + bool draining; ++ /* True when we've destroyed the stream. This pointer is leaked on stream ++ * destruction if we could not join the thread. */ ++ std::atomic<std::atomic<bool>*> emergency_bailout; + }; + +- + class wasapi_endpoint_notification_client : public IMMNotificationClient + { + public: +@@ -781,6 +784,7 @@ static unsigned int __stdcall + wasapi_stream_render_loop(LPVOID stream) + { + cubeb_stream * stm = static_cast<cubeb_stream *>(stream); ++ std::atomic<bool> * emergency_bailout = stm->emergency_bailout; + + bool is_playing = true; + HANDLE wait_array[4] = { +@@ -820,6 +824,10 @@ wasapi_stream_render_loop(LPVOID stream) + wait_array, + FALSE, + 1000); ++ if (*emergency_bailout) { ++ delete emergency_bailout; ++ return 0; ++ } + if (waitResult != WAIT_TIMEOUT) { + timeout_count = 0; + } +@@ -1134,12 +1142,13 @@ int wasapi_init(cubeb ** context, char const * context_name) + } + + namespace { +-void stop_and_join_render_thread(cubeb_stream * stm) ++bool stop_and_join_render_thread(cubeb_stream * stm) + { ++ bool rv = true; + LOG("Stop and join render thread."); + if (!stm->thread) { + LOG("No thread present."); +- return; ++ return true; + } + + BOOL ok = SetEvent(stm->shutdown_event); +@@ -1153,11 +1162,15 @@ void stop_and_join_render_thread(cubeb_stream * stm) + if (r == WAIT_TIMEOUT) { + /* Something weird happened, leak the thread and continue the shutdown + * process. */ ++ *(stm->emergency_bailout) = true; + LOG("Destroy WaitForSingleObject on thread timed out," + " leaking the thread: %d", GetLastError()); ++ rv = false; + } + if (r == WAIT_FAILED) { ++ *(stm->emergency_bailout) = true; + LOG("Destroy WaitForSingleObject on thread failed: %d", GetLastError()); ++ rv = false; + } + + LOG("Closing thread."); +@@ -1167,6 +1180,8 @@ void stop_and_join_render_thread(cubeb_stream * stm) + + CloseHandle(stm->shutdown_event); + stm->shutdown_event = 0; ++ ++ return rv; + } + + void wasapi_destroy(cubeb * context) +@@ -1775,7 +1790,16 @@ void wasapi_stream_destroy(cubeb_stream * stm) + { + XASSERT(stm); + +- stop_and_join_render_thread(stm); ++ // Only free stm->emergency_bailout if we could not join the thread. ++ // If we could not join the thread, stm->emergency_bailout is true ++ // and is still alive until the thread wakes up and exits cleanly. ++ if (stop_and_join_render_thread(stm)) { ++ delete stm->emergency_bailout.load(); ++ stm->emergency_bailout = nullptr; ++ } else { ++ // If we're leaking, it must be that this is true. ++ assert(*(stm->emergency_bailout)); ++ } + + unregister_notification_client(stm); + +@@ -1844,6 +1868,8 @@ int wasapi_stream_start(cubeb_stream * stm) + + auto_lock lock(stm->stream_reset_lock); + ++ stm->emergency_bailout = new std::atomic<bool>(false); ++ + if (stm->output_client) { + int rv = stream_start_one_side(stm, OUTPUT); + if (rv != CUBEB_OK) { +@@ -1903,7 +1929,12 @@ int wasapi_stream_stop(cubeb_stream * stm) + stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STOPPED); + } + +- stop_and_join_render_thread(stm); ++ if (stop_and_join_render_thread(stm)) { ++ if (stm->emergency_bailout.load()) { ++ delete stm->emergency_bailout.load(); ++ stm->emergency_bailout = nullptr; ++ } ++ } + + return CUBEB_OK; + } +-- +2.7.4 + |