Skip to content

[browser][mt] Awaiting a Task returned by a [JSImport] method sometimes causes a deadlock #106788

@MackinnonBuck

Description

@MackinnonBuck

Description

When <WasmEnableThreads> is set to true, awaiting a Task returned by a [JSImport] method may cause a deadlock, even if the associated JS Promise is just a Promise.resolve().

This is likely the cause of the following test failures we've been seeing in dotnet/aspnetcore:

When I repro'd the failures locally, the test app was deadlocking in an interop call made by the framework here.

However, a much simpler scenario can reproduce the same issue. Here's some of the code from my minimal repro project:

using System.Runtime.InteropServices.JavaScript;
using System.Threading.Tasks;

JS.Log("Started...");
await JS.GetEmptyPromiseAsync();
JS.Log("Complete, reloading...");
JS.Reload();

partial class JS
{
    [JSImport("log", "main.js")]
    internal static partial void Log(string message);

    [JSImport("getEmptyPromise", "main.js")]
    internal static partial Task GetEmptyPromiseAsync();

    [JSImport("globalThis.location.reload")]
    internal static partial void Reload();
}

This repeatedly reloads the page until the deadlock occurs. On my machine, the deadlock happens within ~10 refreshes.

Reproduction Steps

  1. Download the latest .NET 9 Preview 7 build from https://github.com/dotnet/sdk/blob/main/documentation/package-table.md
  2. Clone https://github.com/MackinnonBuck/dotnet-wasm-repro
  3. From the root of the repro project, run the following:
    • dotnet workload install wasm-tools --include-previews
    • dotnet workload install wasm-experimental --include-previews
    • dotnet tool install dotnet-serve
    • dotnet publish
  4. From the wwwroot folder in the published output, run:
    • dotnet serve -h "Cross-Origin-Embedder-Policy:require-corp" -h "Cross-Origin-Opener-Policy:same-origin"
  5. Open the outputted URL in any web browser
  6. Observe the deadlock:
    • The page will repeatedly refresh until the deadlock occurs
    • When the deadlock happens, the page will look something like this:
      image

Expected behavior

A deadlock does not happen, and the webpage continues to refresh indefinitely.

Actual behavior

The page freezes within ~10 page reloads.

Regression?

Unsure - I unfortunately wasn't able to get the repro to run on a .NET 8 TFM and SDK.

Known Workarounds

No response

Configuration

.NET SDK:

  • Version: 9.0.100-preview.7.24407.12
  • Commit: d672b8a045

OS

Windows 11 Enterprise 23H2

Architecture

x64

Do you know whether it is specific to that configuration?

No

Which web browser(s) do you see this issue in?

I was able to repro this in:

  • Microsoft Edge
  • Google Chrome
  • Mozilla Firefox

Other information

No response

Metadata

Metadata

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions