Skip to content

[WIP] Fix thread safety in TrimmableTypeMap.Initialize#11049

Draft
Copilot wants to merge 2 commits intomainfrom
copilot/fix-thread-safety-in-trimmabletypemap
Draft

[WIP] Fix thread safety in TrimmableTypeMap.Initialize#11049
Copilot wants to merge 2 commits intomainfrom
copilot/fix-thread-safety-in-trimmabletypemap

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 30, 2026

Thanks for asking me to work on this. I will get started on it and keep this PR's description up to date as I form a plan and make progress.


This section details on the original issue you should resolve

<issue_title>[TrimmableTypeMap] Fix thread safety in TrimmableTypeMap.Initialize()</issue_title>
<issue_description>Part of #10788

Problem

TrimmableTypeMap.Initialize() has a race condition. The Interlocked.CompareExchange correctly ensures only one instance wins the singleton slot, but the losing thread still proceeds to call RegisterBootstrapNativeMethod():

// TrimmableTypeMap.cs:41-48
internal static void Initialize()
{
    var instance = new TrimmableTypeMap();
    var previous = Interlocked.CompareExchange(ref s_instance, instance, null);
    Debug.Assert(previous is null, "TrimmableTypeMap must only be created once.");
    instance.RegisterBootstrapNativeMethod();  // runs even if CompareExchange lost
}

If two threads race on Initialize():

  1. Both create a TrimmableTypeMap instance (expensive — scans type map attributes)
  2. Only one wins the CompareExchange
  3. Both call RegisterBootstrapNativeMethod() — the losing thread registers on its discarded instance, which is a no-op, but it still creates JNI types and calls RegisterNatives unnecessarily

Fix

Add an early return guard after the CompareExchange:

internal static void Initialize()
{
    var instance = new TrimmableTypeMap();
    var previous = Interlocked.CompareExchange(ref s_instance, instance, null);
    if (previous is not null)
        return;
    instance.RegisterBootstrapNativeMethod();
}

Impact

Low — Initialize() is typically called once during startup. But the fix is trivial and prevents unnecessary work + potential double JNI registration.</issue_description>

Comments on the Issue (you are @copilot in this section)

@simonrozsival
Copy link
Copy Markdown
Member

@copilot try again

Agent-Logs-Url: https://github.com/dotnet/android/sessions/cb7028a6-408a-410f-9e71-a8d53aa9c2ec

Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>
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.

[TrimmableTypeMap] Fix thread safety in TrimmableTypeMap.Initialize()

2 participants