process: move process mutation into bootstrap/node.js
This patch moves the part in the report initialization that mutates the process object into bootstrap/node.js so it's easier to tell the side effect of the initialization on the global state during bootstrap. PR-URL: https://github.com/nodejs/node/pull/25821 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Gus Caplan <me@gus.host> Reviewed-By: Richard Lau <riclau@uk.ibm.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com>
This commit is contained in:
parent
c2359bdad6
commit
406329de57
@ -309,7 +309,18 @@ if (process.env.NODE_V8_COVERAGE) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (getOptionValue('--experimental-report')) {
|
if (getOptionValue('--experimental-report')) {
|
||||||
NativeModule.require('internal/process/report').setup();
|
const {
|
||||||
|
config,
|
||||||
|
handleSignal,
|
||||||
|
report,
|
||||||
|
syncConfig
|
||||||
|
} = NativeModule.require('internal/process/report');
|
||||||
|
process.report = report;
|
||||||
|
// Download the CLI / ENV config into JS land.
|
||||||
|
syncConfig(config, false);
|
||||||
|
if (config.events.includes('signal')) {
|
||||||
|
process.on(config.signal, handleSignal);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupTraceCategoryState() {
|
function setupTraceCategoryState() {
|
||||||
|
@ -3,158 +3,156 @@
|
|||||||
const { emitExperimentalWarning } = require('internal/util');
|
const { emitExperimentalWarning } = require('internal/util');
|
||||||
const {
|
const {
|
||||||
ERR_INVALID_ARG_TYPE,
|
ERR_INVALID_ARG_TYPE,
|
||||||
ERR_SYNTHETIC } = require('internal/errors').codes;
|
ERR_SYNTHETIC
|
||||||
|
} = require('internal/errors').codes;
|
||||||
|
|
||||||
exports.setup = function() {
|
const REPORTEVENTS = 1;
|
||||||
const REPORTEVENTS = 1;
|
const REPORTSIGNAL = 2;
|
||||||
const REPORTSIGNAL = 2;
|
const REPORTFILENAME = 3;
|
||||||
const REPORTFILENAME = 3;
|
const REPORTPATH = 4;
|
||||||
const REPORTPATH = 4;
|
const REPORTVERBOSE = 5;
|
||||||
const REPORTVERBOSE = 5;
|
|
||||||
|
|
||||||
// If report is enabled, extract the binding and
|
// If report is enabled, extract the binding and
|
||||||
// wrap the APIs with thin layers, with some error checks.
|
// wrap the APIs with thin layers, with some error checks.
|
||||||
// user options can come in from CLI / ENV / API.
|
// user options can come in from CLI / ENV / API.
|
||||||
// CLI and ENV is intercepted in C++ and the API call here (JS).
|
// CLI and ENV is intercepted in C++ and the API call here (JS).
|
||||||
// So sync up with both sides as appropriate - initially from
|
// So sync up with both sides as appropriate - initially from
|
||||||
// C++ to JS and from JS to C++ whenever the API is called.
|
// C++ to JS and from JS to C++ whenever the API is called.
|
||||||
// Some events are controlled purely from JS (signal | exception)
|
// Some events are controlled purely from JS (signal | exception)
|
||||||
// and some from C++ (fatalerror) so this sync-up is essential for
|
// and some from C++ (fatalerror) so this sync-up is essential for
|
||||||
// correct behavior and alignment with the supplied tunables.
|
// correct behavior and alignment with the supplied tunables.
|
||||||
const nr = internalBinding('report');
|
const nr = internalBinding('report');
|
||||||
|
|
||||||
// Keep it un-exposed; lest programs play with it
|
// Keep it un-exposed; lest programs play with it
|
||||||
// leaving us with a lot of unwanted sanity checks.
|
// leaving us with a lot of unwanted sanity checks.
|
||||||
let config = {
|
let config = {
|
||||||
events: [],
|
events: [],
|
||||||
signal: 'SIGUSR2',
|
signal: 'SIGUSR2',
|
||||||
filename: '',
|
filename: '',
|
||||||
path: '',
|
path: '',
|
||||||
verbose: false
|
verbose: false
|
||||||
};
|
};
|
||||||
const report = {
|
const report = {
|
||||||
setDiagnosticReportOptions(options) {
|
setDiagnosticReportOptions(options) {
|
||||||
emitExperimentalWarning('report');
|
emitExperimentalWarning('report');
|
||||||
// Reuse the null and undefined checks. Save
|
// Reuse the null and undefined checks. Save
|
||||||
// space when dealing with large number of arguments.
|
// space when dealing with large number of arguments.
|
||||||
const list = parseOptions(options);
|
const list = parseOptions(options);
|
||||||
|
|
||||||
// Flush the stale entries from report, as
|
// Flush the stale entries from report, as
|
||||||
// we are refreshing it, items that the users did not
|
// we are refreshing it, items that the users did not
|
||||||
// touch may be hanging around stale otherwise.
|
// touch may be hanging around stale otherwise.
|
||||||
config = {};
|
config = {};
|
||||||
|
|
||||||
// The parseOption method returns an array that include
|
// The parseOption method returns an array that include
|
||||||
// the indices at which valid params are present.
|
// the indices at which valid params are present.
|
||||||
list.forEach((i) => {
|
list.forEach((i) => {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case REPORTEVENTS:
|
case REPORTEVENTS:
|
||||||
if (Array.isArray(options.events))
|
if (Array.isArray(options.events))
|
||||||
config.events = options.events;
|
config.events = options.events;
|
||||||
else
|
else
|
||||||
throw new ERR_INVALID_ARG_TYPE('events',
|
throw new ERR_INVALID_ARG_TYPE('events',
|
||||||
'Array',
|
'Array',
|
||||||
options.events);
|
options.events);
|
||||||
break;
|
break;
|
||||||
case REPORTSIGNAL:
|
case REPORTSIGNAL:
|
||||||
if (typeof options.signal !== 'string') {
|
if (typeof options.signal !== 'string') {
|
||||||
throw new ERR_INVALID_ARG_TYPE('signal',
|
throw new ERR_INVALID_ARG_TYPE('signal',
|
||||||
'String',
|
'String',
|
||||||
options.signal);
|
options.signal);
|
||||||
}
|
}
|
||||||
process.removeListener(config.signal, handleSignal);
|
process.removeListener(config.signal, handleSignal);
|
||||||
if (config.events.includes('signal'))
|
if (config.events.includes('signal'))
|
||||||
process.on(options.signal, handleSignal);
|
process.on(options.signal, handleSignal);
|
||||||
config.signal = options.signal;
|
config.signal = options.signal;
|
||||||
break;
|
break;
|
||||||
case REPORTFILENAME:
|
case REPORTFILENAME:
|
||||||
if (typeof options.filename !== 'string') {
|
if (typeof options.filename !== 'string') {
|
||||||
throw new ERR_INVALID_ARG_TYPE('filename',
|
throw new ERR_INVALID_ARG_TYPE('filename',
|
||||||
'String',
|
'String',
|
||||||
options.filename);
|
options.filename);
|
||||||
}
|
}
|
||||||
config.filename = options.filename;
|
config.filename = options.filename;
|
||||||
break;
|
break;
|
||||||
case REPORTPATH:
|
case REPORTPATH:
|
||||||
if (typeof options.path !== 'string')
|
if (typeof options.path !== 'string')
|
||||||
throw new ERR_INVALID_ARG_TYPE('path', 'String', options.path);
|
throw new ERR_INVALID_ARG_TYPE('path', 'String', options.path);
|
||||||
config.path = options.path;
|
config.path = options.path;
|
||||||
break;
|
break;
|
||||||
case REPORTVERBOSE:
|
case REPORTVERBOSE:
|
||||||
if (typeof options.verbose !== 'string' &&
|
if (typeof options.verbose !== 'string' &&
|
||||||
typeof options.verbose !== 'boolean') {
|
typeof options.verbose !== 'boolean') {
|
||||||
throw new ERR_INVALID_ARG_TYPE('verbose',
|
throw new ERR_INVALID_ARG_TYPE('verbose',
|
||||||
'Booelan | String' +
|
'Booelan | String' +
|
||||||
' (true|false|yes|no)',
|
' (true|false|yes|no)',
|
||||||
options.verbose);
|
options.verbose);
|
||||||
}
|
}
|
||||||
config.verbose = options.verbose;
|
config.verbose = options.verbose;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// Upload this new config to C++ land
|
// Upload this new config to C++ land
|
||||||
nr.syncConfig(config, true);
|
nr.syncConfig(config, true);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
triggerReport(file, err) {
|
triggerReport(file, err) {
|
||||||
emitExperimentalWarning('report');
|
emitExperimentalWarning('report');
|
||||||
if (err == null) {
|
if (err == null) {
|
||||||
if (file == null) {
|
if (file == null) {
|
||||||
return nr.triggerReport(new ERR_SYNTHETIC().stack);
|
return nr.triggerReport(new ERR_SYNTHETIC().stack);
|
||||||
}
|
|
||||||
if (typeof file !== 'string')
|
|
||||||
throw new ERR_INVALID_ARG_TYPE('file', 'String', file);
|
|
||||||
return nr.triggerReport(file, new ERR_SYNTHETIC().stack);
|
|
||||||
}
|
}
|
||||||
if (typeof err !== 'object')
|
|
||||||
throw new ERR_INVALID_ARG_TYPE('err', 'Object', err);
|
|
||||||
if (file == null)
|
|
||||||
return nr.triggerReport(err.stack);
|
|
||||||
if (typeof file !== 'string')
|
if (typeof file !== 'string')
|
||||||
throw new ERR_INVALID_ARG_TYPE('file', 'String', file);
|
throw new ERR_INVALID_ARG_TYPE('file', 'String', file);
|
||||||
return nr.triggerReport(file, err.stack);
|
return nr.triggerReport(file, new ERR_SYNTHETIC().stack);
|
||||||
},
|
}
|
||||||
getReport(err) {
|
if (typeof err !== 'object')
|
||||||
emitExperimentalWarning('report');
|
throw new ERR_INVALID_ARG_TYPE('err', 'Object', err);
|
||||||
if (err == null) {
|
if (file == null)
|
||||||
return nr.getReport(new ERR_SYNTHETIC().stack);
|
return nr.triggerReport(err.stack);
|
||||||
} else if (typeof err !== 'object') {
|
if (typeof file !== 'string')
|
||||||
throw new ERR_INVALID_ARG_TYPE('err', 'Object', err);
|
throw new ERR_INVALID_ARG_TYPE('file', 'String', file);
|
||||||
} else {
|
return nr.triggerReport(file, err.stack);
|
||||||
return nr.getReport(err.stack);
|
},
|
||||||
}
|
getReport(err) {
|
||||||
|
emitExperimentalWarning('report');
|
||||||
|
if (err == null) {
|
||||||
|
return nr.getReport(new ERR_SYNTHETIC().stack);
|
||||||
|
} else if (typeof err !== 'object') {
|
||||||
|
throw new ERR_INVALID_ARG_TYPE('err', 'Object', err);
|
||||||
|
} else {
|
||||||
|
return nr.getReport(err.stack);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
// Download the CLI / ENV config into JS land.
|
|
||||||
nr.syncConfig(config, false);
|
|
||||||
|
|
||||||
function handleSignal(signo) {
|
|
||||||
if (typeof signo !== 'string')
|
|
||||||
signo = config.signal;
|
|
||||||
nr.onUserSignal(signo);
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
if (config.events.includes('signal')) {
|
|
||||||
process.on(config.signal, handleSignal);
|
function handleSignal(signo) {
|
||||||
}
|
if (typeof signo !== 'string')
|
||||||
|
signo = config.signal;
|
||||||
function parseOptions(obj) {
|
nr.onUserSignal(signo);
|
||||||
const list = [];
|
}
|
||||||
if (obj == null)
|
|
||||||
return list;
|
function parseOptions(obj) {
|
||||||
if (obj.events != null)
|
const list = [];
|
||||||
list.push(REPORTEVENTS);
|
if (obj == null)
|
||||||
if (obj.signal != null)
|
return list;
|
||||||
list.push(REPORTSIGNAL);
|
if (obj.events != null)
|
||||||
if (obj.filename != null)
|
list.push(REPORTEVENTS);
|
||||||
list.push(REPORTFILENAME);
|
if (obj.signal != null)
|
||||||
if (obj.path != null)
|
list.push(REPORTSIGNAL);
|
||||||
list.push(REPORTPATH);
|
if (obj.filename != null)
|
||||||
if (obj.verbose != null)
|
list.push(REPORTFILENAME);
|
||||||
list.push(REPORTVERBOSE);
|
if (obj.path != null)
|
||||||
return list;
|
list.push(REPORTPATH);
|
||||||
}
|
if (obj.verbose != null)
|
||||||
process.report = report;
|
list.push(REPORTVERBOSE);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
config,
|
||||||
|
handleSignal,
|
||||||
|
report,
|
||||||
|
syncConfig: nr.syncConfig
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user