From b0f36812f785e6ce8f176f5608d1ad091113f7f0 Mon Sep 17 00:00:00 2001 From: Godly Alias Date: Wed, 27 May 2026 00:26:52 +0500 Subject: [PATCH] Fix UniversalBGTask crash and gracefully handle CoCreateInstance failures UniversalBGTask::Task::Run could crash backgroundTaskHost.exe in two scenarios: 1. When LocalSettings has no entry for the task's TaskId, ApplicationDataContainerSettings::Lookup returns S_OK with a null IInspectable. The subsequent unbox_value then throws hresult_no_interface, and because the broker treats the failure as transient it re-fires the trigger forever. 2. When CoCreateInstance fails (e.g. the COM class isn't registered against the package), the wrapped THROW_IF_FAILED produced no diagnostic context. Fix: - If LocalSettings.Lookup returns null, log via wil and unregister the orphaned OS task so the broker stops re-firing it. - If CoCreateInstance fails, log the HR with the CLSID and TaskId and return cleanly. The registration is left in place so the broker can retry on the next trigger in case the failure is transient. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Task.cpp | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/dev/WindowsAppRuntime_UniversalBGTaskDLL/Task.cpp b/dev/WindowsAppRuntime_UniversalBGTaskDLL/Task.cpp index c02c7c12af..488889a28b 100644 --- a/dev/WindowsAppRuntime_UniversalBGTaskDLL/Task.cpp +++ b/dev/WindowsAppRuntime_UniversalBGTaskDLL/Task.cpp @@ -20,9 +20,45 @@ namespace winrt::Microsoft::Windows::ApplicationModel::Background::UniversalBGTa ApplicationDataContainer localSettings = ApplicationData::Current().LocalSettings(); auto values = localSettings.Values(); auto lookupobj = values.Lookup(lookupStr); + + // LocalSettings.Lookup returns S_OK with a null IInspectable when the key is missing. + // Treat this as an orphaned OS task registration: log and unregister so the broker + // stops re-firing it. Returning cleanly is preferred over throwing because thrown + // exceptions are treated as transient by the broker and would be retried indefinitely. + if (!lookupobj) + { + LOG_HR_MSG( + HRESULT_FROM_WIN32(ERROR_NOT_FOUND), + "UniversalBGTask: no CLSID stored in LocalSettings for TaskId='%ls'. Unregistering orphaned task.", + lookupStr.c_str()); + try + { + taskInstance.Task().Unregister(true); + } + CATCH_LOG_MSG("UniversalBGTask: failed to unregister orphaned task TaskId='%ls'.", lookupStr.c_str()); + return; + } + winrt::guid comClsId = winrt::unbox_value(lookupobj); - THROW_IF_FAILED(CoCreateInstance(comClsId, nullptr, CLSCTX_LOCAL_SERVER, winrt::guid_of(), winrt::put_abi(m_bgTask))); + // CoCreateInstance can fail when the COM class isn't registered, the stored CLSID is + // GUID_NULL, or the impl doesn't expose IBackgroundTask. Log the HR with the CLSID + // for diagnostics and return; do not unregister, since the failure may be transient. + wchar_t comClsIdStr[40]{}; + ::StringFromGUID2(comClsId, comClsIdStr, ARRAYSIZE(comClsIdStr)); + HRESULT coCreateHr = CoCreateInstance(comClsId, nullptr, CLSCTX_LOCAL_SERVER, + winrt::guid_of(), + winrt::put_abi(m_bgTask)); + if (FAILED(coCreateHr)) + { + LOG_HR_MSG( + coCreateHr, + "UniversalBGTask: CoCreateInstance failed for CLSID=%ls referenced by TaskId='%ls'.", + comClsIdStr, + lookupStr.c_str()); + return; + } + m_bgTask.Run(taskInstance); } }