Skip to content

[NativeAOT][iOS] App Hangs/Freezes with Static Virtual Properties in Interfaces on .NET 9 #113423

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
vyacheslav-volkov opened this issue Mar 12, 2025 · 4 comments

Comments

@vyacheslav-volkov
Copy link

vyacheslav-volkov commented Mar 12, 2025

Description

When migrating an iOS project from .NET 8 NativeAOT to .NET 9 NativeAOT, the application hangs (appears to deadlock) without throwing any exceptions or generating error logs. After significant troubleshooting, the issue was traced to the use of a static virtual property within an interface. In .NET 9, the following simplified code consistently reproduces the hang, whereas it works as expected under .NET 8.

[Register("AppDelegate")]
public class AppDelegate : UIApplicationDelegate
{
    public override UIWindow? Window { get; set; }

    public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
    {
        Window = new UIWindow(UIScreen.MainScreen.Bounds);
        Window.RootViewController = new MainController();
        Window.MakeKeyAndVisible();
        return true;
    }
}

public class Test : ITestInterface<Test>
{
    public static bool Flag => true;
}

public interface ITestInterface<in TRequest>
    where TRequest : ITestInterface<TRequest>
{
    protected static virtual bool Flag => false;

    public static virtual void Invoke(TRequest request)
    {
        if (TRequest.Flag)
            Console.WriteLine("flag=true");
    }
}

public class MainController : UIViewController
{
    public override void ViewDidLoad()
    {
        base.ViewDidLoad();
        Console.WriteLine("Begin Invoke");
        Invoke(new Test());
        Console.WriteLine("End Invoke");
    }

    public static void Invoke<TRequest>(TRequest request)
        where TRequest : ITestInterface<TRequest> 
            => TRequest.Invoke(request);
}

Reproduction Steps

  • Create a new iOS project targeting .NET 9 with the code from the issue.
  • Run the application in NativeAOT mode

Expected behavior

The application should start normally and display the log messages:

Begin Invoke
flag=true
End Invoke

Actual behavior

The application hangs (freezes) with no console output beyond Begin Invoke, and no exceptions are thrown. Execution never reaches flag=true or End Invoke.

Regression?

This issue does not appear on .NET 8; it only occurs after upgrading to .NET 9.

Known Workarounds

If I change the property to abstract, it works.
If I change the property to method protected static virtual bool GetFlag() => false;, it works.

Configuration

No response

Other information

No response

@ghost ghost added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Mar 12, 2025
@jkotas jkotas added os-ios Apple iOS and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Mar 12, 2025
Copy link
Contributor

Tagging subscribers to 'os-ios': @vitek-karas, @kotlarmilos, @ivanpovazan, @steveisok, @akoeplinger
See info in area-owners.md if you want to be subscribed.

Copy link
Contributor

Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas
See info in area-owners.md if you want to be subscribed.

@MichalStrehovsky
Copy link
Member

This looks like another instance of #110932 that we fixed in #111030; doesn't repro with .NET 10 builds.

Non-apple repro:

MainController ctrl = new MainController();

ctrl.ViewDidLoad();

public class Test : ITestInterface<Test>
{
    public static bool Flag => true;
}

public interface ITestInterface<in TRequest>
    where TRequest : ITestInterface<TRequest>
{
    protected static virtual bool Flag => false;

    public static virtual void Invoke(TRequest request)
    {
        if (TRequest.Flag)
            Console.WriteLine("flag=true");
    }
}

public class MainController
{
    public void ViewDidLoad()
    {
        Console.WriteLine("Begin Invoke");
        Invoke(new Test());
        Console.WriteLine("End Invoke");
    }

    public static void Invoke<TRequest>(TRequest request)
        where TRequest : ITestInterface<TRequest>
            => TRequest.Invoke(request);
}

@MichalStrehovsky
Copy link
Member

Fix was merged to 9.0 staging branch in #113462.

@github-actions github-actions bot locked and limited conversation to collaborators Apr 26, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
Archived in project
Development

No branches or pull requests

3 participants