2023年12月11日发(作者:)

Cache的Insert和Add方法引发的血案

Cache的Insert 和Add 方法引发的血案

把一个简单的CMS系统拷贝到阿里云2008服务器上后,执行一个页面操作的时候,第一次操作正常,第二次或者第三次的时候,IIS就假

死。查看日志:“**错误应用程序名称: ,版本: 7.5.7601.17514,时间戳: 0x4ce7a5f8

错误模块名称: ,版本: 6.1.7601.19045,时间戳: 0x56258f05**”“错误存储段 ,类型 0 事件名称: APPCRASH

响应: 不可用”。

百度了一下,各种说法都有,有说权限不够的,有说程序有错误的。于是各种权限实验,还是报同样的错误。注意到其中有一条是说,程序

里面有死循环所以导致溢出。联想到程序在2003下跑得欢快,而且每次都是点特定的页面第二三次,iis才crash。

开始测试数据库是否正常。自己写了和crash页面相同功能的操作,实验多次,发现不是数据库问题。那么应该是代码问题了。不过没有源

码啊没有源码。没有办法只有反对编译,使用ILSpy 反编译代码。

看源代码好像没有什么问题啊,很简单,就是获取参数,然后塞入数据库。

没法子,把源代码拷贝出来,直接放在aspx运行,还是crash,把怀疑的注释掉,终于在我注释掉一个

ListToCache();

后IIS的日志里面再也没有crash了。再反编译这个方法其实是调用了一个Cache类,再反编译:

“`

public class NewsCache

{

private static object syncObj;

protected int _timeOut = 6000;

protected static volatile Cache webCache;

public int TimeOut

{

get

{

return (this._timeOut > 0) ? this._timeOut : 6000;

}

set

{

this._timeOut = ((value > 0) ? value : 6000);

}

}

public static Cache GetNewsCache

{

get

{

return he;

}

}

static NewsCache()

{

j = new object();

he = null;

he = ;

lock (j)

{

HttpContext current = t;

if (current != null)

{

he = ; } else { he = ; } } } public void AddObject(string objId, object o) { if (objId != null && != 0 && o != null) { CacheItemRemovedCallback cacheItemRemovedCallback = new CacheItemRemovedCallback(ve); if (t == 60) { // if (he[objId] == null) //{ (objId, o, null, ue, , , cacheItemRemovedCallback); //} } else { // if (he[objId] == null) // { (objId, o, null, utes((double)t), ingExpiration, , cacheItemRemovedCallback); // } } } } public void onRemove(string key, object val, CacheItemRemovedReason reason) { switch ((int)reason) { case 1: { CacheItemRemovedCallback cacheItemRemovedCallback = new CacheItemRemovedCallback(ve); (key, val, null, utes((double)t), ingExpiration, , cacheItemRemovedCallback); break; } case 2: { CacheItemRemovedCallback cacheItemRemovedCallback2 = new CacheItemRemovedCallback(ve); (key, val, null, utes((double)t), ingExpiration, , cacheItemRemovedCallback2); break; } case 3: { CacheItemRemovedCallback cacheItemRemovedCallback3 = new CacheItemRemovedCallback(ve); (key, val, null, utes((double)t), ingExpiration, , cacheItemRemovedCallback3); break; } } } public void RemoveObject(string objId) { if (objId != null && != 0) { (objId); } } public object RetrieveObject(string objId)

{

object result;

if (objId == null || == 0)

{

result = null;

}

else

{

result = (objId);

}

return result;

}

}

值得注意的是这个Cache类Insert的时候传入的一个回掉事件,在回掉事件里面又把Cache的数据赛进去了,大概是想这个Cache永远不过

期吧。

是的这个类AddObject 方法如果你多次叫用之后IIS就会挂掉,onRemove 会不挺的被调用。换句说就是对于Cache来说如果你多次调用

Insert方法,而且Insert后面有回掉事件的话,这个事件就会被执行。之前的程序员在onRemove 里面又Insert了一次,于是这个

onRemove 就死循环了。奇怪的是这个问题在IIS 6上并不会发生或者说在win 2003 server的IIS 6 的.Net 2.0 上并不会发生。在IIS 7 或

者 7.5 的 .Net 2.0 上会发生。

当然解决的办法是把Insert换成Add,或者在Insert的时候判断一次这个Cache是否为Null。

**百度上解释的Cache 的Insert 方法是先移除再添加数据,不过msdn上没有提到insert多次会触发回掉事件。

Add 是如果有同名的键会有异常,实验证明Add有同名的也不会报错。**

最后:

ILSpy真是个好东西,反编译很棒,还免费的

Aspx文件去掉 Page language=”c#” Codebehind=”” YouClass就可以把代码写到aspx文件里面动态编

译,没有源代码,只要不太复制也可以搞定。