精简Chromium代码仓库进行维护与升级

Chromium的代码仓库很大,我最近更新了一下,现在git仓库里面pack文件已经有8.8GB了。然而网络又不稳定,要完整获取如此大的代码还是比较困难。 我最推荐的方式是用阿里云香港或者新加坡的服务器搭建VPN,连接VPN来获取代码。阿里云香港或者新加坡的的VPN速度很快很稳定,我自己这边下载代码的速度有2MB/s,非常快。 其次是搭建Chromium代码仓库的mirror。这种方法对服务器的配置要求很高,4GB的内存只能支持不超过2个人同时获取代码。维护也比较麻烦,要成功编译Chromium,除了Chromium仓库,还有各种第三方仓库还有其他文件都需要做mirror。 如果不是很需要Chromium代码的历史提交记录,我们可以从Chromium代码的一个tag里面拉出代码,再提交到我们的自己的git仓库里面。这样的git仓库有700MB左右大小,只有Chromium的十分之一。 比如我们从Chromium的60.0.3112.113... Read More | Share it now!

Chromium代码注释中的ascii图

我们在Chromium的代码注释里经常能够看到使用纯ascii字符做的示意图,如下所示: chrome\browser\ui\views\frame\browser_view.h components\update_client\background_downloader_win.cc components\update_client\crx_update_item.h media\cast\sender\performance_metrics_overlay.h v8\src\compiler\osr.h 这些图都是用ascii字符组成的,因此很容易结合在源代码里面,形象的描述了代码的逻辑。 如果自己手动敲出这些ascii图,当然很麻烦了,幸好有这方面的工具帮助我们画出ascii图来。 最方便的是这个http://asciiflow.com/... Read More | Share it now!

Chromium installer介绍

mini_installer是Chromium的安装和升级系统的一部分。它的有两个主要作用: 从自身资源中抽取出chrome.packed.7z和setup.exe程序 调用setup.exe进行实际的安装操作 mini_installer很小 mini_installer之所以叫mini,是因为它真的很小。除去资源的大小,它本身大约只有5kb,而我们创建一个空的控制台的程序也有100多kb。 mini_installer做的这么小的原因是:Chromium的差量升级包实际上也是一个mini_installer。为了使差量包尽可能的小,所以mini_installer本身也要非常小。 mini_installer只是一个壳,本身并没有很复杂的逻辑,它是调用setup.exe做真正的安装和升级逻辑。另外它还没有链接CRT库。没有链接CRT库带来了一个副作用就是不能调用CRT库里面的函数,只能调用Windows... Read More | Share it now!

Chromium不再支持GDI渲染字体

因为Chromium不再支持XP/VISTA系统,顺便的Chromium从52开始强制使用DirectWrite渲染字体,也不再支持GDI渲染字体。 不过据我来看,目前Chromium使用DirectWrite渲染字体并不稳定,经常会导致崩溃,比如IDWriteFactory2接口不支持低于win8.1的系统,而Chromium代码对这个没有区分操作系统,因此会导致win7上DWrite初始化失败的问题。Chromium最新版60还没有解决DirectWrite崩溃的问题,代码里面仍然还有FontCache::CrashWithFontInfo用来收集字体崩溃的信息。 不过有很多人想让Chromium加回对GDI渲染字体的支持,在Chromium-dev里面发帖要求,见 https://groups.google.com/a/chromium.org/forum/#!topic/chromium-dev/WzivQg8_drw ... Read More | Share it now!

windows的兼容模式

Windows从Vista之后,新增了一个应用程序的兼容模式。比如程序在XP系统下面可以正常运行,但是系统升级到Win7之后,调用的一个XP的系统接口在Win7系统里不存在或者接口行为或者参数意义发生了改变,这样程序运行的时候就会发生崩溃或者异常。兼容模式就是让程序不变的情况下,操作系统自己去兼容程序的API调用。 我们在Win7上面右键菜单查看属性,选择兼容性,可以看到如下图所示: 选择兼容模式,就可以让应用程序兼容所选定的操作系统运行。 比如我们选择兼容Windows... Read More | Share it now!

调试Utility进程崩溃

M55内核升级中发现Utility进程崩溃很多。以前Utility进程的崩溃只占到总崩溃量1%不到,现在却增加到了10%以上。 Utility进程崩溃的堆栈都很类似,如下: 我们看0号线程,也就是主线程。这个调用栈没有wMain函数,却有exit函数。可以看出来程序崩溃在进程退出的时候。最后的我们的代码崩溃帧是在BrokerServicesBase::~BrokerServicesBase里面,其代码如下: 我认为0号线程是正常的。我们再看1号线程。1号线程是程序发生异常,生成dump的线程。可以看到是ntdll!TppWaiterpThread引发了ntdll!KiUserExceptionDispatcher。好奇怪,异常竟然来自系统模块。我们看下Windbg的dump分析: 可以看到ExceptionCode的值为c000070a,查一下ntstatus.h头文件,值c000070a表示STATUS_THREADPOOL_HANDLE_EXCEPTION,意思是线程池等待的句柄异常,可以看到句柄是0000012c。 然后用!handle命令行查看一下进程当前拥有的句柄情况: 可以看到进程句柄表里面并没有0000012c句柄。因此我猜测可能是因为0000012c句柄已经关闭了,而TppWaiterpThread还在使用0000012c这个无效的句柄导致的异常。 因此我想收集一下句柄分配和释放的信息,然后根据dump查看一下无效的句柄是怎么分配和释放的。幸好chromium里面有一个ActiveVerifier机制,ActiveVerifier是用来跟踪句柄使用情况的,它跟踪了一部分句柄创建的和Hook了CloseHandle函数。在StartTracking和CloseHandle里面加一个我自己写的LogHandle函数,这个函数会把句柄分配和释放的StackTrace跟进句柄值记录到环境变量中。 因为Utility进程创建和释放的句柄并不多,所以把这个调试信息放在环境变量中是方便和合适的。 灰度出去,收集崩溃信息。这次果然收集到了有用的信息,先看dump分析: 这次异常的句柄值是00000198,再看看环境变量中的调试信息: 00000198果然被CloseHandle了。然后根据后面的地址查看关闭的调用栈: 从代码里面可以看到00000198句柄已经随着ChildProcess的析构而关闭变成无效了,其他地方继续使用这个句柄是有问题的。 00000198句柄是ChildProcess的shutdown_event_成员变量。这个shutdown_event_会被ChildThreadImpl传递给其IPC::SyncChannel的channel_成员。而SyncChannel的shutdown_watcher_会调用系统的RegisterWaitForSingleObject去利用线程池去等待00000198句柄对应Event。 所以问题的根源是ChildProcess的析构函数CloseHandle了shutdown_event_,但是SyncChannel里面的shutdown_watcher_通过RegisterWaitForSingleObject继续等待shutdown_event_句柄。MSDN里RegisterWaitForSingleObjec介绍说:If... Read More | Share it now!