Handle managed exceptions a bit better when we know there won't be any other
managed frames further up the stack (such as in the main method). In this
case, there's no use in trying to convert the managed exception into an
Objective-C exception, because we already know the process will be terminated.
Instead just print the exception to stderr, and abort immediately.
This means we'll actually get some useful information printed to stderr.
Resolves#14285
1. Make sure `libextension-dotnet.a` gets built, and with the `-DEXTENSION` flag.
2. Make sure `libextension-dotnet.a` gets included in the package alongside `libxamarin-dotnet.a`
3. At build time, make sure to link with the correct lib[tv]extension-dotnet.a library depending when we need to.
4. Add some tests.
Co-authored-by: Eric Sink <eric@Erics-MacBook-Pro.local>
Co-authored-by: Manuel de la Pena <mandel@microsoft.com>
Co-authored-by: Rolf Bjarne Kvinge <rolf@xamarin.com>
If we try to process any exceptions, we'll throw an Objective-C exception,
which will likely be unhandled because we're pretty much at the top of the
stack, and when we handle this Objective-C exception we'll try to convert it
into a managed exception and throw that, and since there are no managed frames
on the stack we'll end up converting it to an Objective-C exception, which
we'll try to throw, and so on, eventually running into a stack overflow.
This is unnecessary, so just abort directly.
* We now create a tracking GCHandle for all NSObjects, not only the toggled ones.
CoreCLR will notify us when a tracked GCHandle's target enters finalization, and
we need to be notified for all NSObjects, not just the toggled ones.
* Augment the tracking callback to know about non-toggled objects, and in that
case report that the tracking GCHandle is a weak GCHandle.
* There's no need to store the tracking GCHandle in a field in the NSObject instance,
since we store it in our runtime object_map.
* Remove one place where we set the InFinalizerQueue flag, since it's no longer
required there (this reverts a previous attempt at fixing this problem - 0622ae4af2)
- we only set the InFinalizerQueue flag in the xamarin_coreclr_reference_tracking_tracked_object_entered_finalization
callback now.
* Update a few comments accordingly.
Partial fix for https://github.com/xamarin/xamarin-macios/issues/13531.
Fixes https://github.com/xamarin/xamarin-macios/issues/13921 (again).
We were trying to call the 'retain' and 'autorelease' selectors on objects
that weren't NSObjects when returning them from function calls. For some
unfathomable reason that has worked until now, but I started running into this
problem with other (unrelated) changes, so it needs to be fixed.
The fix is to not call the 'retain' and 'autorelease' selectors on
NativeObjects, instead call into managed code to either call the Retain method
on the managed NativeObject (if we're supposed to retain the return value), or
if we have to autorelease the return value, then check first if the input is
an NSObject, and only then call retain+autorelease.
* Remove ObjCRuntime.nfloat (in favor of System.Runtime.InteropServices.NFloat).
* Automatically add a reference to the System.Runtime.InteropServices.Internal
package, so that developers get the new NFloat API (with operators) we've
added post .NET 6 (but don't do this for .NET 7).
* Automatically add a global using alias for
System.Runtime.InteropServices.NFloat -> nfloat. This is not behind the
usual `ImplicitUsings` condition our other implicit usings are, because
they're off by default for existing projects, and the main target for the
global using alias for nfloat is upgraded projects.
* Automatically generate a global using alias (like above) in the generator
for all code the generator compiles.
* Update xtro entries to reference System.Runtime.InteropServices.NFloat
instead of ObjCRuntime.nfloat.
* Add a workaround for a hopefully temporary issue with .NET/CoreCLR where the
wrong runtime pack is selected otherwise (without the new NFloat API, so
nothing works at runtime).
Ref: https://github.com/xamarin/xamarin-macios/issues/13087
This fixes an issue where the build would continue if the server in question
serves an error page (and eventually fail with weird errors because the error
page wouldn't be valid C code).
Rename our product assemblies to:
* Microsoft.iOS.dll
* Microsoft.tvOS.dll
* Microsoft.macOS.dll
* Microsoft.MacCatalyst.dll
This makes it easy to distinguish between legacy Xamarin and .NET whenever the
product assembly is mentioned, and I've also chosen the platform part of the
name to match how the platforms are named elsewhere (this also makes it
possible to simplify our build logic, since we can remove a lot of special
casing).
Fixes https://github.com/xamarin/xamarin-macios/issues/13748.
* Propagate the IsAppExtension variable correctly.
* Don't try to call mono_domain_set_config for app extensions in .NET.
It doesn't look like it's needed, and it also immediately aborts anyway, so
if it turns out to be needed, another solution would have to be implemented.
Fixes https://github.com/xamarin/xamarin-macios/issues/13742.
fixes#13160
- remove unused types
- use System.Numerics when possible
- move own created types from OpenTK namespace to CoreGraphics
- create missing types in CoreGraphics namespace
Co-authored-by: Rolf Bjarne Kvinge <rolf@xamarin.com>
When exception marshalling was originally implemented, for backwards
compatibility concerns it was only turned on by default for platforms that
really needed it (watchOS).
However, exception marshalling is by far the safest option, so in .NET we're
enabling it by default for all platforms (it's still possible to disable it
for those who wants to).
Ref: https://docs.microsoft.com/en-us/xamarin/ios/platform/exception-marshaling
* Make Runtime.Arch a readonly field.
* Tell the AOT compiler Runtime.Arch is a constant value.
* Tell the linker to stub out the method we use to fetch the current
architecture from native code (it turned out a bit complicated to set the
Arch field when it's readonly - the solution I came up with was to call a
P/Invoke).
Test case (size of the main executable): link all (debug)
* Before: 33.522.704 bytes
* After: 33.506.112 bytes
* Difference: -16.592 bytes (-0.05 %)
There were no size differences in release mode, nor were there any size
differences in the "don't link" test, neither for debug nor release mode.
Fixes https://github.com/xamarin/xamarin-macios/issues/5518.
This makes diagnosing what happens much easier in some cases.
Exhibit A, pre fix:
*** Terminating app due to uncaught exception 'ObjCRuntime.RuntimeException', reason: 'Failed to lookup the required marshalling information.
Additional information:
Selector: conformsToProtocol:
Type: ViewController
Exhibit B, post fix:
*** Terminating app due to uncaught exception 'ObjCRuntime.RuntimeException', reason: 'Failed to lookup the required marshalling information.
Additional information:
Selector: conformsToProtocol:
Type: ViewController
(ObjCRuntime.RuntimeException)
Failed to get the 'this' instance in a method call to templ.ViewController.InvokeConformsToProtocol. (ObjCRuntime.RuntimeException)
at Registrar.DynamicRegistrar.GetMethodDescriptionAndObject(Type type, IntPtr selector, Boolean is_static, IntPtr obj, IntPtr& mthis, IntPtr desc)
at ObjCRuntime.Runtime.GetMethodAndObjectForSelector(IntPtr klass, IntPtr sel, Boolean is_static, IntPtr obj, IntPtr& mthis, IntPtr desc)
at ObjCRuntime.Runtime.get_method_and_object_for_selector(IntPtr cls, IntPtr sel, Boolean is_static, IntPtr obj, IntPtr& mthis, IntPtr desc, IntPtr& exception_gchandle)
Failed to marshal the Objective-C object 0x7f813fd2f470 (type: ViewController). Could not find an existing managed instance for this object, nor was it possible to create a new managed instance (because the type 'templ.ViewController' does not have a constructor that takes one NativeHandle argument). (ObjCRuntime.RuntimeException)
at ObjCRuntime.Runtime.MissingCtor(IntPtr ptr, IntPtr klass, Type type, MissingCtorResolution resolution)
at ObjCRuntime.Runtime.ConstructNSObject[T](IntPtr ptr, Type type, MissingCtorResolution missingCtorResolution)
at ObjCRuntime.Runtime.ConstructNSObject(IntPtr ptr, IntPtr klass, MissingCtorResolution missingCtorResolution)
at ObjCRuntime.Runtime.GetNSObject(IntPtr ptr, MissingCtorResolution missingCtorResolution, Boolean evenInFinalizerQueue)
at Registrar.DynamicRegistrar.GetMethodDescriptionAndObject(Type type, IntPtr selector, Boolean is_static, IntPtr obj, IntPtr& mthis, IntPtr desc)
It does exactly what you'd think it does: nothing helpful at all.
Make sure to use a GCHandle that's alive instead.
Output before fix:
Xamarin.Mac: Processing managed exception for exception marshalling (mode: 2):
Failed to print exception: System.NullReferenceException: Object reference not set to an instance of an object.
at ObjCRuntime.Runtime.PrintException(Exception exc, Boolean isInnerException, StringBuilder sb)
at ObjCRuntime.Runtime.PrintAllExceptions(IntPtr exception_gchandle)
Output after fix:
Xamarin.Mac: Processing managed exception for exception marshalling (mode: 2):
Failed to lookup the required marshalling information.
Additional information:
Selector: conformsToProtocol:
Type: ViewController
(ObjCRuntime.RuntimeException)
Failed to get the 'this' instance in a method call to templ.ViewController.InvokeConformsToProtocol. (ObjCRuntime.RuntimeException)
at Registrar.DynamicRegistrar.GetMethodDescriptionAndObject(Type type, IntPtr selector, Boolean is_static, IntPtr obj, IntPtr& mthis, IntPtr desc)
at ObjCRuntime.Runtime.GetMethodAndObjectForSelector(IntPtr klass, IntPtr sel, Boolean is_static, IntPtr obj, IntPtr& mthis, IntPtr desc)
at ObjCRuntime.Runtime.get_method_and_object_for_selector(IntPtr cls, IntPtr sel, Boolean is_static, IntPtr obj, IntPtr& mthis, IntPtr desc, IntPtr& exception_gchandle)
Failed to marshal the Objective-C object 0x7f89e6c2a2a0 (type: ViewController). Could not find an existing managed instance for this object, nor was it possible to create a new managed instance (because the type 'templ.ViewController' does not have a constructor that takes one NativeHandle argument). (ObjCRuntime.RuntimeException)
at ObjCRuntime.Runtime.MissingCtor(IntPtr ptr, IntPtr klass, Type type, MissingCtorResolution resolution)
at ObjCRuntime.Runtime.ConstructNSObject[T](IntPtr ptr, Type type, MissingCtorResolution missingCtorResolution)
at ObjCRuntime.Runtime.ConstructNSObject(IntPtr ptr, IntPtr klass, MissingCtorResolution missingCtorResolution)
at ObjCRuntime.Runtime.GetNSObject(IntPtr ptr, MissingCtorResolution missingCtorResolution, Boolean evenInFinalizerQueue)
at Registrar.DynamicRegistrar.GetMethodDescriptionAndObject(Type type, IntPtr selector, Boolean is_static, IntPtr obj, IntPtr& mthis, IntPtr desc)
* Use 'ObjCException' instead of 'MonoTouchException' as the managed exception
type wrapping an NSException for all platforms in .NET (that was already the
case for macOS, so no change there).
* Make the ObjCException class behave like the MonoTouchException class does.
* Move the ObjCException type to the ObjCRuntime namespace in .NET.
Fixes https://github.com/xamarin/xamarin-macios/issues/13855.
Co-authored-by: TJ Lambert <50846373+tj-devel709@users.noreply.github.com>
This means using NativeHandle in numerous signatures, as well as adding a few .NET-specific
signatures (because sometimes the IntPtr version would still be needed).
This makes it easier to iterate over all the *_SDK_VERSION variables in
template code, because they're all named using the standard platform names we
use elsewhere.
* [generator] Use '[U]IntPtr' in the P/Invoke signature for native enums.
* Use '[U]IntPtr' as the parameter type in the P/Invoke signature for native enum
parameters.
* Use '[U]IntPtr' in the P/Invoke method name for native enum parameters.
* Add an explicit conversion from UIntPtr to nuint (like we already have from IntPtr
to nint).
This makes the code identical between .NET and legacy Xamarin when using C# n[u]ints,
because those are really [U]IntPtrs.
* Use IntPtr/UIntPtr for all nint/nuint types in P/Invokes, not only native enums.
* Add a few more casts
Fixes these generator tests:
* GeneratorTests.BGenTests.FieldEnumTests
* GeneratorTests.BGenTests.NativeEnum
* [registrar] Handle UIntPtr like we do IntPtr.
Fixes this error in numerous tests:
error MT4169: Failed to generate a P/Invoke wrapper for objc_msgSend(System.IntPtr,System.IntPtr): The registrar cannot build a signature for type `System.Void' in method `ObjCRuntime.Messaging.objc_msgSend`.
* [NativeTypes] Make IntPtr and UIntPtr behave the same.
This fixes an issue where the linked output for a 32-bit mscorlib.dll and a
64-bit mscorlib.dll would be different, because different explicit operators
for UIntPtr would be kept.
The fix works because the conversion operators for nuint will not use
UIntPtr's explicit conversion operators anymore, it will just operate on plain
memory instead.
The deadlock goes like this:
1. Thread A holds the framework_peer_release_lock lock, and tries to lock the
refcount_mutex lock.
2. Thread B holds the refcount_mutex, and is waiting for the GC to complete
3. Thread C is trying to lock the framework_peer_release_lock while running
the GC.
The fix is in thread A, by not doing anything at all with the
framework_peer_release_lock lock locked.
The code contains extensive comments explaining the situation and the solution.
Fixes https://github.com/xamarin/xamarin-macios/issues/13066.
Co-authored-by: Chris Hamons <chris.hamons@xamarin.com>
P/Invokes may point to a dylib, while the actual library linked into the .app
might be a static library, so make sure to compare without the extension.
This fixes an issue when linking with the static version of the runtime libraries.
Defining xm_nint_t to be 32-bit sized only on i386 is not the right thing to do for armv7.
Strangely enough this caused just a single test failure:
MonoTouchFixtures.Foundation.CalendarTest
[FAIL] TestFindNextDateAfterDateMatching : Expected: <Foundation.MonoTouchException>
But was: null
at MonoTouchFixtures.Foundation.CalendarTest.TestFindNextDateAfterDateMatching()
and that happened because:
1. We use a wrapper function around objc_msgSend:
void *
xamarin_IntPtr_objc_msgSend_IntPtr_IntPtr_nuint_exception (id self, SEL sel, void * p0, void * p1, xm_nuint_t p2, GCHandle *exception_gchandle)
{
@try {
return ((func_xamarin_IntPtr_objc_msgSend_IntPtr_IntPtr_nuint_exception) objc_msgSend) (self, sel, p0, p1, p2);
} @catch (NSException *e) {
xamarin_process_nsexception_using_mode (e, true, exception_gchandle);
return NULL;
}
}
2. Note that the second to last argument is an 'xm_nuint_t'. We told the
native compiler this was a 64-bit value, when the managed P/Invoke would
give it a 32-bit value. This had no effect on the 'p2' parameter, but it
meant that clang would thing the next argument, 'exception_gchandle', would
be somewhere it wasn't (the managed function would pass two 32-bit values,
'p2' and 'exception_gchandle', which clang would merge into a single 64-bit
'p2' argument, and then read random stuff for 'exception_gchandle').
3. Finally things would go sideways when we caught the exception and passed
'exception_gchandle' to xamarin_process_nsexception_using_mode. In effect
we'd ask xamarin_process_nsexception_using_mode to store the resulting
gchandle in random memory. Amazingly it only resulted in a test failure
(because upon return the managed location for the 'exception_gchandle'
wasn't touched, and would have its initial value of 0, thus managed code
would think no exception occurred).
So fix this to use the correct underlying types, instead of trying to figure
out the correct #if condition.
I'm not sure why we're using our own types here anyways, but this fix is the
smallest.
Instead of generating one native P/Invoke signature with an int parameter and
another with a long parameter for methods that take [Native] enums, generate a
single nint parameter (and the same for the unsigned version).
This simplifies both the generator code and the generated code. The generator
diff contains *a lot* of changes like this:
- if (IntPtr.Size == 8) {
- ret = (ARAppClipCodeUrlDecodingState) global::ObjCRuntime.Messaging.Int64_objc_msgSend (this.Handle, Selector.GetHandle ("urlDecodingState"));
- } else {
- ret = (ARAppClipCodeUrlDecodingState) global::ObjCRuntime.Messaging.int_objc_msgSend (this.Handle, Selector.GetHandle ("urlDecodingState"));
- }
+ ret = (ARKit.ARAppClipCodeUrlDecodingState) (long) global::ObjCRuntime.Messaging.nint_objc_msgSend (this.Handle, Selector.GetHandle ("urlDecodingState"));
An unlinked Xamarin.iOS.dll is ~300kb smaller (once linked the difference
should be minimal though).
I also made the min/max detection logic (check for int32.MinValue/MaxValue and
convert to int64.MinValue/MaxValue) specific to ARCH_32, since we don't need
it in 64-bit code.
Setting the XAMARIN_LOG_MARSHALLED_EXCEPTIONS environment variable will now
make us print all exceptions that go through exception marshalling, and how
we'll handle them.
Fixes https://github.com/xamarin/xamarin-macios/issues/12343.
* Add support for Mono Components.
* Modify how we look up symbols from native libraries shipped with Mono: we keep
track of which native libraries we linked with, and depending on how we linked
to those assemblies, we look the symbols up at runtime in either the current executable
(if linking statically), or the actual library (where the P/Invoke says they're
supposed to be).
* This means that we have to propagate how libmono is linked from the MSBuild code
to the Application class so that our existing logic is able to correctly determine
which native mono lib to use.
* Modify how we list the P/Invokes we need to preserve by taking into account the
list of native libraries from Mono we have to link with (for .NET). For legacy
Xamarin, I've reverted the logic to how it was before we started adding .NET support.
Fixes https://github.com/xamarin/xamarin-macios/issues/10950.
Fixes https://github.com/xamarin/xamarin-macios/issues/11145.
Fixes https://github.com/xamarin/xamarin-macios/issues/12100.
List all the assemblies in the app bundle and pass them to MonoVM/CoreCLR's in
the TRUSTED_PLATFORM_ASSEMBLIES initialization property.
This way CoreCLR knows where to find System.Private.CoreLib.dll for fat apps
(it's in the runtimeidentifier-specific subdirectory, and by default CoreCLR
will only look next to libcoreclr.dylib).
Fixes https://github.com/xamarin/xamarin-macios/issues/12265.
This also meant propagating how libmono is linked from the MSBuild code to the Application
class so that our existing logic is able to correctly determine which native mono
lib to use.
We need to process the runtimeconfig.json file somehow when using CoreCLR, and
the embedding API we use (coreclr_initialize) won't parse it for us. So re-use
the logic we already have to process runtimeconfig.json for MonoVM (which
involves converting it to a binary format at build time, which we then process
at runtime).