From 8ad5ea0cb166e408fabab2adfe65cb7aca1418fb Mon Sep 17 00:00:00 2001 From: reuk Date: Mon, 19 Oct 2020 12:10:45 +0100 Subject: [PATCH] FileChooser: Fix win32 threading bug The Win32NativeFileChooser was taking ownership of itself in its `Thread::run` implementation. This meant that sometimes the destructor of the file chooser thread would execute directly in `Thread::run`. Now, we explicitly transfer ownership into a function object which will run asynchronously on the main thread. This way, the file chooser thread will be stopped on the main thread. --- .../native/juce_win32_FileChooser.cpp | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/modules/juce_gui_basics/native/juce_win32_FileChooser.cpp b/modules/juce_gui_basics/native/juce_win32_FileChooser.cpp index 065d873e11..4a65f0f4ec 100644 --- a/modules/juce_gui_basics/native/juce_win32_FileChooser.cpp +++ b/modules/juce_gui_basics/native/juce_win32_FileChooser.cpp @@ -420,18 +420,33 @@ private: void run() override { + // We use a functor rather than a lambda here because + // we want to move ownership of the Ptr into the function + // object, and C++11 doesn't support general lambda capture + struct AsyncCallback + { + AsyncCallback (Ptr p, Array r) + : ptr (std::move (p)), + results (std::move (r)) {} + + void operator()() + { + ptr->results = std::move (results); + + if (ptr->owner != nullptr) + ptr->owner->exitModalState (ptr->results.size() > 0 ? 1 : 0); + } + + Ptr ptr; + Array results; + }; + // as long as the thread is running, don't delete this class Ptr safeThis (this); threadHasReference.signal(); auto r = openDialog (true); - MessageManager::callAsync ([safeThis, r] - { - safeThis->results = r; - - if (safeThis->owner != nullptr) - safeThis->owner->exitModalState (r.size() > 0 ? 1 : 0); - }); + MessageManager::callAsync (AsyncCallback (std::move (safeThis), std::move (r))); } static HashMap& getNativeDialogList()