runtime: SerialPort Flush[Async] makes Read[Async] timeout/block
A call to SerialPort.BaseStream.Flush[Async] seems to mess up the state in the serial port base stream so a read following the flush will timeout/block. Write will send data out on the port without a call to Flush, but other classes wrapping streams in .Net Core, like PipeWriter.Create, will always flush, making this issue a blocker. Code below will work if the call to flush is removed. I used a USB-RS232 adapter on a RaspPi3 with pin 2-3 connected (loopback). I have verified data on oscilloscope with and without flush.
@krwq you seem to have worked a lot on the SerialPort for Linux, is this a known issue with Flush breaking the stream?
using System;
using System.Buffers;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SerialFlushTest
{
class Program
{
static async Task Main(string[] args)
{
var portName = args.Any() ? args[0] : SerialPort.GetPortNames().Last();
var port = new SerialPort(portName, 115_200);
Console.WriteLine("Using port: " + port.PortName);
port.Open();
var msg = Encoding.ASCII.GetBytes("reader.is_alive()\n");
await port.BaseStream.WriteAsync(msg);
Console.WriteLine("< " + Encoding.ASCII.GetString(msg));
await port.BaseStream.FlushAsync();// Uncomment this line to make read work
Console.WriteLine("Flushed " + msg.Length);
using var buf = MemoryPool<byte>.Shared.Rent(1024);
var read = await port.BaseStream.ReadAsync(buf.Memory);
Console.WriteLine("> " + Encoding.ASCII.GetString(buf.Memory.Span.Slice(0, read)));
}
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RuntimeIdentifier>linux-arm</RuntimeIdentifier>
<SelfContained>false</SelfContained>
</PropertyGroup>
<PropertyGroup>
<SshDeployHost>192.168.1.118</SshDeployHost>
<SshDeployClean />
<SshDeployTargetPath>/home/pi/serialflush</SshDeployTargetPath>
<SshDeployUsername>pi</SshDeployUsername>
<SshDeployPassword>raspberry</SshDeployPassword>
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
</PropertyGroup>
<Target Condition="$(BuildingInsideSshDeploy) ==''" Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="cd $(ProjectDir)" />
<Exec Command="dotnet-sshdeploy push" />
</Target>
<ItemGroup>
<PackageReference Include="System.IO.Ports" Version="4.7.0" />
</ItemGroup>
</Project>
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 50 (22 by maintainers)
@krwq see https://github.com/dotnet/runtime/issues/33130. It’s incorrect for IO.Ports to PInvoke to the shims. Those aren’t public surface area.
So this will explain the problem, but I will let you guys figure out the right solution. Renaming the native libs seems like a bad idea 😉 Another thing I’m wondering is, why are not exceptions thrown in the thread pool printed. Is the thread pool catching exceptions and suppressing them by default? I’ve had similar issues before when everything seems fine but it turned out an exception in the thread pool happened. I think you should add a continuation on the Task created to run the IO loop to catch exceptions thrown in there. Or add a try catch in the IOLoop.