From e898b07573dfcd4a31be8c0c51bca5ed61bc42ca Mon Sep 17 00:00:00 2001 From: tknew2 Date: Mon, 11 Aug 2014 15:21:59 +0200 Subject: [PATCH] memory leak fix --- examples/auto-save.js | 30 ------------------ examples/keymetrics-test.js | 24 ++++++++------ lib/CLI.js | 4 +++ lib/God.js | 63 +++++++++++++++++++------------------ lib/God/ClusterMode.js | 8 ++--- lib/God/ForkMode.js | 7 ++--- 6 files changed, 55 insertions(+), 81 deletions(-) diff --git a/examples/auto-save.js b/examples/auto-save.js index 79de09f5..e69de29b 100644 --- a/examples/auto-save.js +++ b/examples/auto-save.js @@ -1,30 +0,0 @@ - - -// Expose action -// And "touch" file every 1.4s to restart the file - -var axm = require('axm'); - -function makeid() { - var text = ""; - var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - - for( var i=0; i < 5; i++ ) - text += possible.charAt(Math.floor(Math.random() * possible.length)); - - return text; -} - - -axm.action('cmd:' + makeid(), {comment : 'Refresh main database'}, function(reply) { - console.log('Refreshing'); - reply({success : true}); - }); - -setTimeout(function() { - var fs = require('fs'); - - - var a = fs.readFileSync(__filename); - fs.writeFileSync(__filename, a); -}, 1400); diff --git a/examples/keymetrics-test.js b/examples/keymetrics-test.js index d5e623cf..c5244dcd 100644 --- a/examples/keymetrics-test.js +++ b/examples/keymetrics-test.js @@ -4,20 +4,24 @@ var pm2 = require('..'); pm2.connect(function() { pm2.delete('all', function() { pm2.start('examples/human_event.js', function() { - pm2.start('examples/child.js', {instances:2},function() { - pm2.start('examples/custom_action.js', function() { - pm2.start('examples/custom_action_with_params.js', function() { - pm2.start('examples/auto-save.js', {watch : true, name :'auto-save-modify'}, function() { - pm2.start('examples/http-trace.js', {name:'trace'}, function() { - //pm2.start('examples/auto-bench.js', {instances : 'max'}, function() { - pm2.start('examples/throw.js', {name:'auto-throw'}, function() { - pm2.disconnect(function() { process.exit(1); }); + pm2.start('examples/child.js', {instances:2},function() { + pm2.start('examples/custom_action.js', function() { + pm2.start('examples/custom_action.js', {execMode : 'fork', force : true}, function() { + pm2.start('examples/auto-save.js', {execMode : 'fork', watch:true, force : true}, function() { + pm2.start('examples/custom_action_with_params.js', function() { + pm2.start('examples/auto-save.js', {watch : true,force:true, name :'auto-save-modify'}, function() { + pm2.start('examples/http-trace.js', {name:'trace'}, function() { + //pm2.start('examples/auto-bench.js', {instances : 'max'}, function() { + pm2.start('examples/throw.js', {name:'auto-throw'}, function() { + pm2.disconnect(function() { process.exit(1); }); + }); + //}); }); - //}); + }); + }); }); }); }); - }); }); }); }); diff --git a/lib/CLI.js b/lib/CLI.js index 15ef31cc..7b15901d 100644 --- a/lib/CLI.js +++ b/lib/CLI.js @@ -89,6 +89,10 @@ CLI.start = function(script, opts, cb) { appConf['exec_interpreter'] = 'node'; } + if (opts.execMode) { + appConf['exec_mode'] = opts.execMode; + } + // if (appConf['exec_mode'] == 'cluster_mode' && process.version.match(/0.10/)) { // printOut(cst.PREFIX_MSG_ERR + ' [Warning], you\'re using the 0.10.x node version, it\'s prefered that you switch to fork mode by adding the -x parameter.'); // } diff --git a/lib/God.js b/lib/God.js index c1ac5c41..0ec55afd 100644 --- a/lib/God.js +++ b/lib/God.js @@ -1,8 +1,3 @@ -'use strict'; - -/** - * Module dependencies - */ var cluster = require('cluster'); var numCPUs = require('os').cpus() ? require('os').cpus().length : 1; @@ -30,8 +25,7 @@ var God = module.exports = { bus : new EventEmitter2({ wildcard: true, delimiter: ':', - newListener: false, - maxListeners: 20 + maxListeners: 1000 }) }; @@ -44,22 +38,6 @@ require('./God/ClusterMode.js')(God); require('./God/Reload')(God); require('./God/ActionMethods')(God); -/** - * Forced entry to initialize cluster monitoring - */ - -(function initEngine() { - cluster.on('online', function(clu) { - console.log('%s - id%d worker online', clu.pm2_env.pm_exec_path, clu.pm2_env.pm_id); - clu.pm2_env.status = cst.ONLINE_STATUS; - God.bus.emit('process:online', { process : clu }); - }); - - cluster.on('exit', function(clu, code, signal) { - handleExit(clu, code); - }); -})(); - /** * Handle logic when a process exit (Node or Fork) * @method handleExit @@ -136,8 +114,6 @@ function handleExit(clu, exit_code) { God.executeApp = function(env, cb) { var env_copy = JSON.parse(JSON.stringify(env)); - util._extend(env_copy, env.env); - env_copy['axm_actions'] = []; if (env_copy['pm_id'] === undefined) { @@ -179,17 +155,21 @@ God.executeApp = function(env, cb) { God.forkMode(env_copy, function(err, clu) { if (cb && err) return cb(err); - God.clusters_db[env_copy.pm_id] = clu; + var old_env = God.clusters_db[clu.pm2_env.pm_id]; + if (old_env) old_env = null; + + var proc = God.clusters_db[env_copy.pm_id] = clu; clu.once('error', function(err) { - clu.pm2_env.status = cst.ERRORED_STATUS; + proc.pm2_env.status = cst.ERRORED_STATUS; }); clu.once('close', function(code) { - handleExit(clu, code); + proc.removeAllListeners(); + return handleExit(proc, code); }); - God.bus.emit('process:online', {process : clu }); + God.bus.emit('process:online', {process : proc}); if (cb) cb(null, clu); return false; @@ -202,8 +182,29 @@ God.executeApp = function(env, cb) { God.nodeApp(env_copy, function(err, clu) { if (cb && err) return cb(err); if (err) return false; - God.clusters_db[clu.pm2_env.pm_id] = clu; - if (cb) cb(null, clu); + + var old_env = God.clusters_db[clu.pm2_env.pm_id]; + if (old_env) old_env = null; + + var proc = God.clusters_db[clu.pm2_env.pm_id] = clu; + + clu.once('online', function() { + proc.pm2_env.status = cst.ONLINE_STATUS; + + console.log('%s - id%d worker online', proc.pm2_env.pm_exec_path, proc.pm2_env.pm_id); + + God.bus.emit('process:online', { process : proc }); + + if (cb) return cb(null, proc); + return false; + }); + + clu.once('exit', function(exited_clu, code) { + proc.removeAllListeners(); + return handleExit(proc, code); + }); + + if (cb) return cb(null, proc); return false; }); } diff --git a/lib/God/ClusterMode.js b/lib/God/ClusterMode.js index ec133d5a..2986cd4a 100644 --- a/lib/God/ClusterMode.js +++ b/lib/God/ClusterMode.js @@ -69,13 +69,9 @@ module.exports = function(God) { }); // Avoid circular dependency - delete clu.process._handle.owner; + // delete clu.process._handle.owner; - clu.once('online', function() { - clu.pm2_env.status = cst.ONLINE_STATUS; - if (cb) return cb(null, clu); - return false; - }); + return cb(null, clu); return false; }; }; diff --git a/lib/God/ForkMode.js b/lib/God/ForkMode.js index 30188b49..95d162dc 100644 --- a/lib/God/ForkMode.js +++ b/lib/God/ForkMode.js @@ -100,7 +100,7 @@ module.exports = function(God) { stdio : ['ipc', null, null] }); } catch(e) { - console.error(e.stack || e); + God.logAndGenerateError(e); if (cb) return cb(e); } @@ -124,7 +124,7 @@ module.exports = function(God) { }); cspr.stdout.on('data', function(data) { - + var log_data = data.toString(); if (pm2_env.log_date_format) log_data = moment().format(pm2_env.log_date_format) + ': ' + log_data; @@ -150,12 +150,11 @@ module.exports = function(God) { try { stderr.close(); stdout.close(); - } catch(e) { console.error(e.stack || e);} + } catch(e) { God.logAndGenerateError(e);} }); cspr._reloadLogs = startLogging; - cspr.unref(); if (cb) return cb(null, cspr);