【发布时间】:2023-04-03 18:01:01
【问题描述】:
我们正在为 ASP.NET 应用程序使用进程外会话提供程序 (ScaleOut),我们注意到 when 对象不正确反序列化设置无意中进入会话,它将最终导致整个进程终止。
重现和处理这个场景变得更加有趣。
终止进程的异常在 AnyStaObjectsInSessionState 中引发,其实现非常简单:
internal static bool AnyStaObjectsInSessionState(HttpSessionState session)
{
if (session != null)
{
int count = session.Count;
for (int i = 0; i < count; i++)
{
object obj2 = session[i];
if (((obj2 != null) && (obj2.GetType().FullName == "System.__ComObject"))
&& (UnsafeNativeMethods.AspCompatIsApartmentComponent(obj2) != 0))
{
return true;
}
}
}
return false;
}
这是显示异常如何终止进程的堆栈跟踪:
An unhandled exception occurred and the process was terminated.
Application ID: /LM/W3SVC/1/ROOT
Process ID: 4208
Exception: System.Runtime.Serialization.SerializationException
Message: The constructor to deserialize an object of type 'Lucene.Net.QueryParsers.ParseException' was not found.
StackTrace: at System.Runtime.Serialization.ObjectManager.CompleteISerializableObject(Object obj, SerializationInfo info, StreamingContext context)
at System.Runtime.Serialization.ObjectManager.FixupSpecialObject(ObjectHolder holder)
at System.Runtime.Serialization.ObjectManager.DoFixups()
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Web.Util.AltSerialization.ReadValueFromStream(BinaryReader reader)
at System.Web.SessionState.SessionStateItemCollection.ReadValueFromStreamWithAssert()
at System.Web.SessionState.SessionStateItemCollection.DeserializeItem(String name, Boolean check)
at System.Web.SessionState.SessionStateItemCollection.DeserializeItem(Int32 index)
at System.Web.SessionState.SessionStateItemCollection.get_Item(Int32 index)
at System.Web.SessionState.HttpSessionStateContainer.get_Item(Int32 index)
at System.Web.Util.AspCompatApplicationStep.AnyStaObjectsInSessionState(HttpSessionState session)
at System.Web.HttpApplicationFactory.FireSessionOnEnd(HttpSessionState session, Object eventSource, EventArgs eventArgs)
at System.Web.SessionState.SessionOnEndTargetWorkItem.RaiseOnEndCallback()
at System.Web.Util.WorkItem.CallCallbackWithAssert(WorkItemCallback callback)
at System.Threading.ExecutionContext.runTryCode(Object userData)
at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallbackInternal(_ThreadPoolWaitCallback tpWaitCallBack)
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback(Object state)
InnerException: System.Runtime.Serialization.SerializationException
Message: The constructor to deserialize an object of type 'Lucene.Net.QueryParsers.ParseException' was not found.
StackTrace: at System.Runtime.Serialization.ObjectManager.GetConstructor(Type t, Type[] ctorParams)
at System.Runtime.Serialization.ObjectManager.CompleteISerializableObject(Object obj, SerializationInfo info, StreamingContext context)
我们想了解两件事:
FireSessionOnEnd 何时触发进程外提供程序,更重要的是,我们如何在未负载的开发环境中模拟这一点?我尝试过降低会话超时(设置为一分钟)、手动调用 Abandon() 和手动调用 GC.Collect(),但均无济于事。
我们能否捕获在此步骤中发生的错误以保护应用程序池?此处引发的异常使用 Source=ASP.NET 2.0.50727.0 进行记录,并且不会到达 global.asax 中的应用程序错误处理程序。即使在对会话绑定对象应用了适当的制衡机制之后,我们可以做些什么来防止这种情况发生?
我们将不胜感激。
【问题讨论】:
-
也许他们应该修复他们的代码以不允许序列化异常导致 AppDomain 崩溃。只是一个想法。
-
这是个好主意,我认为他们同意;这是一种极为罕见的情况,但仍应加以防范。
-
@John:看起来他正在使用 Lucene.net。虽然它是第 3 方应用程序,AFAIK,它的开源,他应该标记违规类
Serializable -
你说得对,应该由 ScaleOut 产品的供应商来防范它。
标签: asp.net session serialization httpmodule restart