libplctag / libplctag.NET

A .NET wrapper for libplctag.
https://libplctag.github.io/
Mozilla Public License 2.0
214 stars 53 forks source link

ReadAsync() not handling exception when wrong IP Address is provided. #327

Closed beena26g closed 1 year ago

beena26g commented 1 year ago

I am trying to do some error handling and ran into an issue specifically for ReadAsync() and wrong IP Address. If I provide wrong IP Address and do tag.ReadAsync(), the code faults out and does not throw an exception. Whereas it works perfectly fine with tag.Read(), tag.Write() and tag.WriteAsync(). Other exception types like wrong data type tags or wrong tag names would throw exceptions.

My sample code is as below. ` public static async Task Run() {

        //Instantiate the tag with the proper mapper and datatype
        var tag = new Tag<DintPlcMapper, int>()
        {
            Name = "Cycle_Limit",
            Gateway = "127.0.0.1", //Wrong IP Address 
            Path = "1,0",
            PlcType = PlcType.ControlLogix,
            Protocol = Protocol.ab_eip,
            Timeout = TimeSpan.FromSeconds(5)
        };

        try
        {
            // This does not fault out and give ErrorTimeOut in LibPlcException Handling. Generates an error and Task not handled correctly.
            // This is specifically for wrong IP Address, it works correctly if the tag name is wrong or has a wrong datatype and would throw exceptions accordingly.
            await tag.ReadAsync();
            //tag.Read(); //This works - and gives an LibPlcTagException.
        }
        catch (LibPlcTagException e)
        {
            Console.WriteLine(e.Message);
        }
    }   

I am using libplctag (1.1.1) version. Thank you and your help is appreciated.

timyhac commented 1 year ago

the code faults out and does not throw an exception

Can you elaborate on this? You should be getting a TaskCanceledException. If I run that code thats what I get.

//Instantiate the tag with the proper mapper and datatype
using libplctag.DataTypes;
using libplctag;

var tag = new Tag<DintPlcMapper, int>()
{
    Name = "Cycle_Limit",
    Gateway = "10.10.10.10",
    Path = "1,0",
    PlcType = PlcType.ControlLogix,
    Protocol = Protocol.ab_eip,
    Timeout = TimeSpan.FromSeconds(5)
};

try
{
    await tag.ReadAsync();
}
catch (Exception e)
{
    Console.WriteLine(e.GetType()); // System.Threading.Tasks.TaskCanceledException
}

Its a bit messy that a timeout gives a LibplctagException when using the synchronous methods and TaskCancelledException for async methods.

beena26g commented 1 year ago

Hello timy,

tag.Read() would gives Error TimeOut Libpcl tagException as connection is not established with plc due to wrong IP Address. I was expecting the same would happen with tag.ReadAsync() - should it not give an Error Timeout Libpcl tagException. You can run the same program with tag.Read() instead of tag.ReadAsync() and you will see the difference.

Its a bit messy that a timeout gives a LibplctagException when using the synchronous methods and TaskCanceledException for async methods.

I tried with asynchronous method tag.WriteAsync - that has given me Libpcl tagException Error Timeout instead of taskcanceledexception. Is there something I am missing here.

Thank you

timyhac commented 1 year ago

OK - good that you're at least getting that exception.

Actually looking through the code I think you're right - apologies its been a long time since I've looked at this part of the code. If it times out using the Tag Timeout property then it should throw a LibplctagException.

I think the issue is the wrong cancellation token being supplied to the internal call to InitializeAsync.

If we tweak the example code so that it first makes an explicit call to InitializeAsync(), it does show the expected exception:

using libplctag.DataTypes;
using libplctag;

var tag = new Tag<DintPlcMapper, int>()
{
    Name = "Cycle_Limit",
    Gateway = "10.10.10.10", //Wrong IP Address 
    Path = "1,0",
    PlcType = PlcType.ControlLogix,
    Protocol = Protocol.ab_eip,
    Timeout = TimeSpan.FromSeconds(5)
};

try
{
    await tag.InitializeAsync();    // LibPlcTagException
    await tag.ReadAsync();
}
catch (Exception e)
{
    Console.WriteLine(e.GetType());
}
timyhac commented 1 year ago

Hi @beena26g - an alpha package has been released with the change - let me know if you have further issues.