runtime: System.IO.Ports.SerialPort not working on Linux arm64

Description

'Unable to load shared library ‘libSystem.IO.Ports.Native’ or one of its dependencies

Similar to issue #63187 though Linux versions differ. Presumably the same root issue.

Reproduction Steps

Create new console app (.net 6.0) Add System.IO.Ports NuGet.

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <PlatformTarget>AnyCPU</PlatformTarget>
    <RuntimeIdentifier>linux-arm</RuntimeIdentifier>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="System.IO.Ports" Version="6.0.0" />
  </ItemGroup>

</Project>
using System.IO.Ports;

namespace RaspberryPiIoTTestApp02
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, World!");

            string[] ports = SerialPort.GetPortNames();
            // Display each port name to the console.
            foreach (string p in ports)
            {
                Console.WriteLine($"GetSerialPorts(): {p}");
            }

            string _portName = "/dev/ttyAMA1";
            SerialPort port = new SerialPort(_portName);
            port.BaudRate = 19200;
            port.DataBits = 8;
            port.Parity = Parity.Even;
            port.StopBits = StopBits.One;
            port.Open();
        }
    }
}

Expected behavior

Program runs.

Prints out available serial ports, (in my case)

GetSerialPorts(): /dev/ttyAMA1
GetSerialPorts(): /dev/ttyAMA2
GetSerialPorts(): /dev/ttyAMA0

Opens port /dev/ttyAMA1

Actual behavior

Program runs.

Prints out available serial ports, (in my case)

GetSerialPorts(): /dev/ttyAMA1
GetSerialPorts(): /dev/ttyAMA2
GetSerialPorts(): /dev/ttyAMA0

Exception at port.Open();

Exception thrown: 'System.DllNotFoundException' in System.IO.Ports.dll
An unhandled exception of type 'System.DllNotFoundException' occurred in System.IO.Ports.dll: 'Unable to load shared library 'libSystem.IO.Ports.Native' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: liblibSystem.IO.Ports.Native: cannot open shared object file: No such file or directory'
Stack trace:
 >   at Interop.Serial.SerialPortOpen(String name)
 >   at System.IO.Ports.SafeSerialDeviceHandle.Open(String portName)
 >   at System.IO.Ports.SerialStream..ctor(String portName, Int32 baudRate, Parity parity, Int32 dataBits, StopBits stopBits, Int32 readTimeout, Int32 writeTimeout, Handshake handshake, Boolean dtrEnable, Boolean rtsEnable, Boolean discardNull, Byte parityReplace)
 >   at System.IO.Ports.SerialPort.Open()
 >   at RaspberryPiIoTTestApp02.Program.Main(String[] args) in C:\Users\georg\OneDrive\Documents\Visual Studio\2022 - vs22\RaspberryPiIoTTestApp02\RaspberryPiIoTTestApp02\Program.cs:line 17

