Portalum / Portalum.Zvt

A .NET Zvt Library for Payment Terminals (C#)
MIT License
88 stars 36 forks source link

Error from TcpClient after Disconnecting and Disposing the Portalum.ZVT.TCPDeviceCommunication #31

Closed Astra3141 closed 1 year ago

Astra3141 commented 1 year ago

Hello,

first of all thanks for your work and your great libraries.

I use the Portalum.ZVT-Library on an Android Device using Xamarin. There I have this issue that when I disconnect and dispose the TCPDeviceCommunication to free the terminal for other devices that want to use it, I get an error from Nager.TcpClient.DataReadAsync approximately 3 minutes later where it states "Unable to read from stream" which it shouldn't try anymore because Portalum disconnected and disposed the TcpClient.

I can see that the TcpClient rethrows those kind of exceptions but unfortunately I can't catch this error because it's outside of my scope. It just comes out of nowhere and crashes my app.


Logs: System.AggregateException: A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread. (Unable to read data from the transport connection: Operation aborted.) ---> System.IO.IOException: Unable to read data from the transport connection: Operation aborted. ---> System.Net.Sockets.SocketException: Operation aborted at Nager.TcpClient.TcpClient.DataReadAsync (System.Threading.CancellationToken cancellationToken) [0x00221]

System.AggregateException: A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread. (Unable to read data from the transport connection: interrupted.) ---> System.IO.IOException: Unable to read data from the transport connection: interrupted. ---> System.Net.Sockets.SocketException: interrupted at Nager.TcpClient.TcpClient.DataReadAsync (System.Threading.CancellationToken cancellationToken) [0x00221]

tinohager commented 1 year ago

Here you would have to debug deeper, I have no android device to test at hand. I can therefore not help you without a test setup at the moment.

Astra3141 commented 1 year ago

Thanks for your fast reply. I'll try to dig deeper then. Although it's less important now since it seems that Disconnect is enough to free the terminal for other devices and Dispose is not really necessary.

tinohager commented 1 year ago

Do we need anything else here or can we close the issue

Astra3141 commented 1 year ago

Sorry, no, I don't think we can do anything about that right now. I'll do some more research as soon as I can manage. Closing it for now.

tinohager commented 1 year ago

I can help them in the collection of the problem, but this would cause costs.

Astra3141 commented 1 year ago

Thanks but thats not necessary. I did dig into it and found that the base problem is somewhere inside the Net.Sockets.TcpClient at get_Connected when Nager asks the TcpClient for TcpClient.Connected inside DataReceiverAsync. Seems like the socket is already disposed when the client is being asked for the connection status.

Thats the log entry: System.AggregateException: A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread. (Object reference not set to an instance of an object.) ---> System.NullReferenceException: Object reference not set to an instance of an object. at System.Net.Sockets.TcpClient.get_Connected () [0x00000] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/mcs/class/referencesource/System/net/System/Net/Sockets/TCPClient.cs:168 at Nager.TcpClient.TcpClient.DataReceiverAsync (System.Threading.CancellationToken cancellationToken) [0x00179] in .\Nager.TcpClient-main\src\Nager.TcpClient\TcpClient.cs:442 at Nager.TcpClient.TcpClient.<.ctor>b__21_1 () [0x0002f] in .\Nager.TcpClient-main\src\Nager.TcpClient\TcpClient.cs:86

It also seems like checking the TcpClient and the TcpClient.Client for null right before asking for Connected does the trick. Still have to test a bit more to make completely sure of that. Wonder why though, the TcpClient is being null-checked right before that but just checking the TcpClient.Client doesn't seem to be enough.

That makes it a Nager / .Net / Mono problem so its no issue of Portalum either way.

tinohager commented 1 year ago

Can you try the new version of Nager.TcpClient?

Astra3141 commented 1 year ago

Tried it with Nager 1.1.0 for a few hours and didn't get the error anymore or any crash from the TcpNetworkDeviceCommunication as long as I just disconnect. Tried to dispose the TcpNetworkDeviceCommunication again out of curiosity which gave me another crashing error but won't do it anymore since it is not necessary.

Thank you a lot for your help and again for your work.

(Just FYI: The error on dispose is a "System.IO.IOException: Unable to read data from the transport connection: Operation aborted." in Nager.TcpClient.DataReadAsync which is caught, rethrown and just crashes outside the app somewhere since it can't be caught again.)