文章归档

wordpress latex的bug

latex for wordpress 插件的这个bug,因为目录不可写的情况下仍然尝试从LaTex Image server获取formula image,过多的进程以及处于等待数据状态的socket,可能导致httpd进程崩溃。

昨晚休息之前手机就收到linode的警告,说DISK io rate已经超过阈值,可惜实在太累,只好倒头就睡,顾不上这么多了。早上7点多陈老师消息过来,说web服务器无法访问,而这时linode的警告又来了,这次不但说DISK,连CPU都出问题了。然后我意识到,服务器可能被攻击了。
勉强通过ssh登录vps服务器,发现一堆httpd进程,这倒没什么,top一下cpu进程持续100%,查了apache的日志,很奇怪 access_log/error_log 的内容关于 May 2这天的日志都是空的,也就是从早上凌晨开始到现在,没有一个人访问过我们的服务器,我们的RP再低,也不至于这种情况吧。。。

再看了看linode后台的监控信息:

也就是说从昨晚6点到现在,CPU一直都是满负荷的而网站几乎没什么流量。但是昨晚这个时候我恰好在撰写blog,说明server应该没啥问题的。我重启了httpd服务,再刷新一下blog,可以正常访问,但是速度很慢,这个昨晚我也明显感觉到了。

我喜欢用latex写数学公式,有时为了查错经常需要刷新页面,所以我猜测会不会是latex的js引擎渲染的问题呢,然后对比测试了一下单独开启js渲染和cache image,结果发现js渲染居然比cache image要快很多很多,但是cache image的时候并没有显示image,可能是cache目录没有写权限。
按常理来说没法理解啊呵呵,没显示我的image又耗掉我那么多性能,联系到今天server的状况,大概是latex for wordpress有问题了。这个插件做了什么事情让server变得那么慢呢?然后看了看它代码。

if (!is_file($cache_formula_path) || filesize($cache_formula_path) < 10) {
  if (!class_exists('Snoopy'))
    require_once (ABSPATH.'/wp-includes/class-snoopy.php');
  $snoopy = new Snoopy;
  $formula_text_html = str_replace('%C2%A0', '%20', 
    rawurlencode(html_entity_decode(preg_replace('/\\label{.*?}/', '', 
    $formula_text))));
  $snoopy->fetch(get_option('latex_img_server').$formula_text_html);
  if (strlen($snoopy->results) < 10)
    $snoopy->fetch('http://www.quantnet.com/cgi-bin/mathtex.cgi?'.rawurlencode(($formula_text)));
  $cache_file = fopen($cache_formula_path, 'w');
  fputs($cache_file, $snoopy->results);
  fclose($cache_file);
}

之所以会导致这个问题,是因为latex for wordpress在做缓存的时候,是不检查目录是否可写的,它只检查文件是否存在或者文件大小小于10bytes,它在目录不可写的时候仍然尝试去下载formula image。如果你的page里有很多20条latex formula的话,httpd就不得不为每个连接创建20个子进程来接收这些数据,并发的情况下可能来不及接收完毕httpd就已经僵死在那里了。
解决的办法也简单,在做缓存的时候,优先检查目录是否具有写权限,如果目录不可写,就不去获取formula image如下:

$fileRWX = fileperms($cache_path);
if (($fileRWX & 0x01B6) == 0x01B6) {
  if (!is_file($cache_formula_path) || filesize($cache_formula_path) < 10) {
    ...
  }
}

更多 fileperms 的用法,请看:http://www.php.net/fileperms

3 comments to wordpress latex的bug

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>