Skip to content

Commit

Permalink
Add polyfills for SystemException, ThreadAbortException, and impr…
Browse files Browse the repository at this point in the history
…ove `Lock` resilience (#14)
  • Loading branch information
Tyrrrz authored Sep 30, 2024
1 parent 13499d2 commit 694424d
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 6 deletions.
6 changes: 3 additions & 3 deletions PolyShim/Net60/EnumerableExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static T ElementAt<T>(this IEnumerable<T> source, Index index)
if (index.IsFromEnd)
{
var asCollection =
#if !NET45_OR_GREATER
#if NETFRAMEWORK && !NET45_OR_GREATER
source as ICollection<T> ??
#else
source as IReadOnlyCollection<T> ??
Expand All @@ -38,7 +38,7 @@ source as IReadOnlyCollection<T> ??
if (index.IsFromEnd)
{
var asCollection =
#if !NET45_OR_GREATER
#if NETFRAMEWORK && !NET45_OR_GREATER
source as ICollection<T> ??
#else
source as IReadOnlyCollection<T> ??
Expand Down Expand Up @@ -154,7 +154,7 @@ T defaultValue
public static IEnumerable<T> Take<T>(this IEnumerable<T> source, Range range)
{
var asCollection =
#if !NET45_OR_GREATER
#if NETFRAMEWORK && !NET45_OR_GREATER
source as ICollection<T> ??
#else
source as IReadOnlyCollection<T> ??
Expand Down
24 changes: 23 additions & 1 deletion PolyShim/Net90/Lock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,30 @@ public bool TryEnter(int millisecondsTimeout) =>

public Scope EnterScope()
{
Enter();
#if NETFRAMEWORK && !NET40_OR_GREATER
// Older versions of the framework don't have the overload of Monitor.Enter(...) that accepts a ref bool
Monitor.Enter(this);
return new Scope(this);
#else
var acquiredLock = false;
try
{
Monitor.Enter(this, ref acquiredLock);
return new Scope(this);
}
// Ensure that the lock is released if the owning thread is aborted.
// Implementation reference:
// https://github.com/MarkCiliaVincenti/Backport.System.Threading.Lock/blob/c28041f1e22e561d5cde040704abeeb8d9a18649/Backport.System.Threading.Lock/PreNet5Lock.cs#L112-L125
// MIT License, Mark Cilia Vincenti
// https://github.com/Tyrrrz/PolyShim/pull/10#issuecomment-2381456516
catch (ThreadAbortException)
{
if (acquiredLock)
Monitor.Exit(this);

throw;
}
#endif
}
}

Expand Down
4 changes: 2 additions & 2 deletions PolyShim/NetCore10/AggregateException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ namespace System;
[ExcludeFromCodeCoverage]
internal class AggregateException : Exception
{
public ReadOnlyCollection<Exception> InnerExceptions { get; } = new(new Exception[0]);

public AggregateException(string? message, params Exception[] innerExceptions)
: base(message, innerExceptions.FirstOrDefault())
{
Expand Down Expand Up @@ -47,6 +45,8 @@ public AggregateException()
public AggregateException(SerializationInfo info, StreamingContext context)
: base(info, context) { }

public ReadOnlyCollection<Exception> InnerExceptions { get; } = new(new Exception[0]);

public AggregateException Flatten()
{
var innerExceptions = new List<Exception>();
Expand Down
15 changes: 15 additions & 0 deletions PolyShim/NetCore20/SystemException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#if (NETCOREAPP && !NETCOREAPP2_0_OR_GREATER) || (NETSTANDARD && !NETSTANDARD2_0_OR_GREATER)
#nullable enable
// ReSharper disable RedundantUsingDirective
// ReSharper disable CheckNamespace
// ReSharper disable InconsistentNaming
// ReSharper disable PartialTypeWithSinglePart
using System.Diagnostics.CodeAnalysis;

namespace System;

// https://learn.microsoft.com/en-us/dotnet/api/system.systemexception
[ExcludeFromCodeCoverage]
internal class SystemException(string? message = null, Exception? innerException = null)
: Exception(message, innerException);
#endif
20 changes: 20 additions & 0 deletions PolyShim/NetCore20/ThreadAbortException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#if (NETCOREAPP && !NETCOREAPP2_0_OR_GREATER) || (NETSTANDARD && !NETSTANDARD2_0_OR_GREATER)
#nullable enable
// ReSharper disable RedundantUsingDirective
// ReSharper disable CheckNamespace
// ReSharper disable InconsistentNaming
// ReSharper disable PartialTypeWithSinglePart
using System.Diagnostics.CodeAnalysis;

namespace System.Threading;

// https://learn.microsoft.com/en-us/dotnet/api/system.threading.threadabortexception
[ExcludeFromCodeCoverage]
internal class ThreadAbortException : SystemException
{
// This exception cannot be instantiated by user code
private ThreadAbortException() => HResult = unchecked((int)0x80131530);

public object? ExceptionState => null;
}
#endif

0 comments on commit 694424d

Please sign in to comment.