Permalink
Browse files

Fixing race condition between mkdir and event listener registration i…

…n pidfiles and logger plugins.
  • Loading branch information...
1 parent 2a3e68b commit ab8e34946363faf01b4453cda3df6cb8045344d4 @koudelka committed Nov 3, 2011
Showing with 121 additions and 99 deletions.
  1. +80 −81 lib/plugins/logger.js
  2. +15 −17 lib/plugins/pidfiles.js
  3. +26 −1 lib/utils.js
View
161 lib/plugins/logger.js
@@ -11,7 +11,7 @@
var fs = require('fs')
, Log = require('log')
- , mkdir = require('mkdirp').mkdirp;
+ , mkdir = require('utils').mkdirPSync;
@telendt
telendt Dec 20, 2011

why not mkdir = require('mkdirp').mkdirp.sync?

@koudelka
koudelka Dec 20, 2011

I wasn't aware of that, was it added in a recent version of node? (also, cluster seems to be abandoned, or something)

/**
* Enable stdout / stderr logs for both the master
@@ -47,104 +47,103 @@ module.exports = function(dir, level){
return function(master){
dir = master.resolve(dir || 'logs');
- mkdir(dir, 0755, function(err){
- if (err) throw err;
- // master log
- var stream = fs.createWriteStream(dir + '/master.log', { flags: 'a' });
- var log = master.log = new Log(level || Log.INFO, stream);
+ mkdir(dir, 0755);
- // master events
- master.on('start', function(){
- log.info('master started');
- });
+ // master log
+ var stream = fs.createWriteStream(dir + '/master.log', { flags: 'a' });
+ var log = master.log = new Log(level || Log.INFO, stream);
- // master is shutting down
- master.on('closing', function(){
- log.warning('shutting down master');
- });
+ // master events
+ master.on('start', function(){
+ log.info('master started');
+ });
- // master has closed and performed cleanup
- master.on('close', function(){
- log.info('shutdown complete');
- });
+ // master is shutting down
+ master.on('closing', function(){
+ log.warning('shutting down master');
+ });
- // sending signal to all workers
- master.on('kill', function(sig){
- log.warning('sent kill(%s) to all workers', sig);
- });
+ // master has closed and performed cleanup
+ master.on('close', function(){
+ log.info('shutdown complete');
+ });
- // worker was killed
- master.on('worker killed', function(worker){
- if ('restarting' == master.state) return;
- log.error('worker %s died', worker.id);
- });
+ // sending signal to all workers
+ master.on('kill', function(sig){
+ log.warning('sent kill(%s) to all workers', sig);
+ });
- // worker exception
- master.on('worker exception', function(worker, err){
- log.error('worker %s uncaught exception %s', worker.id, err.message);
- });
+ // worker was killed
+ master.on('worker killed', function(worker){
+ if ('restarting' == master.state) return;
+ log.error('worker %s died', worker.id);
+ });
- // worker is waiting on connections to be closed
- master.on('worker waiting', function(worker, connections){
- log.info('worker %s waiting on %s connections', worker.id, connections);
- });
+ // worker exception
+ master.on('worker exception', function(worker, err){
+ log.error('worker %s uncaught exception %s', worker.id, err.message);
+ });
- // worker has timed out
- master.on('worker timeout', function(worker, timeout){
- log.warning('worker %s timed out after %sms', worker.id, timeout);
- });
+ // worker is waiting on connections to be closed
+ master.on('worker waiting', function(worker, connections){
+ log.info('worker %s waiting on %s connections', worker.id, connections);
+ });
- // worker connected to master
- master.on('worker connected', function(worker){
- log.debug('worker %s connected', worker.id);
- });
+ // worker has timed out
+ master.on('worker timeout', function(worker, timeout){
+ log.warning('worker %s timed out after %sms', worker.id, timeout);
+ });
- // cyclic or immediate restart
- master.on('cyclic restart', function(){
- log.warning('cyclic restart detected, restarting in %sms'
- , master.options['restart timeout']);
- });
+ // worker connected to master
+ master.on('worker connected', function(worker){
+ log.debug('worker %s connected', worker.id);
+ });
- // restart requested
- master.on('restarting', function(){
- log.info('restart requested');
- });
+ // cyclic or immediate restart
+ master.on('cyclic restart', function(){
+ log.warning('cyclic restart detected, restarting in %sms'
+ , master.options['restart timeout']);
+ });
- // restart complete
- master.on('restart', function(){
- log.info('restart complete');
- });
+ // restart requested
+ master.on('restarting', function(){
+ log.info('restart requested');
+ });
+
+ // restart complete
+ master.on('restart', function(){
+ log.info('restart complete');
+ });
- // repl socket connection established
- master.on('repl socket', function(sock){
- var from = sock.remoteAddress
- ? 'from ' + sock.remoteAddress
- : '';
- sock.on('connect', function(){
- log.info('repl connection %s', from);
- });
- sock.on('close', function(){
- log.info('repl disconnect %s', from);
- });
+ // repl socket connection established
+ master.on('repl socket', function(sock){
+ var from = sock.remoteAddress
+ ? 'from ' + sock.remoteAddress
+ : '';
+ sock.on('connect', function(){
+ log.info('repl connection %s', from);
});
+ sock.on('close', function(){
+ log.info('repl disconnect %s', from);
+ });
+ });
- // override fds
- master.customFds = [-1, -1];
+ // override fds
+ master.customFds = [-1, -1];
- // children
- master.on('worker', function(worker){
- var proc = worker.proc;
+ // children
+ master.on('worker', function(worker){
+ var proc = worker.proc;
- log.info('spawned worker ' + worker.id);
+ log.info('spawned worker ' + worker.id);
- // worker log streams
- var access = fs.createWriteStream(dir + '/workers.access.log', { flags: 'a' })
- , error = fs.createWriteStream(dir + '/workers.error.log', { flags: 'a' });
+ // worker log streams
+ var access = fs.createWriteStream(dir + '/workers.access.log', { flags: 'a' })
+ , error = fs.createWriteStream(dir + '/workers.error.log', { flags: 'a' });
- // redirect stdout / stderr
- proc.stdout.pipe(access);
- proc.stderr.pipe(error);
- });
+ // redirect stdout / stderr
+ proc.stdout.pipe(access);
+ proc.stderr.pipe(error);
});
}
-};
+};
View
32 lib/plugins/pidfiles.js
@@ -10,7 +10,7 @@
*/
var fs = require('fs')
- , mkdir = require('mkdirp').mkdirp;
+ , mkdir = require('utils').mkdirPSync;
/**
* Save pidfiles to the given `dir` or `./pids`.
@@ -59,25 +59,23 @@ module.exports = function(dir){
});
};
- mkdir(dir, 0755, function(err){
- if (err) throw err;
+ mkdir(dir, 0755);
- // save worker pids
- master.on('worker', function(worker){
- var path = dir + '/worker.' + worker.id + '.pid';
- fs.writeFile(path, worker.proc.pid.toString(), 'ascii', function(err){
- if (err) throw err;
- master.emit('worker pidfile');
- });
+ // save worker pids
+ master.on('worker', function(worker){
+ var path = dir + '/worker.' + worker.id + '.pid';
+ fs.writeFile(path, worker.proc.pid.toString(), 'ascii', function(err){
+ if (err) throw err;
+ master.emit('worker pidfile');
});
+ });
- master.on('listening', function(){
- // save master pid
- fs.writeFile(dir + '/master.pid', process.pid.toString(), 'ascii', function(err){
- if (err) throw err;
- master.emit('pidfile');
- });
+ master.on('listening', function(){
+ // save master pid
+ fs.writeFile(dir + '/master.pid', process.pid.toString(), 'ascii', function(err){
+ if (err) throw err;
+ master.emit('pidfile');
});
});
}
-};
+};
View
27 lib/utils.js
@@ -5,6 +5,10 @@
* MIT Licensed
*/
+
+var path = require('path')
+ , fs = require('fs');
+
/**
* Frame the given `obj`.
*
@@ -95,4 +99,25 @@ exports.unshiftListener = function(obj, event, fn){
} else {
obj._events[event] = [fn, obj._events[event]];
}
-};
+};
+
+
+/**
+ * `mkdir -p`, synchronously
+ *
+ * @param {String} dir
+ * @param {String} mode
+ * @api private
+ */
+
+exports.mkdirPSync = function(dir, mode) {
+ var buildingPath = [],
+ components = path.normalize(dir).split('/');
+
+ components.slice(1, components.length).forEach(function(component) {
+ buildingPath = buildingPath.concat(component);
+ var toCreate = '/' + buildingPath.join('/');
+ if (!path.existsSync(toCreate))
+ fs.mkdirSync('/' + buildingPath.join('/'), mode);
+ });
+};

0 comments on commit ab8e349

Please sign in to comment.