Setting LD_DEBUG=all gives some info though unfortunately its all a bit beyond me!

      5612:	
      5612:	file=/home/pi/vsdbg/RaspberryPiIoTTestApp02/libSystem.IO.Ports.Native.so [0];  dynamically loaded by /usr/lib/dotnet/shared/Microsoft.NETCore.App/6.0.8/libcoreclr.so [0]
      5612:	
      5612:	file=/usr/lib/dotnet/shared/Microsoft.NETCore.App/6.0.8/libSystem.IO.Ports.Native.so [0];  dynamically loaded by /usr/lib/dotnet/shared/Microsoft.NETCore.App/6.0.8/libcoreclr.so [0]
      5612:	
      5612:	file=/home/pi/vsdbg/RaspberryPiIoTTestApp02/libSystem.IO.Ports.Native.so [0];  dynamically loaded by /usr/lib/dotnet/shared/Microsoft.NETCore.App/6.0.8/libcoreclr.so [0]
      5612:	
      5612:	file=libSystem.IO.Ports.Native.so [0];  dynamically loaded by /usr/lib/dotnet/shared/Microsoft.NETCore.App/6.0.8/libcoreclr.so [0]
      5612:	find library=libSystem.IO.Ports.Native.so [0]; searching
      5612:	 search cache=/etc/ld.so.cache
      5612:	 search path=/lib/aarch64-linux-gnu:/usr/lib/aarch64-linux-gnu:/lib:/usr/lib		(system search path)
      5612:	  trying file=/lib/aarch64-linux-gnu/libSystem.IO.Ports.Native.so
      5612:	  trying file=/usr/lib/aarch64-linux-gnu/libSystem.IO.Ports.Native.so
      5612:	  trying file=/lib/libSystem.IO.Ports.Native.so
      5612:	  trying file=/usr/lib/libSystem.IO.Ports.Native.so
      5612:	
      5612:	
      5612:	file=/home/pi/vsdbg/RaspberryPiIoTTestApp02/liblibSystem.IO.Ports.Native.so [0];  dynamically loaded by /usr/lib/dotnet/shared/Microsoft.NETCore.App/6.0.8/libcoreclr.so [0]
      5612:	
      5612:	file=/usr/lib/dotnet/shared/Microsoft.NETCore.App/6.0.8/liblibSystem.IO.Ports.Native.so [0];  dynamically loaded by /usr/lib/dotnet/shared/Microsoft.NETCore.App/6.0.8/libcoreclr.so [0]
      5612:	
      5612:	file=/home/pi/vsdbg/RaspberryPiIoTTestApp02/liblibSystem.IO.Ports.Native.so [0];  dynamically loaded by /usr/lib/dotnet/shared/Microsoft.NETCore.App/6.0.8/libcoreclr.so [0]
      5612:	
      5612:	file=liblibSystem.IO.Ports.Native.so [0];  dynamically loaded by /usr/lib/dotnet/shared/Microsoft.NETCore.App/6.0.8/libcoreclr.so [0]
      5612:	find library=liblibSystem.IO.Ports.Native.so [0]; searching
      5612:	 search cache=/etc/ld.so.cache
      5612:	 search path=/lib/aarch64-linux-gnu:/usr/lib/aarch64-linux-gnu:/lib:/usr/lib		(system search path)
      5612:	  trying file=/lib/aarch64-linux-gnu/liblibSystem.IO.Ports.Native.so
      5612:	  trying file=/usr/lib/aarch64-linux-gnu/liblibSystem.IO.Ports.Native.so
      5612:	  trying file=/lib/liblibSystem.IO.Ports.Native.so
      5612:	  trying file=/usr/lib/liblibSystem.IO.Ports.Native.so
      5612:	
      5612:	
      5612:	file=/home/pi/vsdbg/RaspberryPiIoTTestApp02/libSystem.IO.Ports.Native [0];  dynamically loaded by /usr/lib/dotnet/shared/Microsoft.NETCore.App/6.0.8/libcoreclr.so [0]
      5612:	
      5612:	file=/usr/lib/dotnet/shared/Microsoft.NETCore.App/6.0.8/libSystem.IO.Ports.Native [0];  dynamically loaded by /usr/lib/dotnet/shared/Microsoft.NETCore.App/6.0.8/libcoreclr.so [0]
      5612:	
      5612:	file=/home/pi/vsdbg/RaspberryPiIoTTestApp02/libSystem.IO.Ports.Native [0];  dynamically loaded by /usr/lib/dotnet/shared/Microsoft.NETCore.App/6.0.8/libcoreclr.so [0]
      5612:	
      5612:	file=libSystem.IO.Ports.Native [0];  dynamically loaded by /usr/lib/dotnet/shared/Microsoft.NETCore.App/6.0.8/libcoreclr.so [0]
      5612:	find library=libSystem.IO.Ports.Native [0]; searching
      5612:	 search cache=/etc/ld.so.cache
      5612:	 search path=/lib/aarch64-linux-gnu:/usr/lib/aarch64-linux-gnu:/lib:/usr/lib		(system search path)
      5612:	  trying file=/lib/aarch64-linux-gnu/libSystem.IO.Ports.Native
      5612:	  trying file=/usr/lib/aarch64-linux-gnu/libSystem.IO.Ports.Native
      5612:	  trying file=/lib/libSystem.IO.Ports.Native
      5612:	  trying file=/usr/lib/libSystem.IO.Ports.Native
      5612:	
      5612:	
      5612:	file=/home/pi/vsdbg/RaspberryPiIoTTestApp02/liblibSystem.IO.Ports.Native [0];  dynamically loaded by /usr/lib/dotnet/shared/Microsoft.NETCore.App/6.0.8/libcoreclr.so [0]
      5612:	
      5612:	file=/usr/lib/dotnet/shared/Microsoft.NETCore.App/6.0.8/liblibSystem.IO.Ports.Native [0];  dynamically loaded by /usr/lib/dotnet/shared/Microsoft.NETCore.App/6.0.8/libcoreclr.so [0]
      5612:	
      5612:	file=/home/pi/vsdbg/RaspberryPiIoTTestApp02/liblibSystem.IO.Ports.Native [0];  dynamically loaded by /usr/lib/dotnet/shared/Microsoft.NETCore.App/6.0.8/libcoreclr.so [0]
      5612:	
      5612:	file=liblibSystem.IO.Ports.Native [0];  dynamically loaded by /usr/lib/dotnet/shared/Microsoft.NETCore.App/6.0.8/libcoreclr.so [0]
      5612:	find library=liblibSystem.IO.Ports.Native [0]; searching
      5612:	 search cache=/etc/ld.so.cache
      5612:	 search path=/lib/aarch64-linux-gnu:/usr/lib/aarch64-linux-gnu:/lib:/usr/lib		(system search path)
      5612:	  trying file=/lib/aarch64-linux-gnu/liblibSystem.IO.Ports.Native
      5612:	  trying file=/usr/lib/aarch64-linux-gnu/liblibSystem.IO.Ports.Native
      5612:	  trying file=/lib/liblibSystem.IO.Ports.Native
      5612:	  trying file=/usr/lib/liblibSystem.IO.Ports.Native
      5612:	

