您的位置:首页 > 编程语言

用一行代码让w3wp进程崩溃,如何查找w3wp进程崩溃的原因

2009-12-20 20:29 483 查看
W3wp进程崩溃了,在系统日志中留下了一个错误,而留下的错误信息却很少,如何才能快速查找w3wp崩溃的原因呢?

首先,我们来写一行代码让w3wp崩溃:

viewsource

print?

1
protected
void
Page_Load(
object
sender,EventArgse)
2
{
3
ThreadPool.QueueUserWorkItem(
delegate
(
object
noUse){
throw
new
Exception(
"gotohellw3wp!"
);});
4
}
这一行代码就会让w3wp进程崩溃,因为asp.net2.0之后,微软处理多线程操作异常的默认方式发生了变化,如果在Thread,或者ThreadPool,或者System.Threading.Timer中执行方法中出现未处理异常,则当前执行进程会停止执行崩溃。

当然实际情况中我们不会故意写这么一行代码让w3wp崩溃,也许你会说,我一般情况下不在web程序中使用Thread,或者ThreadPool,即便如此,出现崩溃也是有可能的,因为数据库的连接池,HttpRuntime管理请求队列等系统方法中也会用到Thread,或者System.Threading.Timer类,或者ThreadPool。我曾经亲身遭遇到系统方法导致崩溃,是因为sqlserver的数据库连接池被耗尽,取不出新的数据库连接而导致崩溃,这和以上一行代码导致崩溃的原理是一样的。

可以这么说这种崩溃是一种微软设计的应该崩溃的情况,微软认为如果在多线程中执行过程中发生异常就应该让进程崩溃。而这种崩溃发生之后留下的系统日志往往很少,我们只能看到崩溃的错误,而得不到崩溃的具体点或者崩溃发生的调用堆栈。俗话说:“办法总比苦难多”,虽然系统没有记录,但是我们可以通过代码来让系统记录崩溃原因。我们有两种办法来得到崩溃原因。

第一种办法是利用反射在Global的Application_End事件中记录HttpRuntime的退出堆栈和退出原因。如果你手头有反编译的工具,你可以反编译一下System.Web.HttpRuntime类,你可以看到此类有两个私有的字段:

viewsource

print?

1
private
string
_shutDownMessage;
2
private
string
_shutDownStack;
他们记录了w3wp进程的退出消息和退出堆栈,通常我们在Application_End事件中记录这两个变量的值,就可以看到崩溃的堆栈。具体怎么做请看代码

viewsource

print?

01
protected
void
Application_End(
object
sender,EventArgse)
02
{
03
HttpRuntimeruntime=(HttpRuntime)
typeof
(System.Web.HttpRuntime).InvokeMember(
"_theRuntime"
,
04
BindingFlags.NonPublic|BindingFlags.Static|BindingFlags.GetField,
05
null
,
06
null
,
07
null
);
08
09
if
(runtime==
null
)
10
return
;
11
12
string
shutDownMessage=(
string
)runtime.GetType().InvokeMember(
"_shutDownMessage"
,
13
BindingFlags.NonPublic|BindingFlags.Instance|BindingFlags.GetField,
14
null
,
15
runtime,
16
null
);
17
18
string
shutDownStack=(
string
)runtime.GetType().InvokeMember(
19
"_shutDownStack"
,
20
BindingFlags.NonPublic|BindingFlags.Instance|BindingFlags.GetField,
21
null
,
22
runtime,
23
null
);
24
25
if
(!EventLog.SourceExists(
".NETRuntime"
))
26
{
27
28
EventLog.CreateEventSource(
".NETRuntime"
,
"Application"
);
29
30
}
31
32
EventLoglog=
new
EventLog();
33
34
log.Source=
".NETRuntime"
;
35
36
log.WriteEntry(String.Format(
"\r\n\r\n_shutDownMessage={0}\r\n\r\n_shutDownStack={1}"
,shutDownMessage,shutDownStack),EventLogEntryType.Error);
37
}
以上代码主要使用了反射,本文不做详细解释。

上面的这种方法通常情况可以得到w3wp崩溃的调用堆栈,我们还有另一种方法来获得。利用AppDomain.CurrentDomain.UnhandledException事件来记录未处理异常的发生原因,代码也很简单:

viewsource

print?

01
protected
void
Application_Start(
object
sender,EventArgse)
02
{
03
AppDomain.CurrentDomain.UnhandledException+=
new
UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
04
}
05
06
void
CurrentDomain_UnhandledException(
object
sender,UnhandledExceptionEventArgse)
07
{
08
Exceptionex=e.ExceptionObject
as
Exception;
09
string
msg=ex.Message;
10
string
stack=ex.StackTrace;
11
}
以上代码的是在ApplicationStart的时候给AppDomain的UnhandleException时间加处理方法,来记录未处理异常的发生原因。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: