mirror of
https://github.com/nodejs/node.git
synced 2025-05-03 07:06:00 +00:00

This commit uses the triggerReport() binding to handle signals and removes the custom onUserSignal() function. PR-URL: https://github.com/nodejs/node/pull/26386 Reviewed-By: Richard Lau <riclau@uk.ibm.com> Reviewed-By: James M Snell <jasnell@gmail.com>
116 lines
3.4 KiB
JavaScript
116 lines
3.4 KiB
JavaScript
'use strict';
|
|
const {
|
|
convertToValidSignal,
|
|
emitExperimentalWarning
|
|
} = require('internal/util');
|
|
const {
|
|
ERR_INVALID_ARG_TYPE,
|
|
ERR_SYNTHETIC
|
|
} = require('internal/errors').codes;
|
|
|
|
// If report is enabled, extract the binding and
|
|
// wrap the APIs with thin layers, with some error checks.
|
|
// user options can come in from CLI / ENV / API.
|
|
// CLI and ENV is intercepted in C++ and the API call here (JS).
|
|
// So sync up with both sides as appropriate - initially from
|
|
// C++ to JS and from JS to C++ whenever the API is called.
|
|
// Some events are controlled purely from JS (signal | exception)
|
|
// and some from C++ (fatalerror) so this sync-up is essential for
|
|
// correct behavior and alignment with the supplied tunables.
|
|
const nr = internalBinding('report');
|
|
|
|
// Keep it un-exposed; lest programs play with it
|
|
// leaving us with a lot of unwanted sanity checks.
|
|
let config = {
|
|
events: [],
|
|
signal: 'SIGUSR2',
|
|
filename: '',
|
|
path: ''
|
|
};
|
|
const report = {
|
|
setOptions(options) {
|
|
emitExperimentalWarning('report');
|
|
const previousConfig = config;
|
|
const newConfig = {};
|
|
|
|
if (options === null || typeof options !== 'object')
|
|
options = {};
|
|
|
|
if (Array.isArray(options.events))
|
|
newConfig.events = options.events.slice();
|
|
else if (options.events === undefined)
|
|
newConfig.events = [];
|
|
else
|
|
throw new ERR_INVALID_ARG_TYPE('events', 'Array', options.events);
|
|
|
|
if (typeof options.filename === 'string')
|
|
newConfig.filename = options.filename;
|
|
else if (options.filename === undefined)
|
|
newConfig.filename = '';
|
|
else
|
|
throw new ERR_INVALID_ARG_TYPE('filename', 'string', options.filename);
|
|
|
|
if (typeof options.path === 'string')
|
|
newConfig.path = options.path;
|
|
else if (options.path === undefined)
|
|
newConfig.path = '';
|
|
else
|
|
throw new ERR_INVALID_ARG_TYPE('path', 'string', options.path);
|
|
|
|
if (typeof options.signal === 'string')
|
|
newConfig.signal = convertToValidSignal(options.signal);
|
|
else if (options.signal === undefined)
|
|
newConfig.signal = 'SIGUSR2';
|
|
else
|
|
throw new ERR_INVALID_ARG_TYPE('signal', 'string', options.signal);
|
|
|
|
if (previousConfig.signal)
|
|
process.removeListener(previousConfig.signal, handleSignal);
|
|
|
|
if (newConfig.events.includes('signal'))
|
|
process.on(newConfig.signal, handleSignal);
|
|
|
|
config = newConfig;
|
|
nr.syncConfig(config, true);
|
|
},
|
|
triggerReport(file, err) {
|
|
emitExperimentalWarning('report');
|
|
|
|
if (typeof file === 'object' && file !== null) {
|
|
err = file;
|
|
file = undefined;
|
|
} else if (file !== undefined && typeof file !== 'string') {
|
|
throw new ERR_INVALID_ARG_TYPE('file', 'String', file);
|
|
} else if (err === undefined) {
|
|
err = new ERR_SYNTHETIC();
|
|
} else if (err === null || typeof err !== 'object') {
|
|
throw new ERR_INVALID_ARG_TYPE('err', 'Object', err);
|
|
}
|
|
|
|
return nr.triggerReport('JavaScript API', 'API', file, err.stack);
|
|
},
|
|
getReport(err) {
|
|
emitExperimentalWarning('report');
|
|
|
|
if (err === undefined)
|
|
err = new ERR_SYNTHETIC();
|
|
else if (err === null || typeof err !== 'object')
|
|
throw new ERR_INVALID_ARG_TYPE('err', 'Object', err);
|
|
|
|
return nr.getReport(err.stack);
|
|
}
|
|
};
|
|
|
|
function handleSignal(signo) {
|
|
if (typeof signo !== 'string')
|
|
signo = config.signal;
|
|
nr.triggerReport(signo, 'Signal', null, '');
|
|
}
|
|
|
|
module.exports = {
|
|
config,
|
|
handleSignal,
|
|
report,
|
|
syncConfig: nr.syncConfig
|
|
};
|