While calling .ToArray, I am hitting the following exception:
Internal CLR error. (0x80131506)
at System.Linq.Enumerable.ToArray[[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.Collections.Generic.IEnumerable`1<System.__Canon>)
This happens intermittently, and is hard to reproduce. Can this type of exception be caught and retried? Would I just have to catch a generic exception.
The code to call .ToArray() is inside an async Task. There is already a general try/catch outside the async code to catch any exception and log it. It does not seem to be getting to that code (as evidenced by the fact that the log message is not printed)
Unfortunately, I don't have a good small reproducible example. If I had one, I could probably debug and find out what the issue is. It happens maybe 1% of the time.
The generic structure looks like:
private async Task<bool> Foo()
{
try
{
return (await Bar()).Value;
}
catch (Exception e)
{
LogError();
return false;
}
}
private async Task<bool> Bar()
{
// workQueue uses an ActionBlock to run tasks
var tasks = workToDo.Select(item => await workQueue.ProcessItem(item, DoWorkOnItem));
await Task.WhenAll(tasks);
}
async Task<bool> DoWorkOnItem(Item i)
{
var convertedStatements = i.Select(s => ConvertStatement(s, context)).Where(s => s != null).ToList();
var statementArray = ConvertedStatement.FlattenStatements(convertedStatements).ToArray(); // This is where the exception is hit
}
public static IList<Statement> FlattenStatements(ICollection<ConvertedStatement> convertedStatements)
{
Contract.Requires(convertedStatements != null);
var result = new List<Statement>(convertedStatements.Count);
foreach (var statement in convertedStatements)
{
// m_statement is only set in the constructor of Statement
if (statement.m_statement != null)
{
result.Add(statement.m_statement);
}
else
{
// m_statements is a read-only list of Statement, only set in the constructor of Statement
result.AddRange(statement.m_statements);
}
}
return result;
}
Should I be adding a try catch inside the queued task? When it prints the full exception of the internal CLR error, that trace does not include Foo(), it goes up throw the action block like this:
at BuildXL.FrontEnd.Sdk.SourceFileProcessingQueue`1[[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ProcessWorkItem(QueueInput`1<Boolean,Boolean>)
at System.Threading.Tasks.Dataflow.ActionBlock`1[[BuildXL.FrontEnd.Sdk.SourceFileProcessingQueue`1+QueueInput`1[[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], BuildXL.FrontEnd.Sdk, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6212d9137135ce5d]].ProcessMessageWithTask(System.Func`2<QueueInput`1<Boolean,Boolean>,System.Threading.Tasks.Task>, System.Collections.Generic.KeyValuePair`2<QueueInput`1<Boolean,Boolean>,Int64>)
at System.Threading.Tasks.Dataflow.ActionBlock`1+<>c__DisplayClass6_1[[BuildXL.FrontEnd.Sdk.SourceFileProcessingQueue`1+QueueInput`1[[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], BuildXL.FrontEnd.Sdk, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6212d9137135ce5d]].<.ctor>b__2(System.Collections.Generic.KeyValuePair`2<QueueInput`1<Boolean,Boolean>,Int64>)
at System.Threading.Tasks.Dataflow.Internal.TargetCore`1[[BuildXL.FrontEnd.Sdk.SourceFileProcessingQueue`1+QueueInput`1[[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], BuildXL.FrontEnd.Sdk, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6212d9137135ce5d]].ProcessMessagesLoopCore()
at System.Threading.Tasks.Task.InnerInvoke()
at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(System.Threading.Thread, System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(System.Threading.Tasks.Task ByRef, System.Threading.Thread)
at System.Threading.ThreadPoolWorkQueue.Dispatch()
That makes me think the try catch should be in DoWorkOnItem, not Foo. Does that sound right?
This looks like a legit internal error. If you search for the error code you'll find instances of this appearing, followed by fixes by Microsoft.
Can an internal clr exception be caught and retried?
I'm curious, have you tried it? What was your result?
This isn't a FileNotFoundException
, which you might correctly think you could retry. It's problematic, as you don't know how badly the CLR/execution engine's internal state might be damaged. Retrying could get you another exception, or merely incorrect results.
In short, if you're using the latest release, the right thing to do is probably to report it to Microsoft.
User contributions licensed under CC BY-SA 3.0