Note that the exception appears on port.Open(); not when an instance of SerialPort is created or when we’re getting all available serial ports.

Regression?

Unknown though though the notnet/iot team have example code for Controlling Arduino with .NET using Raspberry Pi via serial port here using System.IO.Ports -v 4.6.0-preview.18571.3. It may be that they are using ARM (32-bit) that is unaffected by this or it is a regression.

Known Workarounds

Unknown though some people have reported work arounds in issue #63187.

Configuration

Which version of .NET is the code running on? .NET 6.0 What OS and version, and what distro if applicable? Raspberry Pi OS - 64-bit - Lite What is the architecture (x64, x86, ARM, ARM64)? ARM64 Do you know whether it is specific to that configuration? It appears to be affecting other versions of linux through similar issues #63187

Other information

No response

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 2
  • Comments: 21 (15 by maintainers)

Most upvoted comments

I find using the CLI dotnet with command line switches eg [dotnet publish -c Debug -r linux-musl-arm64 --sc] is often better than using latest upgrade of VS2022 IDE as it tends to lack new configuration features. Although since they swapped to new Project Properties config menu it is getting closer.

Yes sounds like it. Or something is happening in the source build pipeline for that combination of runtime & architecture, the switching combinations during build can get complex to follow. I’ve gone over the dotnet runtime Repo several times to look at how the native libs are built but starting to wonder if it’s actually a problem in the SDK, and that repo I am not familiar with.

I know people use it, but is Raspbian officially supported by .dot net 7? What is the --runtime your targeting during build? And you’re building on the device using an installed SDK or PC and building for Alpine or something and ARM64 ? What’s the error your getting, same as above missing libSystem.IO.Ports.Native ?

What happens when you CD into the project folder (bin) and run ldd on the library? ldd libSystem.IO.Ports.Native.so As below? https://github.com/dotnet/runtime/issues/74332#issuecomment-1288010254

Are you building a Self-Contained app or runtime dependant, tried both? Out of pure curiosity can you run this & send back just the relevant-interesting OS/bitlevel/etc Environment fields? https://github.com/PRIMETSS/DotNetCoreOpenWRTLinux32

This issue has been automatically marked no-recent-activity because it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will remove no-recent-activity.