From 94be23d5c2afc1d0c35456b54f62659c22eb7ed0 Mon Sep 17 00:00:00 2001 From: Harini Malothu Date: Thu, 18 Sep 2025 12:23:16 +0530 Subject: [PATCH 1/2] Fix INVALID_PARAMETER crash in ThreadPoolSchedulerWin::Post by adding null handle checks --- .../dispatchQueue/threadPoolScheduler_win.cpp | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/vnext/Mso/src/dispatchQueue/threadPoolScheduler_win.cpp b/vnext/Mso/src/dispatchQueue/threadPoolScheduler_win.cpp index 7fbeeb9f594..4892fa3a919 100644 --- a/vnext/Mso/src/dispatchQueue/threadPoolScheduler_win.cpp +++ b/vnext/Mso/src/dispatchQueue/threadPoolScheduler_win.cpp @@ -96,7 +96,11 @@ std::vector> ThreadPoolSchedulerWin::s_trackedThreadPoo ThreadPoolSchedulerWin::ThreadPoolSchedulerWin(uint32_t maxThreads) noexcept : m_threadPoolWork{::CreateThreadpoolWork(WorkCallback, this, nullptr), ThreadPoolWorkDeleter{}}, m_maxThreads{maxThreads == 0 ? MaxConcurrentThreads : maxThreads} { - TrackThreadPoolWork(m_threadPoolWork); + // Validate that thread pool work was created successfully + // If it failed, m_threadPoolWork will be null and Post() will handle this gracefully + if (m_threadPoolWork) { + TrackThreadPoolWork(m_threadPoolWork); + } } ThreadPoolSchedulerWin::~ThreadPoolSchedulerWin() noexcept { @@ -153,7 +157,14 @@ void ThreadPoolSchedulerWin::Post() noexcept { } while (!m_usedThreads.compare_exchange_weak( usedThreads, usedThreads + 1, std::memory_order_release, std::memory_order_relaxed)); - ::SubmitThreadpoolWork(m_threadPoolWork.get()); + // Guard against calling SubmitThreadpoolWork with a null or invalid handle + // This can happen during destruction or if CreateThreadpoolWork failed + if (m_threadPoolWork && m_threadPoolWork.get()) { + ::SubmitThreadpoolWork(m_threadPoolWork.get()); + } else { + // If we can't submit work, decrement the used threads counter to maintain consistency + --m_usedThreads; + } } void ThreadPoolSchedulerWin::Shutdown() noexcept { @@ -163,7 +174,10 @@ void ThreadPoolSchedulerWin::Shutdown() noexcept { void ThreadPoolSchedulerWin::AwaitTermination() noexcept { // Avoid deadlock when the dispatch queue and ThreadPoolSchedulerWin are released from inside of a task. if (ThreadPoolSchedulerWinContext::CurrentScheduler() != this) { - ::WaitForThreadpoolWorkCallbacks(m_threadPoolWork.get(), false); + // Only wait for callbacks if we have a valid thread pool work handle + if (m_threadPoolWork && m_threadPoolWork.get()) { + ::WaitForThreadpoolWorkCallbacks(m_threadPoolWork.get(), false); + } } } @@ -184,7 +198,10 @@ void ThreadPoolSchedulerWin::WaitForThreadPoolWorkCompletion() noexcept { tpWorkToTrack = std::move(s_trackedThreadPoolWork); } for (std::shared_ptr &tpWork : tpWorkToTrack) { - ::WaitForThreadpoolWorkCallbacks(tpWork.get(), false); + // Only wait for callbacks if we have a valid thread pool work handle + if (tpWork && tpWork.get()) { + ::WaitForThreadpoolWorkCallbacks(tpWork.get(), false); + } } } From ab0746d0e5f9179547e0197fbb25779c7efe1f57 Mon Sep 17 00:00:00 2001 From: Harini Malothu Date: Thu, 18 Sep 2025 12:34:52 +0530 Subject: [PATCH 2/2] Change files --- ...ative-windows-2ca15ad4-7aee-4465-8b12-a4692bba16b1.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 change/react-native-windows-2ca15ad4-7aee-4465-8b12-a4692bba16b1.json diff --git a/change/react-native-windows-2ca15ad4-7aee-4465-8b12-a4692bba16b1.json b/change/react-native-windows-2ca15ad4-7aee-4465-8b12-a4692bba16b1.json new file mode 100644 index 00000000000..a8682381b5d --- /dev/null +++ b/change/react-native-windows-2ca15ad4-7aee-4465-8b12-a4692bba16b1.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "Fix INVALID_PARAMETER crash in ThreadPoolSchedulerWin::Post by adding null handle checks", + "packageName": "react-native-windows", + "email": "hmalothu@microsoft.com", + "dependentChangeType": "patch" +}