zeromq / netmq

A 100% native C# implementation of ZeroMQ for .NET
Other
2.95k stars 743 forks source link

Fix fatal SEHException on Arm calling RDTSC #1055

Closed jonorossi closed 1 year ago

jonorossi commented 1 year ago

Arm does not have the x86 Timestamp Counter register or read timestamp counter instruction. Add an additional architecture check to prevent the code path when running on Arm. The code checks for X86/X64 as they are the only Intel-based architectures in the enum, while the enum now contains 4 Arm-based members (only in recent .NET) along with WebAssembly and more.

Running .NET on Windows on Arm, NetMQ throws a fatal exception crashing the application just starting up a poller:

Fatal error. System.Runtime.InteropServices.SEHException (0x80004005): External component has thrown an exception.
   at NetMQ.Core.Utils.Clock.Rdtsc()
   at NetMQ.Core.SocketBase.ProcessCommands(Int32, Boolean, System.Threading.CancellationToken)
   at NetMQ.Core.SocketBase.Bind(System.String)
   at NetMQ.NetMQSocket.Bind(System.String)
   at NetMQ.Sockets.PairSocket.CreateSocketPair(NetMQ.Sockets.PairSocket ByRef, NetMQ.Sockets.PairSocket ByRef)
   at NetMQ.Core.Utils.StopSignaler..ctor()
   at NetMQ.NetMQPoller..ctor()
   [...]

This defect has been reported in #199 (Arm), #714 (Arm) and #1033 (FPGA). There was one fix made in #227 that added the IsARMArchitecture, however that only works on Mono.

The change will fix the defect for .NET Standard 2.0/2.1 targets (which are used for .NET Core and 5+ runtimes) as they both define NETSTANDARD1_1_OR_GREATER. It won't fix the bug for .NET Framework 4.5/4.7 targets as the RuntimeInformation class is only available on .NET Framework 4.7.1, however Windows on Arm appears to emulate the instruction for .NET Framework and the code is set up ready if this project's TFMs are changed in the future.

drewnoakes commented 1 year ago

Thanks, this looks great.

Unfortunately, it looks like there's no way currently to run CI on ARM64.

https://github.com/actions/runner-images/issues/5631

drewnoakes commented 1 year ago

Released in https://www.nuget.org/packages/NetMQ/4.0.1.12

jonorossi commented 1 year ago

Unfortunately, it looks like there's no way currently to run CI on ARM64.

I've pulled 4.0.1.12 and it runs. Cheers for making the release 👏.

drewnoakes commented 1 year ago

Thanks for the high quality PRs and confirming the fix!