Socket
Socket
Sign inDemoInstall

node-cleanup

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

node-cleanup - npm Package Compare versions

Comparing version 2.0.0 to 2.1.0

65

node-cleanup.js

@@ -15,6 +15,14 @@ /******************************************************************************

var nodeCleanup = require('node-cleanup');
nodeCleanup(cleanupHandler, terminationMessages);
nodeCleanup(cleanupHandler, stderrMessages);
Or to only install stderr messages:
nodeCleanup() may be called multiple times to install multiple cleanup handlers. However, only the termination messages established by the first call get used.
nodeCleanup(stderrMessages);
Or to install the default stderr messages:
nodeCleanup();
nodeCleanup() may be called multiple times to install multiple cleanup handlers. However, only the most recently installed stderr messages get used. The messages available are ctrl_C and uncaughtException.
The following uninstalls all cleanup handlers and may be called multiple times in succession:

@@ -29,4 +37,6 @@

var DEFAULT_SIGINT_MSG = '[ctrl-C]';
var DEFAULT_EXCEPTION_MSG = 'Uncaught exception...';
var DEFAULT_MESSAGES = {
ctrl_C: '[ctrl-C]',
uncaughtException: 'Uncaught exception...'
};

@@ -36,3 +46,3 @@ //// CONFIGURATION ////////////////////////////////////////////////////////////

var cleanupHandlers = null; // array of cleanup handlers to call
var exceptionMessage = null; // stderr message for uncaught exceptions
var messages = null; // messages to write to stderr

@@ -46,3 +56,3 @@ var sigintHandler; // POSIX signal handlers

function signalHandler(signal, message)
function signalHandler(signal)
{

@@ -55,4 +65,4 @@ var exit = true;

if (exit) {
if (message !== '')
process.stderr.write(message + "\n");
if (signal === 'SIGINT' && messages && messages.ctrl_C !== '')
process.stderr.write(messages.ctrl_C + "\n");
uninstall(); // don't cleanup again

@@ -66,4 +76,4 @@ // necessary to communicate the signal to the parent process

{
if (exceptionMessage !== '')
process.stderr.write(exceptionMessage + "\n");
if (messages && messages.uncaughtException !== '')
process.stderr.write(messages.uncaughtException + "\n");
process.stderr.write(e.stack + "\n");

@@ -82,18 +92,29 @@ process.exit(1); // will call exitHandler() for cleanup

function install(cleanupHandler, messages)
function install(cleanupHandler, stderrMessages)
{
if (cleanupHandler) {
if (typeof cleanupHandler === 'object') {
stderrMessages = cleanupHandler;
cleanupHandler = null;
}
}
else if (!stderrMessages)
stderrMessages = DEFAULT_MESSAGES;
if (stderrMessages) {
if (messages === null)
messages = { ctrl_C: '', uncaughtException: '' };
if (typeof stderrMessages.ctrl_C === 'string')
messages.ctrl_C = stderrMessages.ctrl_C;
if (typeof stderrMessages.uncaughtException === 'string')
messages.uncaughtException = stderrMessages.uncaughtException;
}
if (cleanupHandlers === null) {
cleanupHandlers = []; // establish before installing handlers
messages = messages || {};
if (typeof messages.ctrl_C !== 'string')
messages.ctrl_C = DEFAULT_SIGINT_MSG;
if (typeof messages.uncaughtException !== 'string')
messages.uncaughtException = DEFAULT_EXCEPTION_MSG;
exceptionMessage = messages.uncaughtException;
sigintHandler = signalHandler.bind(this, 'SIGINT', messages.ctrl_C);
sighupHandler = signalHandler.bind(this, 'SIGHUP', '');
sigquitHandler = signalHandler.bind(this, 'SIGQUIT', '');
sigtermHandler = signalHandler.bind(this, 'SIGTERM', '');
sigintHandler = signalHandler.bind(this, 'SIGINT');
sighupHandler = signalHandler.bind(this, 'SIGHUP');
sigquitHandler = signalHandler.bind(this, 'SIGQUIT');
sigtermHandler = signalHandler.bind(this, 'SIGTERM');

@@ -100,0 +121,0 @@ process.on('SIGINT', sigintHandler);

{
"name": "node-cleanup",
"version": "2.0.0",
"version": "2.1.0",
"description": "installs cleanup handlers that always run on exiting node",
"main": "node-cleanup.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "tap tests/*.js"
},

@@ -9,0 +9,0 @@ "repository": {

@@ -45,3 +45,3 @@ # node-cleanup

```js
nodeCleanup(null, {
nodeCleanup({
ctrl_C: "{^C}",

@@ -52,3 +52,3 @@ uncaughtException: "Uh oh. Look what happened:"

To get just the default `stderr` messages, without installing a cleanup handler:
To get the default `stderr` messages, without installing a cleanup handler:

@@ -109,15 +109,18 @@ ```js

`nodeCleanup()` has the following ([FlowType](https://flowtype.org/docs/getting-started.html#_)) signature:
`nodeCleanup()` has the following available ([FlowType](https://flowtype.org/docs/getting-started.html#_)) signatures:
```js
function nodeCleanup(cleanupHandler?: Function, messages?: object): void
function nodeCleanup(cleanupHandler: Function): void
function nodeCleanup(cleanupHandler: Function, stderrMessages: object): void
function nodeCleanup(stderrMessages: object): void
function nodeCleanup(): void
```
`nodeCleanup()` installs a cleanup handler. It may also assign messages to write to `stderr` on SIGINT or an uncaught exception. Both parameters are optional. If not `cleanupHandler` is provided, the `stderr` messages are still written. If no `messages` are provided, default `stderr` messages are written. Calling `nodeCleanup()` with no parameters just installs these default messages.
The 1st form installs a cleanup handler. The 2nd form also assigns messages to write to `stderr` on SIGINT or an uncaught exception. The 3rd and 4th forms only assign messages to write to `stderr`, without installing a cleanup handler. The 4th form assigns default `stderr` messages.
`cleanupHandler` is a cleanup handler callback and is described in its own section below. When null or undefined, termination events all result in the process terminating, including signals.
`cleanupHandler` is a cleanup handler callback and is described in its own section below. When no cleanup handlers are installed, termination events all result in the process terminating, including signal events.
`messages` is an object mapping any of the keys `ctrl_C` and `uncaughtException` to message strings that output to `stderr`. Default messages are provided for omitted messages. Set a message to the empty string `''` inhibit the message.
`stderrMessages` is an object mapping any of the keys `ctrl_C` and `uncaughtException` to message strings that output to `stderr`. Set a message to the empty string `''` inhibit a previously-assigned message.
`nodeCleanup()` may be called multiple times to install multiple cleanup handlers. Each of these handlers runs for each signal or termination condition. The first call to `nodeCleanup()` establishes the `stderr` messages; messages passed to subsequent calls are ignored.
`nodeCleanup()` may be called multiple times to install multiple cleanup handlers or override previous messages. Each handler gets called on each signal or termination condition. The most recently assigned messages apply.

@@ -166,5 +169,11 @@ ### `nodeCleanup.uninstall()`

## Incompatibilities with v1.0.x
`node-cleanup` v2+ is not fully compatible with v1.x. You may need to change your usage to upgrade. These are the potential incompatibilities:
- The cleanup handlers now also run on SIGHUP, SIGQUIT, and SIGTERM, which were not getting cleanup processing before.
- `stderr` messages are handled quite differently. Previously, there were defaults that you had to override, and only your first message assignments applied. Now, the defaults **only** install with the parameterless call `nodeCleanup()`. Otherwise there are no messages unless you provide them. Moreover, the most recent message assignments are the ones that get used.
## Credit
This module began by borrowing and modifying code from CanyonCasa's [answer to a stackoverflow question](http://stackoverflow.com/a/21947851/650894). I had found the code necessary for all my node projects. @Banjocat piped in with a [comment](http://stackoverflow.com/questions/14031763/doing-a-cleanup-action-just-before-node-js-exits/21947851#comment68567869_21947851) about how the solution didn't properly handle SIGINT. (See [this detailed explanation](https://www.cons.org/cracauer/sigint.html) of the SIGINT problem). I have completely rewritten the module to properly deal with SIGINT and other signals (I hope!). The rewrite also provides some additional flexibility I found myself needing in my projects.
This module began by borrowing and modifying code from CanyonCasa's [answer to a stackoverflow question](http://stackoverflow.com/a/21947851/650894). I had found the code necessary for all my node projects. @Banjocat piped in with a [comment](http://stackoverflow.com/questions/14031763/doing-a-cleanup-action-just-before-node-js-exits/21947851#comment68567869_21947851) about how the solution didn't properly handle SIGINT. (See [this detailed explanation](https://www.cons.org/cracauer/sigint.html) of the SIGINT problem). I have completely rewritten the module to properly deal with SIGINT and other signals (I hope!). The rewrite also provides some additional flexibility that @zixia and I found ourselves needing for our respective projects.

@@ -8,2 +8,3 @@ #!/usr/bin/env node

handlers; number; // 0, 1, or 2 concurrent cleanup handlers
messages0: object|null; // messages argument for no-cleanup call, if any
messages1: object|null; // messages argument for 1st nodeCleanup() call

@@ -51,4 +52,8 @@ messages2: object|null; // messages argument for 2nd nodeCleanup() call

if (config.handlers === 0)
nodeCleanup();
if (config.handlers === 0) {
if (config.messages0)
nodeCleanup(config.messages0);
else
nodeCleanup();
}
else {

@@ -55,0 +60,0 @@ nodeCleanup(cleanup1, config.messages1);

@@ -25,30 +25,11 @@ // tests in which spawned child installs multiple cleanup handlers

t.test("multiple handlers: uncaught exception - default message", function (t) {
t.test("multiple handlers: uncaught exception - custom messages", function (t) {
lib.test(t, {
child: 'stackable',
handlers: 2,
messages1: null,
messages2: null,
return1: true,
return2: true,
exception: true,
uninstall: false
}, function (childPID) {
// no signal
}, {
exitReason: 1,
stdout: "cleanup1 cleanup2",
stderr: lib.DEFAULT_EXCEPTION_OUT
});
});
t.test("multiple handlers: uncaught exception - custom message", function (t) {
lib.test(t, {
child: 'stackable',
handlers: 2,
messages1: {
uncaughtException: "Look! A surprise!"
uncaughtException: "Not the surprise you're looking for."
},
messages2: {
uncaughtException: "Not the surprise you're looking for."
uncaughtException: "Look! A surprise!"
},

@@ -68,3 +49,53 @@ return1: true,

t.test("multiple handlers: child SIGINT - both heeded", function (t) {
t.test("multiple handlers: uncaught exception - removed message",
function (t) {
lib.test(t, {
child: 'stackable',
handlers: 2,
messages1: {
uncaughtException: "Not the surprise you're looking for."
},
messages2: {
uncaughtException: ""
},
return1: true,
return2: true,
exception: true,
uninstall: false
}, function (childPID) {
// no signal
}, {
exitReason: 1,
stdout: "cleanup1 cleanup2",
stderr: /tests[\/\\]bin[\/\\]stackable.js/
});
}
);
t.test("multiple handlers: uncaught exception - added message",
function (t) {
lib.test(t, {
child: 'stackable',
handlers: 2,
messages1: {
ctrl_C: "{^C}}"
},
messages2: {
uncaughtException: "Oops!"
},
return1: true,
return2: true,
exception: true,
uninstall: false
}, function (childPID) {
// no signal
}, {
exitReason: 1,
stdout: "cleanup1 cleanup2",
stderr: /^Oops!/
});
}
);
t.test("multiple handlers: uncaught exception - no message", function (t) {
lib.test(t, {

@@ -77,39 +108,99 @@ child: 'stackable',

return2: true,
exception: false,
exception: true,
uninstall: false
}, function (childPID) {
process.kill(childPID, 'SIGINT');
// no signal
}, {
exitReason: 'SIGINT',
exitReason: 1,
stdout: "cleanup1 cleanup2",
stderr: lib.DEFAULT_SIGINT_OUT
stderr: /tests[\/\\]bin[\/\\]stackable.js/
});
});
t.test("multiple handlers: child SIGINT - first heeded", function (t) {
t.test("multiple handlers: child SIGINT - both heeded, custom messages",
function (t) {
lib.test(t, {
child: 'stackable',
handlers: 2,
messages1: {
ctrl_C: "{^C1}"
},
messages2: {
ctrl_C: "{^C2}"
},
return1: true,
return2: true,
exception: false,
uninstall: false
}, function (childPID) {
process.kill(childPID, 'SIGINT');
}, {
exitReason: 'SIGINT',
stdout: "cleanup1 cleanup2",
stderr: "{^C2}\n"
});
}
);
t.test("multiple handlers: child SIGINT - first heeded, custom messages",
function (t) {
lib.test(t, {
child: 'stackable',
handlers: 2,
messages1: {
ctrl_C: "{^C1}"
},
messages2: {
ctrl_C: "{^C2}"
},
return1: true,
return2: false,
exception: false,
uninstall: false
}, function (childPID) {
process.kill(childPID, 'SIGINT');
}, {
exitReason: 0,
stdout: "cleanup1 cleanup2",
stderr: ""
});
}
);
t.test("multiple handlers: child SIGINT - second heeded, custom messages",
function (t) {
lib.test(t, {
child: 'stackable',
handlers: 2,
messages1: {
ctrl_C: "{^C1}"
},
messages2: {
ctrl_C: "{^C2}"
},
return1: false,
return2: true,
exception: false,
uninstall: false
}, function (childPID) {
process.kill(childPID, 'SIGINT');
}, {
exitReason: 0,
stdout: "cleanup1 cleanup2",
stderr: ""
});
}
);
t.test("multiple handlers: child SIGINT - removed message", function (t) {
lib.test(t, {
child: 'stackable',
handlers: 2,
messages1: null,
messages2: null,
messages1: {
ctrl_C: "{^C1}"
},
messages2: {
ctrl_C: ""
},
return1: true,
return2: false,
exception: false,
uninstall: false
}, function (childPID) {
process.kill(childPID, 'SIGINT');
}, {
exitReason: 0,
stdout: "cleanup1 cleanup2",
stderr: ""
});
});
t.test("multiple handlers: child SIGINT - second heeded", function (t) {
lib.test(t, {
child: 'stackable',
handlers: 2,
messages1: null,
messages2: null,
return1: false,
return2: true,

@@ -121,3 +212,3 @@ exception: false,

}, {
exitReason: 0,
exitReason: 'SIGINT',
stdout: "cleanup1 cleanup2",

@@ -128,3 +219,3 @@ stderr: ""

t.test("multiple handlers: child SIGINT - custom message", function (t) {
t.test("multiple handlers: child SIGINT - added message", function (t) {
lib.test(t, {

@@ -134,6 +225,6 @@ child: 'stackable',

messages1: {
ctrl_C: "{^C1}"
uncaughtException: "Oops!"
},
messages2: {
ctrl_C: "{^C2}"
ctrl_C: "{^C1}"
},

@@ -233,4 +324,8 @@ return1: true,

handlers: 2,
messages1: null,
messages2: null,
messages1: {
uncaughtException: "Shouldn't show."
},
messages2: {
uncaughtException: "Also shouldn't show."
},
return1: true,

@@ -253,4 +348,8 @@ return2: true,

handlers: 2,
messages1: null,
messages2: null,
messages1: {
ctrl_C: "{^C1}"
},
messages2: {
ctrl_C: "{^C2}"
},
return1: true,

@@ -257,0 +356,0 @@ return2: true,

@@ -21,3 +21,3 @@ // tests in which spawned child uses the default cleanup handler

t.test("nocleanup: uncaught exception", function (t) {
t.test("nocleanup: uncaught exception - default message", function (t) {
lib.test(t, {

@@ -37,6 +37,24 @@ child: 'stackable',

t.test("nocleanup: child SIGINT", function (t) {
t.test("nocleanup: uncaught exception - custom message", function (t) {
lib.test(t, {
child: 'stackable',
handlers: 0,
messages0: {
uncaughtException: "Yikes!"
},
exception: true,
uninstall: false
}, function (childPID) {
// no signal
}, {
exitReason: 1,
stdout: "",
stderr: /^Yikes!/
});
});
t.test("nocleanup: child SIGINT - default message", function (t) {
lib.test(t, {
child: 'stackable',
handlers: 0,
exception: false,

@@ -53,2 +71,20 @@ uninstall: false

t.test("nocleanup: child SIGINT - custom message", function (t) {
lib.test(t, {
child: 'stackable',
handlers: 0,
messages0: {
ctrl_C: "{^C}"
},
exception: false,
uninstall: false
}, function (childPID) {
process.kill(childPID, 'SIGINT');
}, {
exitReason: 'SIGINT',
stdout: "",
stderr: "{^C}\n"
});
});
t.test("nocleanup: child SIGQUIT", function (t) {

@@ -55,0 +91,0 @@ lib.test(t, {

@@ -60,20 +60,2 @@ // tests in which spawned child installs a custom cleanup handler

t.test("single: uncaught exception - default message", function (t) {
lib.test(t, {
child: 'groupable',
grandchild: false,
grandchildHeedsSIGINT: false,
messages: null,
exception: true,
skipTermination: false,
exitReturn: 'true'
}, function (childPID) {
// no signal
}, {
exitReason: 1,
stdout: "cleanup",
stderr: lib.DEFAULT_EXCEPTION_OUT
});
});
t.test("single: uncaught exception - custom message", function (t) {

@@ -119,3 +101,3 @@ lib.test(t, {

t.test("single: child SIGINT - true return, default message", function (t) {
t.test("single: child SIGINT - true return, custom message", function (t) {
lib.test(t, {

@@ -125,3 +107,5 @@ child: 'groupable',

grandchildHeedsSIGINT: false,
messages: null,
messages: {
ctrl_C: "{^C}"
},
exception: false,

@@ -135,7 +119,7 @@ skipTermination: false,

stdout: "cleanup",
stderr: lib.DEFAULT_SIGINT_OUT
stderr: "{^C}\n"
});
});
t.test("single: child SIGINT - undefined return, default message",
t.test("single: child SIGINT - undefined return, custom message",
function (t) {

@@ -146,3 +130,5 @@ lib.test(t, {

grandchildHeedsSIGINT: false,
messages: null,
messages: {
ctrl_C: "{^C}"
},
exception: false,

@@ -156,3 +142,3 @@ skipTermination: false,

stdout: "cleanup",
stderr: lib.DEFAULT_SIGINT_OUT
stderr: "{^C}\n"
});

@@ -162,22 +148,2 @@ }

t.test("single: child SIGINT - custom message", function (t) {
lib.test(t, {
child: 'groupable',
grandchild: false,
grandchildHeedsSIGINT: false,
messages: {
ctrl_C: "{^C}"
},
exception: false,
skipTermination: false,
exitReturn: 'true'
}, function (childPID) {
process.kill(childPID, 'SIGINT');
}, {
exitReason: 'SIGINT',
stdout: "cleanup",
stderr: "{^C}\n"
});
});
t.test("single: child SIGINT - no message", function (t) {

@@ -188,5 +154,3 @@ lib.test(t, {

grandchildHeedsSIGINT: false,
messages: {
ctrl_C: ""
},
messages: null,
exception: false,

@@ -209,3 +173,5 @@ skipTermination: false,

grandchildHeedsSIGINT: false,
messages: null,
messages: {
ctrl_C: "{^C}"
},
exception: false,

@@ -228,3 +194,5 @@ skipTermination: false,

grandchildHeedsSIGINT: true,
messages: null,
messages: {
ctrl_C: "{^C}"
},
exception: false,

@@ -238,3 +206,3 @@ skipTermination: false,

stdout: "skipped_cleanup grandchild=SIGINT cleanup",
stderr: lib.DEFAULT_SIGINT_OUT
stderr: "{^C}\n"
});

@@ -241,0 +209,0 @@ });

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc