Skip to content

Commit

Permalink
[d16-6] [appkit] Fix NSApplication with custom initialization (#7958)
Browse files Browse the repository at this point in the history
Custom initialization of Xamarin.Mac is tricky. You can easily start
using ObjC features before everything is ready / loaded into memory.

In contrast a _normal_ XM application, from an app bundle, already has a
lot of things loaded into memory when it starts to initialize.

This means that some things can work _by chance_ due to timing and that
semi-related (and correct) changes could affect your _lucky_ timings.

Such a semi-related change was a239fa9#diff-4aa19167162888aec0ccc2261a7ddbd3

In #7932 the attached code
```csharp
NSApplication.IgnoreMissingAssembliesDuringRegistration = false;
```
triggers the `.cctor` which means that `class_ptr` is initialized.

Note: That's not fully correct/safe since `Init` is not been called
but that's a different issue...

Anyway the dual calls that existed before was enough to hide the first
(which failed but triggered the rest of the native initialization).
That extra call made older XM version works (with attached code).

So in this (#7932) case our generated code
```csharp
static readonly IntPtr class_ptr = Class.GetHandle ("NSApplication");
```
happens too early. Now that cannot be changed because

* it's how .net `readonly` works
* existing/correct code depends on this
* it depends on native side (being loaded/initialized/ready)

but we can **add** to this and make `Init` safer to use by duplicating
the call _only if_ the original call had failed.

Of course the generated code has the `class_ptr` field as `readonly`...
```
error CS0198: A static readonly field cannot be assigned to (except in a static constructor or a variable initializer)
```
so we need to use reflection to achieve this (but that cost will occur
if the original initialization failed)

Fix #7932
  • Loading branch information
monojenkins authored Feb 22, 2020
1 parent 574008d commit ef273a5
Showing 1 changed file with 13 additions and 0 deletions.
13 changes: 13 additions & 0 deletions src/AppKit/NSApplication.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,23 @@ public static void Init ()
// But can affect child xbuild processes, so unset
Environment.SetEnvironmentVariable ("MONO_CFG_DIR", "");

// custom initialization might have happened before native NSApplication code was full ready to be queried
// as such it's possible that `class_ptr` might be empty and that will make things fails later
// reference: https://github.com/xamarin/xamarin-macios/issues/7932
if (class_ptr == IntPtr.Zero)
ResetHandle ();

// TODO:
// Install hook to register dynamically loaded assemblies
}

// separate method so it can be invoked without `Init` (if needed)
static void ResetHandle ()
{
// `class_ptr` is `readonly` so one can't simply do `class_ptr = Class.GetHandle ("NSApplication");`
typeof (NSApplication).GetField ("class_ptr", BindingFlags.Static | BindingFlags.NonPublic).SetValue (null, Class.GetHandle ("NSApplication"));
}

public static void InitDrawingBridge ()
{
FieldInfo UseCocoaDrawableField = Type.GetType ("System.Drawing.GDIPlus, System.Drawing").GetField ("UseCocoaDrawable", BindingFlags.Static | BindingFlags.Public);
Expand Down

5 comments on commit ef273a5

@xamarin-release-manager
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚧 Experimental DDFun pipeline

🔥 Device tests completed (Failed) on iOS-DDFun on Azure DevOps(iOS-DDFun) 🔥

Test results

14 tests failed, 136 tests passed.

Failed tests

  • monotouch-test/iOS Unified 64-bits - device/Debug: Failed
  • monotouch-test/iOS Unified 64-bits - device/AssemblyBuildTarget: dylib (debug): Failed
  • monotouch-test/iOS Unified 64-bits - device/AssemblyBuildTarget: SDK framework (debug): Failed
  • monotouch-test/iOS Unified 64-bits - device/AssemblyBuildTarget: dylib (debug, profiling): Failed
  • monotouch-test/iOS Unified 64-bits - device/AssemblyBuildTarget: SDK framework (debug, profiling): Failed
  • monotouch-test/iOS Unified 64-bits - device/Release: Failed
  • monotouch-test/iOS Unified 64-bits - device/AssemblyBuildTarget: SDK framework (release): Failed
  • monotouch-test/iOS Unified 64-bits - device/Debug (dynamic registrar): Failed
  • monotouch-test/iOS Unified 64-bits - device/Release (all optimizations): Failed
  • monotouch-test/iOS Unified 64-bits - device/Debug (all optimizations): Failed
  • monotouch-test/iOS Unified 64-bits - device/Debug: SGenConc: Failed
  • monotouch-test/iOS Unified 64-bits - device/Debug (interpreter): Failed
  • monotouch-test/iOS Unified 64-bits - device/Debug (interpreter -mscorlib): Failed
  • monotouch-test/iOS Unified 64-bits - device/Release (interpreter -mscorlib): Failed

@xamarin-release-manager
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Device tests passed on iOS on Azure DevOps(iOS): Html Report

🎉 All 150 tests passed 🎉

@xamarin-release-manager
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Build was (probably) aborted

🔥 Jenkins job (on internal Jenkins) failed in stage(s) 'Test run, Test run' 🔥

Build succeeded
✅ Packages:

API Diff (from stable)
API Diff (from PR only) (no change)
Generator Diff (no change)
🔥 Test run failed 🔥

Test results

4 tests failed, 179 tests passed.

Failed tests

  • xammac tests/Mac Modern/Debug: TimedOut (Execution timed out after 1200 seconds.)
  • xammac tests/Mac Modern/Debug: TimedOut (Execution timed out after 1200 seconds.)
  • xammac tests/Mac Modern/Release: TimedOut (Execution timed out after 1200 seconds.)
  • xammac tests/Mac Modern/Release: TimedOut (Execution timed out after 1200 seconds.)

@xamarin-release-manager
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔥 Device tests completed (Failed) on TvOS on Azure DevOps(TvOS): Html Report 🔥

Test results

14 tests failed, 136 tests passed.

Failed tests

  • monotouch-test/tvOS - device/Debug: TimedOut
  • monotouch-test/tvOS - device/AssemblyBuildTarget: dylib (debug): TimedOut
  • monotouch-test/tvOS - device/AssemblyBuildTarget: SDK framework (debug): TimedOut
  • monotouch-test/tvOS - device/AssemblyBuildTarget: dylib (debug, profiling): TimedOut
  • monotouch-test/tvOS - device/AssemblyBuildTarget: SDK framework (debug, profiling): TimedOut
  • monotouch-test/tvOS - device/Release: TimedOut
  • monotouch-test/tvOS - device/AssemblyBuildTarget: SDK framework (release): TimedOut
  • monotouch-test/tvOS - device/Debug (dynamic registrar): TimedOut
  • monotouch-test/tvOS - device/Release (all optimizations): TimedOut
  • monotouch-test/tvOS - device/Debug (all optimizations): TimedOut
  • monotouch-test/tvOS - device/Debug: SGenConc: TimedOut
  • monotouch-test/tvOS - device/Debug (interpreter): TimedOut
  • monotouch-test/tvOS - device/Debug (interpreter -mscorlib): TimedOut
  • monotouch-test/tvOS - device/Release (interpreter -mscorlib): TimedOut

@xamarin-release-manager
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔥 Device tests completed (Failed) on iOS32b on Azure DevOps(iOS32b): Html Report 🔥

Test results

# Test run in progress: Running: 1, RunQueued: 11, Succeeded: 128, Failed: 14, Ignored: 1100, Crashed: 1, TimedOut: 3, BuildFailure: 3

Failed tests

  • [xUnit] Mono BCL tests group 4/iOS Unified 32-bits - device/Debug: Failed
  • mscorlib Part 2/iOS Unified 32-bits - device/Debug: Failed
  • dont link/iOS Unified 32-bits - device/AssemblyBuildTarget: SDK framework (release): Crashed
  • [NUnit] Mono BCL tests group 2/iOS Unified 32-bits - device/Release: UseThumb: TimedOut
  • [xUnit] Mono BCL tests group 4/iOS Unified 32-bits - device/AssemblyBuildTarget: dylib (debug): Failed
  • [xUnit] Mono BCL tests group 4/iOS Unified 32-bits - device/AssemblyBuildTarget: SDK framework (debug): Failed
  • [xUnit] Mono BCL tests group 4/iOS Unified 32-bits - device/AssemblyBuildTarget: dylib (debug, profiling): Failed
  • [xUnit] Mono BCL tests group 4/iOS Unified 32-bits - device/AssemblyBuildTarget: SDK framework (debug, profiling): Failed
  • mscorlib Part 1/iOS Unified 32-bits - device/AssemblyBuildTarget: SDK framework (debug): TimedOut
  • mscorlib Part 1/iOS Unified 32-bits - device/AssemblyBuildTarget: dylib (debug, profiling): TimedOut
  • mscorlib Part 1/iOS Unified 32-bits - device/Release: BuildFailure
  • mscorlib Part 1/iOS Unified 32-bits - device/Release: UseThumb: BuildFailure
  • mscorlib Part 1/iOS Unified 32-bits - device/AssemblyBuildTarget: SDK framework (release): BuildFailure
  • mscorlib Part 2/iOS Unified 32-bits - device/AssemblyBuildTarget: dylib (debug): Failed
  • mscorlib Part 2/iOS Unified 32-bits - device/AssemblyBuildTarget: SDK framework (debug): Failed
  • mscorlib Part 2/iOS Unified 32-bits - device/AssemblyBuildTarget: dylib (debug, profiling): Failed
  • mscorlib Part 2/iOS Unified 32-bits - device/AssemblyBuildTarget: SDK framework (debug, profiling): Failed
  • mscorlib Part 2/iOS Unified 32-bits - device/Release: Failed
  • mscorlib Part 2/iOS Unified 32-bits - device/Release: UseThumb: Failed
  • mscorlib Part 2/iOS Unified 32-bits - device/AssemblyBuildTarget: SDK framework (release): Failed
  • mscorlib Part 2/iOS Unified 32-bits - device/Debug: SGenConc: Failed

Please sign in to comment.