Browse Source

Merge pull request #3451 from AvaloniaUI/feature/implement-avalonia-native-exception-dispatch

Implement ExceptionDispatch for OSX
pull/3453/head
danwalmsley 7 years ago
committed by GitHub
parent
commit
fdfd5be1b1
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      src/Avalonia.Native/Avalonia.Native.csproj
  2. 14
      src/Avalonia.Native/CallbackBase.cs
  3. 59
      src/Avalonia.Native/PlatformThreadingInterface.cs

5
src/Avalonia.Native/Avalonia.Native.csproj

@ -19,8 +19,9 @@
<ItemGroup> <ItemGroup>
<SharpGenMapping Include="Mappings.xml" /> <SharpGenMapping Include="Mappings.xml" />
<PackageReference Include="SharpGenTools.Sdk" Version="1.1.2" PrivateAssets="all" /> <PackageReference Include="SharpGenTools.Sdk" Version="1.2.1" PrivateAssets="all" />
<PackageReference Include="SharpGen.Runtime.COM" Version="1.1.0" /> <PackageReference Include="SharpGen.Runtime" Version="1.2.1" />
<PackageReference Include="SharpGen.Runtime.COM" Version="1.2.0" />
<ProjectReference Include="..\..\packages\Avalonia\Avalonia.csproj" /> <ProjectReference Include="..\..\packages\Avalonia\Avalonia.csproj" />
<ProjectReference Include="..\Avalonia.Dialogs\Avalonia.Dialogs.csproj" /> <ProjectReference Include="..\Avalonia.Dialogs\Avalonia.Dialogs.csproj" />
</ItemGroup> </ItemGroup>

14
src/Avalonia.Native/CallbackBase.cs

@ -2,11 +2,13 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information. // Licensed under the MIT license. See licence.md file in the project root for full license information.
using System; using System;
using System.Runtime.ExceptionServices;
using SharpGen.Runtime; using SharpGen.Runtime;
using Avalonia.Platform;
namespace Avalonia.Native namespace Avalonia.Native
{ {
public class CallbackBase : SharpGen.Runtime.IUnknown public class CallbackBase : SharpGen.Runtime.IUnknown, IExceptionCallback
{ {
private uint _refCount; private uint _refCount;
private bool _disposed; private bool _disposed;
@ -76,5 +78,15 @@ namespace Avalonia.Native
{ {
} }
public void RaiseException(Exception e)
{
if (AvaloniaLocator.Current.GetService<IPlatformThreadingInterface>() is PlatformThreadingInterface threadingInterface)
{
threadingInterface.TerminateNativeApp();
threadingInterface.DispatchException(ExceptionDispatchInfo.Capture(e));
}
}
} }
} }

59
src/Avalonia.Native/PlatformThreadingInterface.cs

@ -2,6 +2,7 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information. // Licensed under the MIT license. See licence.md file in the project root for full license information.
using System; using System;
using System.Runtime.ExceptionServices;
using System.Threading; using System.Threading;
using Avalonia.Native.Interop; using Avalonia.Native.Interop;
using Avalonia.Platform; using Avalonia.Platform;
@ -43,6 +44,8 @@ namespace Avalonia.Native
} }
readonly IAvnPlatformThreadingInterface _native; readonly IAvnPlatformThreadingInterface _native;
private ExceptionDispatchInfo _exceptionDispatchInfo;
private CancellationTokenSource _exceptionCancellationSource;
public PlatformThreadingInterface(IAvnPlatformThreadingInterface native) public PlatformThreadingInterface(IAvnPlatformThreadingInterface native)
{ {
@ -57,32 +60,48 @@ namespace Avalonia.Native
public void RunLoop(CancellationToken cancellationToken) public void RunLoop(CancellationToken cancellationToken)
{ {
if (cancellationToken.CanBeCanceled == false) var l = new object();
_native.RunLoop(null); _exceptionCancellationSource = new CancellationTokenSource();
else
var compositeCancellation = CancellationTokenSource
.CreateLinkedTokenSource(cancellationToken, _exceptionCancellationSource.Token).Token;
var cancellation = _native.CreateLoopCancellation();
compositeCancellation.Register(() =>
{ {
var l = new object(); lock (l)
var cancellation = _native.CreateLoopCancellation();
cancellationToken.Register(() =>
{ {
lock (l) cancellation?.Cancel();
{
cancellation?.Cancel();
}
});
try
{
_native.RunLoop(cancellation);
} }
finally });
try
{
_native.RunLoop(cancellation);
}
finally
{
lock (l)
{ {
lock(l) cancellation?.Dispose();
{ cancellation = null;
cancellation?.Dispose();
cancellation = null;
}
} }
} }
if (_exceptionDispatchInfo != null)
{
_exceptionDispatchInfo.Throw();
}
}
public void DispatchException (ExceptionDispatchInfo exceptionInfo)
{
_exceptionDispatchInfo = exceptionInfo;
}
public void TerminateNativeApp()
{
_exceptionCancellationSource?.Cancel();
} }
public void Signal(DispatcherPriority priority) public void Signal(DispatcherPriority priority)

Loading…
Cancel
Save