3

I have a very trivial method for deserialization of data from a file:

private static List<DataJSON> LoadJSON()
{

    List<DataJSON> jsonData = new List<DataJSON>();
    /*
    using (StreamReader file = File.OpenText(@"actions.json"))
    {
        JsonSerializer serializer = new JsonSerializer();
        jsonData = (List<DataJSON>)serializer.Deserialize(file, typeof(List<DataJSON>));
    }*/

    Console.WriteLine("a");
    var file = File.ReadAllText("actions.json");
    Console.WriteLine("b");
    try
    {
        jsonData = JsonConvert.DeserializeObject<List<DataJSON>>(file);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
    Console.WriteLine("c");
    return jsonData;
}

Which is working just fine on Windows machine. However, on linux (Debian 9) I am getting "Aborts". There is no exception thrown at all:

enter image description here

I have placed some additional console line outputs, and managed to track down the issue to this line:

List<DataJSON> jsonData = JsonConvert.DeserializeObject<List<DataJSON>>

is it possible for the dotnet to output something more meaningful than "Aborted"? What could be the cause of this issue?

App is compiled like this:

dotnet publish -c release --runtime linux-x64

Also dotnet --version command output:

2.1.3

Edit: As it turns out - the issue is totally random. The JSON is de-serialized 3 times out of 10. Or 5 out of 10. It either works or not - randomly.

Edit 2. As it turns out - this issue has very little in common with Deserialization. The problem is the type of the object that is being de-serialized. I was able to reproduce the issue on multiple occasions just by doing this:

static void Main(string[] args)
{
    Console.WriteLine("Start");

    List<string> symbolsStr = new List<string>() {
        "MODETH", "MTHETH", "MTLETH", "NANOETH", "NAVETH", "NEBLETH", "NEOETH",
        "NULSETH", "OAXETH", "OMGETH", "OSTETH", "PIVXETH", "POEETH", "POWRETH",
        "MDAETH", "PPTETH", "QTUMETH", "RCNETH", "RDNETH", "REQETH", "RLCETH",
        "SALTETH", "SNGLSETH", "SNMETH", "SNTETH", "STEEMETH", "STORJETH", "STRATETH",
        "SUBETH", "TNBETH", "QSPETH", "TNTETH", "MCOETH", "LUNETH", "CNDETH"};

    foreach (var item in symbolsStr)
    {
        var symbol = (Symbol)item;
    }

    Console.WriteLine("End");
    Environment.Exit(0);
}

When the string is converted to Symbol type of object - Abort is happening (presumably). The causes of it are unknown to me. Also, the reason why exception is not shown is also unknown. I'd still appreciate to hear out any advices on how to debug this issue. In a meanwhile - I have contacted the creator of a library (C# Binance API by sonvister) which seems to be misbehaving on my machine. I will keep this post updated.

Alex
  • 4,607
  • 9
  • 61
  • 99
  • It could be anything. Perhaps catch the exception and log? – TyCobb Feb 13 '18 at 18:32
  • try-catch does not catch the exception. it just aborts – Alex Feb 13 '18 at 18:32
  • Yes it is :( I will update the question in a sec with try-catch clause in place. – Alex Feb 13 '18 at 18:35
  • oh wait! seems like I am onto it! when the method is called from outside of async task then seems to be working Ok. Need to run more tests – Alex Feb 13 '18 at 18:39
  • Possibly a `StackOverflowException`? – dbc Feb 13 '18 at 18:41
  • @dbc I don't know... no exceptions are thrown. However, I just made a progress. It turns out that the deserialization works! ~3 times out of 10. Totally randomly. I thought that I had some idea but now i am lost completely. – Alex Feb 13 '18 at 18:49
  • `StackOverflowException` can't be caught, see [C# catch a stack overflow exception](https://stackoverflow.com/q/1599219). But if it's random it's almost certainly not. – dbc Feb 13 '18 at 19:14

2 Answers2

0

If you want the information from the exception you can try to throw it:

catch (Exception ex)
{
    Console.WriteLine(ex.Message);
    throw ex; 
}
bernieslearnings
  • 1,424
  • 4
  • 17
  • 27
torsan
  • 401
  • 5
  • 14
  • 1
    Catching the exception and re-throwing is the same as not catching it all. Your Console.WriteLine will also never hit since you throw beforehand. – TyCobb Feb 13 '18 at 20:17
0

I have got a partial answer to my question.

Problem description

As you know, there is an type-safe Enum pattern out there. The JSON that I was trying to deserialize - had objects of such type(Symbol) serialized. Abortion happenned at the time when code tried to access Symbol object instance (or convert string to Symbol type).

The main class had following structure (extremely simplified version):

public sealed class Symbol
{
    public static readonly Symbol ONE = new Symbol(new[] { OrderType.Limit, OrderType.LimitMaker, OrderType.Market, OrderType.StopLossLimit, OrderType.TakeProfitLimit });
    public static readonly Symbol TWO = new Symbol(new[] { OrderType.Limit, OrderType.LimitMaker, OrderType.Market, OrderType.StopLossLimit, OrderType.TakeProfitLimit });
    public static readonly Symbol THREE = new Symbol(new[] { OrderType.Limit, OrderType.LimitMaker, OrderType.Market, OrderType.StopLossLimit, OrderType.TakeProfitLimit });
    // 264 such lines in total

    public Symbol(IEnumerable<OrderType> orderTypes)
    {

    }
}

After hours of testing I managed to track down the issue to the fact, that when half of Symbols are removed from the main class, then the problem goes away. It doesn't matter exactly which symbols are removed as long as it's noticeable amount.

I have then determined, then anonymous type of objects are causing this issue, by randomly changing the parameter type to List.

I.e. instead of this:

new[] { OrderType.Limit, OrderType.LimitMaker, OrderType.Market, OrderType.StopLossLimit, OrderType.TakeProfitLimit }

I used this:

new List<OrderType> { OrderType.Limit, OrderType.LimitMaker, OrderType.Market, OrderType.StopLossLimit, OrderType.TakeProfitLimit }

That was when the issue was finally resolved.

Test approach

Console app (.net core 2.x):

 static void Main(string[] args)
 {
      var symbol = Symbol.ONE;
 }

Compilation command:

dotnet publish -c release -r debian-x64

Linux command for testing:

while sleep 0.5 ; do dotnet BinanceTestConsole.dll ; done

The linux command will execute dotnet application once in half-a-second time. Therefore, if at least one "Aborted" is printed within 20 second interval - you can consider the test as not passed.

Final words

Now, I don't know exactly what the issue is. It probably has something to do with how .net core handles anonymous object conversion to other types of objects or something completely different. This resolution also does not provide any information about exception is (presumably) being thrown at a run time. My suggestion for anybody who's having the same issue - get the source of the library that is throwing the error - and try to strip down the code until there is nothing but bones, and the error is still thrown! Corner it and fight it! Hopefully you will find the answer. Then file a report to Microsoft (/git).

Edit:

OrderType[] has the same result as if new[] was used.. So probably it has nothing to do with anonymous object.. but an array? Hm

Alex
  • 4,607
  • 9
  • 61
  • 99