Skip to content

Fix .NET 10 CLR shutdown hook breaking change#7964

Merged
Arkatufus merged 14 commits into
akkadotnet:devfrom
Arkatufus:fix-net-10-CLR-hook
Dec 20, 2025
Merged

Fix .NET 10 CLR shutdown hook breaking change#7964
Arkatufus merged 14 commits into
akkadotnet:devfrom
Arkatufus:fix-net-10-CLR-hook

Conversation

@Arkatufus
Copy link
Copy Markdown
Contributor

Fixes #7963

Fix CoordinatedShutdown CLR Termination Hook for .NET 10 Compatibility

Summary

This PR addresses a breaking change in .NET 10 where AppDomain.ProcessExit is no longer raised when termination signals (SIGTERM, SIGHUP) are received. This would have caused CoordinatedShutdown to fail silently in containerized environments (Kubernetes, Docker) when running on .NET 10+.

Breaking Change Reference

Changes

New Termination Signal Handler Abstraction

Introduced ITerminationSignalHandler interface with two implementations:

  • PosixTerminationSignalHandler (.NET 6+): Uses PosixSignalRegistration to handle SIGTERM/SIGHUP signals directly, with ProcessExit as fallback
  • LegacyTerminationSignalHandler (netstandard2.0): Uses ProcessExit only (maintains backward compatibility)

Key features:

  • Sets context.Cancel = true to allow graceful shutdown time before OS terminates
  • Uses Interlocked.CompareExchange to ensure callback only executes once
  • Supports dependency injection for testability

Files Modified/Created

File Change
src/core/Akka/Actor/TerminationSignalHandler.cs New - Interface and implementations
src/core/Akka/Actor/CoordinatedShutdown.cs Refactored InitClrHook to use abstraction
src/core/Akka.Tests/Actor/TerminationSignalHandlerSpec.cs New - 7 unit tests
src/core/Akka.Tests/Akka.Tests.csproj .NET 10 compatibility fixes

Additional .NET 10 Test Fixes

  1. System.Linq.Async conflict: Excluded transitive System.Linq.Async package for .NET 10+ to resolve ambiguous method calls with BCL's built-in System.Linq.AsyncEnumerable

  2. ConfigurationSpec exclusion: Added CORECLR define for .NET 10 to properly exclude App.config-based tests (which only work on .NET Framework)

Test Coverage

New tests verify:

  • Handler registration when run-by-clr-shutdown-hook is enabled/disabled
  • Shutdown tasks execute when termination signal is received
  • ClrExitReason is set correctly during CLR shutdown
  • Handler is disposed when ActorSystem terminates normally
  • CLR hooks only execute once (idempotency)
  • Exception handling in shutdown tasks

Backward Compatibility

Framework Handler Behavior
netstandard2.0 / .NET Framework 4.8 LegacyTerminationSignalHandler ProcessExit only (unchanged)
.NET 6/8 PosixTerminationSignalHandler SIGTERM/SIGHUP + ProcessExit fallback
.NET 10+ PosixTerminationSignalHandler Properly handles SIGTERM

Copy link
Copy Markdown
Member

@Aaronontheweb Aaronontheweb left a comment

Choose a reason for hiding this comment

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

Had a conceptual question about Windows support but otherwise this looks good

Comment thread build-system/pr-validation.yaml Outdated
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

/// Handles SIGTERM and SIGHUP signals, plus ProcessExit as fallback.
/// This is required for .NET 10 compatibility where ProcessExit no longer fires on SIGTERM.
/// </summary>
internal sealed class PosixTerminationSignalHandler : ITerminationSignalHandler
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Dumb question on my part so I feel like I must be missing it - what do we do for Windows?

<PackageReference Include="Xunit.SkippableFact" Version="1.4.13" />
</ItemGroup>

<!-- Exclude System.Linq.Async for .NET 10+ as it conflicts with built-in BCL methods -->
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Good call

Comment thread Directory.Build.props Outdated
{
_callback = onTerminationSignal;

// Register POSIX signals (works on Unix/macOS/Windows in .NET 6+)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ah ok, so even though this is named "PosixSignalRegistration" it actually works on Windows too?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes from my research, I might actually be wrong. It does appear that way from my probings. Would be nice to hear from other people about this.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

the tests pass on Windows so I think it should be fine.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It isn't supported in IOS and not all signals are translated between windows and linux.

Copy link
Copy Markdown
Member

@Aaronontheweb Aaronontheweb left a comment

Choose a reason for hiding this comment

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

LGTM

Comment thread src/core/Akka/Actor/TerminationSignalHandler.cs Outdated
@Arkatufus Arkatufus merged commit ff33700 into akkadotnet:dev Dec 20, 2025
11 checks passed
Arkatufus added a commit to Arkatufus/akka.net that referenced this pull request Jan 7, 2026
* Fix .NET 10 CLR shutdown hook breaking change

* fix global.json

* Fix warning as errors

* Install .NET SDK 8.0

* Add very targetted .NET 10 CI/CD run

* Fix CI/CD script

* Code fix

* Revert .NET 10 CI/CD integration (will be moved to a new PR)

* whitespace cleanup

---------

Co-authored-by: Aaron Stannard <aaron@petabridge.com>
Aaronontheweb added a commit that referenced this pull request Jan 8, 2026
* Fix .NET 10 CLR shutdown hook breaking change

* fix global.json

* Fix warning as errors

* Install .NET SDK 8.0

* Add very targetted .NET 10 CI/CD run

* Fix CI/CD script

* Code fix

* Revert .NET 10 CI/CD integration (will be moved to a new PR)

* whitespace cleanup

---------

Co-authored-by: Aaron Stannard <aaron@petabridge.com>
This was referenced May 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

.NET 10 breaks CoordinatedShutdown

2 participants