Skip to content

Background Assets: fix EnsureLocalAvailability never completing on success - #127

Open
petarkarov wants to merge 1 commit into
apple:mainfrom
petarkarov:fix/backgroundassets-ensure-local-availability-completion
Open

petarkarov wants to merge 1 commit into
apple:mainfrom
petarkarov:fix/backgroundassets-ensure-local-availability-completion

Conversation

@petarkarov

Copy link
Copy Markdown
Contributor

Problem

AssetPackManager.EnsureLocalAvailabilityOfAssetPackAsync(...) and EnsureLocalAvailabilityOfAssetPacksAsync(...) never return when the download succeeds.

The native wrappers baw_assetpackmanager_assetpack_local_ensure, _local_ensure_update and _local_ensure_updatev only invoke the completion handler in the catch block. On success the handler is never called, so the C# side's SemaphoreSlim is never released. The await hangs forever and the AllocHGlobal'd context is leaked.

await AssetPackManager.EnsureLocalAvailabilityOfAssetPackAsync(pack);
// never reached once the pack has downloaded successfully

Failures are reported correctly. Only the success path is affected.

Separately, EnsureLocalAvailabilityOfAssetPacksAsync is declared async void, although its documentation says it returns a task. Callers can't await it or catch its errors.

Fix

  • AssetPackManager.swift: call completionHandler(.none, baw_res_kind_success, contextPointer) after ensureLocalAvailability returns, in all three local_ensure* functions.
  • Error.swift: add baw_err.none, a static empty error used as the unused error value on success. It's marked _static, so baw_err_deinit never tries to free it.
  • AssetPackManager.cs: change EnsureLocalAvailabilityOfAssetPacksAsync from async void to async Task, matching its doc comment and the single-pack versions.

The C# callback already handles baw_res_kind_success (it releases the semaphore and leaves the error unset), so no other C# changes are needed.

Notes

  • RemoveAssetPackAsync (baw_assetpackmanager_assetpack_remove) and ReconcilePreferredLanguages (baw_assetpackmanager_lang_reconcile) have the same missing success callback. They are left out to keep this PR focused, and I'm happy to fix them here or in a follow-up.

The native local_ensure* functions only invoked the completion handler
on failure, so on a successful download the C# side's semaphore was
never released: EnsureLocalAvailabilityOfAssetPack(s)Async hung forever
and leaked the marshalled context. Invoke the handler with
baw_res_kind_success once ensureLocalAvailability returns, using a new
static, empty baw_err.none as the unused error value.

Also make EnsureLocalAvailabilityOfAssetPacksAsync return Task instead
of void, as its documentation describes, so callers can await it and
catch its errors.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant