由Resource temporarily unavailable说起

最近登录到我们前端沙盒机器上去的时候,偶尔碰到-bash: fork retry: Resource temporarily unavailable这样的错误,过一会儿就自动好了。当时不以为然,但是后面每次想用phantomjs去截图的时候,它都会出现。

首先,我们运行的简单的demo是

    var page = require('webpage').create();
    page.viewportSize = { width: 1276, height: 800};
    var url = 'https://www.baidu.com';
    page.open(url, function() {
        page.render('text.jpg');
        phantom.exit();
    });

这是一个最简单的phantomjs的demo,运行command是

    $ phantomjs test.js

运行这条命令的时候,偶尔会卡死在那儿;偶尔会报Resource temporarily unavailable的错误。
stackoverflow上去看,发现这个问题有很多的答案,大致是说进程数太多,超过了系统的限制。

所以这时候我们面临着3个问题

  • 1、如何解决进程数太多而不能再fork的问题?
  • 2、为什么phantomjs会fork新进程?
  • 3、node层有没有什么陷阱导致不断fork?

##一、如何解决进程数太多而不能再fork的问题?

按照so提供的思路,我们用ulimit把max process提高了

    $ ulimit -u 50000

然后再次运行demo,发现一点问题都没有了。虽然问题已经解决,但是还是不知道问题在哪儿。

##二、为什么phantomjs会fork进程?

首先,我们看看phantomjs入口文件 /usr/local/lib/node_modules/phantomjs/bin/phantomjs

    var binPath = require(path.join(__dirname, '..', 'lib', 'phantomjs')).path
    ...
    var cp = spawn(binPath, args)

我们可以看到,phantomjs其实只是一个壳,它真正spawn了lib/phantomjs.js这个文件。ok,既然是spawn,那就一定会fork出子进程。这会不会是被卡住的真正原因呢?我并没有深入研究…

##三、node层有没有什么陷阱导致不断fork?

如果我们在spawn、fork、或者exec的时候,没有处理好进程的销毁时间,是很有可能出现fork陷阱的。
另外,宿主进程死掉,被fork出来的进程是不会自动销毁的。
所以,一般来说,我们最好是在spawn的时候做好异常处理;或者用脚本的方式,在杀掉宿主进程的时候,同时也杀掉子进程。