LINQ to SQL: intermittent AccessViolationException

2020-06-09 06:00发布

问题:

Since a few weeks we are experiencing W3WP-crashes with our ASP.Net web application. These started after our webservers were updated. Our application did not change and has been stable for years.
Our situation seems to be a lot like this earlier question. And this question might also be related, though in our case the queries run fine in 99.9% of the times used.

We use a lot of uncompiled LINQ queries and tried if compiling them would prevent these crashes. The number of crashes decreased drastically, but they still do occur.

Also wrapping our queries in a try catch and then catching the TargetInvocationException does not work. The exception is not caught.

When a crash happens, we get a WER-report and can retreive a crash dump.
A stack trace from a dump for an uncompiled query typically looks like this:

at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
at System.Delegate.DynamicInvokeImpl(Object[] args)
at System.Data.Linq.SqlClient.QueryConverter.VisitInvocation(InvocationExpression invoke)
at System.Data.Linq.SqlClient.QueryConverter.VisitInner(Expression node)
at System.Data.Linq.SqlClient.QueryConverter.VisitExpression(Expression exp)
at System.Data.Linq.SqlClient.QueryConverter.VisitBinary(BinaryExpression b)
at System.Data.Linq.SqlClient.QueryConverter.VisitInner(Expression node)
at System.Data.Linq.SqlClient.QueryConverter.VisitExpression(Expression exp)
at System.Data.Linq.SqlClient.QueryConverter.VisitBinary(BinaryExpression b)
at System.Data.Linq.SqlClient.QueryConverter.VisitInner(Expression node)
at System.Data.Linq.SqlClient.QueryConverter.Visit(Expression node)
at System.Data.Linq.SqlClient.QueryConverter.VisitWhere(Expression sequence, LambdaExpression predicate)
at System.Data.Linq.SqlClient.QueryConverter.VisitSequenceOperatorCall(MethodCallExpression mc)
at System.Data.Linq.SqlClient.QueryConverter.VisitInner(Expression node)
at System.Data.Linq.SqlClient.QueryConverter.VisitWhere(Expression sequence, LambdaExpression predicate)
at System.Data.Linq.SqlClient.QueryConverter.VisitSequenceOperatorCall(MethodCallExpression mc)
at System.Data.Linq.SqlClient.QueryConverter.VisitInner(Expression node)
at System.Data.Linq.SqlClient.QueryConverter.VisitSelect(Expression sequence, LambdaExpression selector)
at System.Data.Linq.SqlClient.QueryConverter.VisitSequenceOperatorCall(MethodCallExpression mc)
at System.Data.Linq.SqlClient.QueryConverter.VisitInner(Expression node)
at System.Data.Linq.SqlClient.QueryConverter.VisitDistinct(Expression sequence)
at System.Data.Linq.SqlClient.QueryConverter.VisitSequenceOperatorCall(MethodCallExpression mc)
at System.Data.Linq.SqlClient.QueryConverter.VisitInner(Expression node)
at System.Data.Linq.SqlClient.QueryConverter.ConvertOuter(Expression node)
at System.Data.Linq.SqlClient.SqlProvider.BuildQuery(Expression query, SqlNodeAnnotations annotations)
at System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query)
at System.Data.Linq.DataQuery'1.System.Collections.Generic.IEnumerable.GetEnumerator()
at System.Linq.Buffer'1..ctor(IEnumerable'1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable'1 source)

The stack trace from a dump for a compiled query looks like:

at System.RuntimeMethodHandle.InvokeMethod(System.Object, System.Object[], System.Signature, Boolean)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(System.Object, System.Object[], System.Object[])
at System.Delegate.DynamicInvokeImpl(System.Object[])
at System.Data.Linq.SqlClient.SqlProvider.AssignParameters(System.Data.Common.DbCommand, System.Collections.ObjectModel.ReadOnlyCollection`1, System.Object[], System.Object)
at System.Data.Linq.SqlClient.SqlProvider.Execute(System.Linq.Expressions.Expression, QueryInfo, System.Data.Linq.SqlClient.IObjectReaderFactory, System.Object[], System.Object[], System.Data.Linq.SqlClient.ICompiledSubQuery[], System.Object)
at System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(System.Linq.Expressions.Expression, QueryInfo[], System.Data.Linq.SqlClient.IObjectReaderFactory, System.Object[], System.Data.Linq.SqlClient.ICompiledSubQuery[])
at System.Data.Linq.SqlClient.SqlProvider+CompiledQuery.Execute(System.Data.Linq.Provider.IProvider, System.Object[])
at System.Data.Linq.CompiledQuery.ExecuteQuery(System.Data.Linq.DataContext, System.Object[])

Does anyone know what might have changed the behavior our application? We know it was "an update" (but not exactly which one), but we are more interested in it's technical background.
Of course, we would also welcome a solution to prevent our application from crashing.

回答1:

I thought I would post a solution, that we found to this issue, because we started experiencing the problem recently.

We have many servers that run our code just fine but only 1 was crashing a couple of times a week with this error. I believe this server was on .net 4.5.2.

We opened a ticket with Microsoft since the unhandled exception was happening in their stack.

They looked at our dump and came back with this solution which worked.

A new fix is available at https://support.microsoft.com/en-us/kb/3139544

It would be better if you move to .net 4.6.1

I hope this solution will help anyone else that finds themselves reading this.



回答2:

Hard to tell without seeing any of your Linq Code but I would venture a wild guess that an it's an internal (casting) error with the linq library you are using.

As you mentioned that you upgraded recently
(which .NET version did you upgrade from and to ?)

I had similar issue which was resolved by installing windows updates, which you say you have done with some resulting success?

Try to identify the user inputs that cause error. Try to handle the casting yourself rather than relying on Linq