Two correctness bugs in packages/dredd/lib/CLI.js, both [verified] against source.
1. SIGINT handler crashes (commandSigInt)
packages/dredd/lib/CLI.js:504-507
commandSigInt() {
logger.error('\nShutting down from keyboard interruption (Ctrl+C)');
this.dreddInstance.transactionsComplete(() => this._processExit(0));
}
transactionsComplete is defined nowhere in lib/ (grep -rn transactionsComplete packages/dredd/lib returns only this call site). The Dredd class has no such method.
- The handler is also registered unbound:
process.on('SIGINT', this.commandSigInt) (CLI.js:514), so this is not the CLI instance at call time and this.dreddInstance is wrong regardless.
Failure: pressing Ctrl+C during a run throws TypeError instead of shutting down gracefully.
2. exitWithStatus never returns after the error path
packages/dredd/lib/CLI.js:525-538
exitWithStatus(error, stats) {
if (error) {
if (error.message) { logger.error(error.message); }
this._processExit(1); // no return
}
if (stats.failures + stats.errors > 0) { // still runs
this._processExit(1);
} else {
this._processExit(0);
}
}
For the programmatic API (this.exit configured), _processExit does not call process.exit (see Dredd.js:212+), so the custom exit callback fires twice, and stats.failures throws when stats is undefined on the error path.
Tasks
Two correctness bugs in
packages/dredd/lib/CLI.js, both [verified] against source.1. SIGINT handler crashes (
commandSigInt)packages/dredd/lib/CLI.js:504-507transactionsCompleteis defined nowhere inlib/(grep -rn transactionsComplete packages/dredd/libreturns only this call site). TheDreddclass has no such method.process.on('SIGINT', this.commandSigInt)(CLI.js:514), sothisis not the CLI instance at call time andthis.dreddInstanceis wrong regardless.Failure: pressing Ctrl+C during a run throws
TypeErrorinstead of shutting down gracefully.2.
exitWithStatusnever returns after the error pathpackages/dredd/lib/CLI.js:525-538For the programmatic API (
this.exitconfigured),_processExitdoes not callprocess.exit(seeDredd.js:212+), so the custom exit callback fires twice, andstats.failuresthrows whenstatsis undefined on the error path.Tasks
commandSigInt(e.g.process.on('SIGINT', this.commandSigInt.bind(this))) and replace the call to the nonexistenttransactionsCompletewith a real graceful-shutdown path.returnafter the error-path_processExit(1)inexitWithStatus.