<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>swigger's BLOG &#187; debug</title>
	<atom:link href="http://www.swigger.net/archives/tag/debug/feed" rel="self" type="application/rss+xml" />
	<link>http://www.swigger.net</link>
	<description>醉卧沙场君莫笑 古来征战几人回</description>
	<lastBuildDate>Tue, 24 Jan 2012 05:34:35 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>msctf导致windows UI hang住问题。</title>
		<link>http://www.swigger.net/archives/13.html</link>
		<comments>http://www.swigger.net/archives/13.html#comments</comments>
		<pubDate>Sat, 05 Apr 2008 05:58:49 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[开发]]></category>
		<category><![CDATA[debug]]></category>
		<category><![CDATA[hang]]></category>

		<guid isPermaLink="false">http://www.swigger.net/?p=13</guid>
		<description><![CDATA[最近在调试一个小程序发现，windows UI会随机性的hang住，表现为所有窗口都很能动了，做任何操作都要等半天。 在一般的用户看来，这就是windows死机了，肯定会去按reset按钮。 但要是这样就reset的话，程序就没法调试了。咱不是一般用户，自然去看一下为什么UI会hang住。首先立刻就能想到，应该是所有当前桌面的进程里，有一个dll，它在进行同步操作，而被同步的那个进程呢，恰好就是被调试进程，所以同步就失败了。这时候就会死锁。但如果WaitForobject函数超时不是无限的话，到时候还能活一下。现在这个表现，正好符合这一点，因此wait函数肯定是有限超时的。 好，拿出万能的调试器ollydbg来查吧。首先，打开一个记事本，然后用deskswitcher创建一个desktop。然后开始调试，一直调到卡住时。还好deskswitcher的快捷键还是有反应的，切换到这个新的桌面上。然后就开始调试前面这个桌面的记事本。 为什么要调记事本呢，因为它最简单，最容易找到问题。 attach上调试器后，直接break下来，看callstack，最后翻到调用wait的地方： 在输入法的msctf.dll中有如下调用： push 1388h (dec=5000) push xxx call WaitForSingleObject 可以看到，msctf里waitforsingleobject(xxx,5000), 5000就是5000毫秒就是5秒，所以做任何一个动作之后，等5秒桌面又能活一小下。再次进入这个call又要5秒。把5000改回1,切回原桌面，发现这个记录本响应很快了。其它程序还是基本不能操作，更进一步证明：问题就在这里。msctf等待一个share的对象5秒时间，但这个share对象被某进程A占用了，而A恰好又处在调试中，被调试器中断了，因此不能释放这个对象。A不能释放，其它所有进程都在等。结果当前桌面就半死锁了。之所以说是半死锁是因为还有5秒超时，要是没有超时时间的话，就是真死锁了。 知道了原因，解决方案就有了，两个方案任取其一： 新建一个桌面，在此桌面上进行其于本机的远程调试。 patch msctf.dll，把5000改成1. 即把push 1388h改成push 1。不过，这个方案需要禁用windows file protection。而且下回msctf.dll被哪个升级包升级一下又要重新改。 方案1每次都麻烦，方案2呢每升级完一次麻烦一次。不过出现这样的死锁的情况不多，暂时就用方案1好点。关于desk switcher这个软件也是有东西可以写的，且听下回分解。]]></description>
			<content:encoded><![CDATA[<p>最近在调试一个小程序发现，windows UI会随机性的hang住，表现为所有窗口都很能动了，做任何操作都要等半天。</p>
<p>在一般的用户看来，这就是windows死机了，肯定会去按reset按钮。</p>
<p>但要是这样就reset的话，程序就没法调试了。咱不是一般用户，自然去看一下为什么UI会hang住。首先立刻就能想到，应该是所有当前桌面的进程里，有一个dll，它在进行同步操作，而被同步的那个进程呢，恰好就是被调试进程，所以同步就失败了。这时候就会死锁。但如果WaitForobject函数超时不是无限的话，到时候还能活一下。现在这个表现，正好符合这一点，因此wait函数肯定是有限超时的。</p>
<p>好，拿出万能的调试器ollydbg来查吧。首先，打开一个记事本，然后用deskswitcher创建一个desktop。然后开始调试，一直调到卡住时。还好deskswitcher的快捷键还是有反应的，切换到这个新的桌面上。然后就开始调试前面这个桌面的记事本。</p>
<p>为什么要调记事本呢，因为它最简单，最容易找到问题。</p>
<p>attach上调试器后，直接break下来，看callstack，最后翻到调用wait的地方：</p>
<p>在输入法的msctf.dll中有如下调用：<br />
push 1388h (dec=5000)<br />
push xxx<br />
call WaitForSingleObject</p>
<p>可以看到，msctf里waitforsingleobject(xxx,5000), 5000就是5000毫秒就是5秒，所以做任何一个动作之后，等5秒桌面又能活一小下。再次进入这个call又要5秒。把5000改回1,切回原桌面，发现这个记录本响应很快了。其它程序还是基本不能操作，更进一步证明：问题就在这里。msctf等待一个share的对象5秒时间，但这个share对象被某进程A占用了，而A恰好又处在调试中，被调试器中断了，因此不能释放这个对象。A不能释放，其它所有进程都在等。结果当前桌面就半死锁了。之所以说是半死锁是因为还有5秒超时，要是没有超时时间的话，就是真死锁了。</p>
<p>知道了原因，解决方案就有了，两个方案任取其一：</p>
<ul>
<li>新建一个桌面，在此桌面上进行其于本机的远程调试。</li>
<li>patch msctf.dll，把5000改成1. 即把push 1388h改成push 1。不过，这个方案需要禁用windows file protection。而且下回msctf.dll被哪个升级包升级一下又要重新改。</li>
</ul>
<p>方案1每次都麻烦，方案2呢每升级完一次麻烦一次。不过出现这样的死锁的情况不多，暂时就用方案1好点。关于desk switcher这个软件也是有东西可以写的，且听下回分解。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.swigger.net/archives/13.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

