Skip to content

Commit

Permalink
process: split bootstrappers by threads that can run them
Browse files Browse the repository at this point in the history
This patch split part of the bootstrappers into three files:

- `lib/internal/process/main_thread_only.js`: contains bootstrappers
  that can only be run in the main thread, including
  - `setupStdio` for the main thread that sets up `process.stdin`,
    `process.stdout`, `process.error` that may interact with external
    resources, e.g. TTY/File/Pipe/TCP sockets
  - `setupProcessMethods` that setup methods changing process-global
    states, e.g. `process.chdir`, `process.umask`, `process.setuid`
  - `setupSignalHandlers`
  - `setupChildProcessIpcChannel` that setup `process.send` for
    child processes.
- `lib/internal/process/worker_thread_only.js`: contains bootstrappers
  that can only be run in the worker threads, including
  - `setupStdio` for the worker thread that are streams to be
    manipulated or piped to the parent thread
- `lib/internal/process/per_thread.js`: contains bootstrappers
    that can be run in all threads, including:
  - `setupAssert` for `process.assert`
  - `setupCpuUsage` for `process.cpuUsage`
  - `setupHrtime` for `process.hrtime` and `process.hrtime.bigint`
  - `setupMemoryUsage` for `process.memoryUsage`
  - `setupConfig` for `process.config`
  - `setupKillAndExit` for `process.kill` and `process.exit`
  - `setupRawDebug` for `process._rawDebug`
  - `setupUncaughtExceptionCapture` for
    `process.setUncaughtExceptionCaptureCallback` and
    `process.hasUncaughtExceptionCaptureCallback`

Hopefully in the future we can sort more bootstrappers in
`boostrap/node.js` into these three files and further group
them into functions that can be run before creating the
snapshot / after loading the snapshot.

This patch also moves most of the `isMainThread` conditionals
into the main bootstrapper instead of letting them scattered around
special-casing different implementations.

PR-URL: #21378
Reviewed-By: Gus Caplan <[email protected]>
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Jeremiah Senkpiel <[email protected]>

Backport-PR-URL: #21866
Reviewed-By: Michaël Zasso <[email protected]>
  • Loading branch information
joyeecheung authored and targos committed Jul 18, 2018
1 parent eef975e commit 581390c
Show file tree
Hide file tree
Showing 7 changed files with 227 additions and 165 deletions.
67 changes: 45 additions & 22 deletions lib/internal/bootstrap/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,33 +44,57 @@

setupGlobalVariables();

const _process = NativeModule.require('internal/process');
_process.setupConfig(NativeModule._source);
_process.setupSignalHandlers();
_process.setupUncaughtExceptionCapture(exceptionHandlerState,
_shouldAbortOnUncaughtToggle);
// Bootstrappers for all threads, including worker threads and main thread
const perThreadSetup = NativeModule.require('internal/process/per_thread');
// Bootstrappers for the main thread only
let mainThreadSetup;
// Bootstrappers for the worker threads only
let workerThreadSetup;
if (isMainThread) {
mainThreadSetup = NativeModule.require(
'internal/process/main_thread_only'
);
} else {
workerThreadSetup = NativeModule.require(
'internal/process/worker_thread_only'
);
}

perThreadSetup.setupAssert();
perThreadSetup.setupConfig(NativeModule._source);

if (isMainThread) {
mainThreadSetup.setupSignalHandlers();
}

perThreadSetup.setupUncaughtExceptionCapture(exceptionHandlerState,
_shouldAbortOnUncaughtToggle);

NativeModule.require('internal/process/warning').setup();
NativeModule.require('internal/process/next_tick').setup(_setupNextTick,
_setupPromises);
NativeModule.require('internal/process/stdio').setup();
NativeModule.require('internal/process/methods').setup(_chdir,
_umask,
_initgroups,
_setegid,
_seteuid,
_setgid,
_setuid,
_setgroups);

if (isMainThread) {
mainThreadSetup.setupStdio();
mainThreadSetup.setupProcessMethods(
_chdir, _umask, _initgroups, _setegid, _seteuid,
_setgid, _setuid, _setgroups
);
} else {
workerThreadSetup.setupStdio();
}

const perf = process.binding('performance');
const {
NODE_PERFORMANCE_MILESTONE_BOOTSTRAP_COMPLETE,
} = perf.constants;

_process.setup_hrtime(_hrtime, _hrtimeBigInt);
_process.setup_cpuUsage(_cpuUsage);
_process.setupMemoryUsage(_memoryUsage);
_process.setupKillAndExit();
perThreadSetup.setupRawDebug(_rawDebug);
perThreadSetup.setupHrtime(_hrtime, _hrtimeBigInt);
perThreadSetup.setupCpuUsage(_cpuUsage);
perThreadSetup.setupMemoryUsage(_memoryUsage);
perThreadSetup.setupKillAndExit();

if (global.__coverage__)
NativeModule.require('internal/process/write-coverage').setup();

Expand All @@ -90,10 +114,9 @@
NativeModule.require('internal/inspector_async_hook').setup();
}

if (isMainThread)
_process.setupChannel();

_process.setupRawDebug(_rawDebug);
if (isMainThread) {
mainThreadSetup.setupChildProcessIpcChannel();
}

const browserGlobals = !process._noBrowserGlobals;
if (browserGlobals) {
Expand Down
127 changes: 127 additions & 0 deletions lib/internal/process/main_thread_only.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
'use strict';

// This file contains process bootstrappers that can only be
// run in the main thread

const {
errnoException
} = require('internal/errors');

const {
setupProcessStdio,
getMainThreadStdio
} = require('internal/process/stdio');

const assert = require('assert').strict;

function setupStdio() {
setupProcessStdio(getMainThreadStdio());
}

// Non-POSIX platforms like Windows don't have certain methods.
// Workers also lack these methods since they change process-global state.
function setupProcessMethods(_chdir, _umask, _initgroups, _setegid,
_seteuid, _setgid, _setuid, _setgroups) {
if (_setgid !== undefined) {
setupPosixMethods(_initgroups, _setegid, _seteuid,
_setgid, _setuid, _setgroups);
}

process.chdir = function chdir(...args) {
return _chdir(...args);
};

process.umask = function umask(...args) {
return _umask(...args);
};
}

function setupPosixMethods(_initgroups, _setegid, _seteuid,
_setgid, _setuid, _setgroups) {

process.initgroups = function initgroups(...args) {
return _initgroups(...args);
};

process.setegid = function setegid(...args) {
return _setegid(...args);
};

process.seteuid = function seteuid(...args) {
return _seteuid(...args);
};

process.setgid = function setgid(...args) {
return _setgid(...args);
};

process.setuid = function setuid(...args) {
return _setuid(...args);
};

process.setgroups = function setgroups(...args) {
return _setgroups(...args);
};
}

// Worker threads don't receive signals.
function setupSignalHandlers() {
const constants = process.binding('constants').os.signals;
const signalWraps = Object.create(null);
let Signal;

function isSignal(event) {
return typeof event === 'string' && constants[event] !== undefined;
}

// Detect presence of a listener for the special signal types
process.on('newListener', function(type) {
if (isSignal(type) && signalWraps[type] === undefined) {
if (Signal === undefined)
Signal = process.binding('signal_wrap').Signal;
const wrap = new Signal();

wrap.unref();

wrap.onsignal = process.emit.bind(process, type, type);

const signum = constants[type];
const err = wrap.start(signum);
if (err) {
wrap.close();
throw errnoException(err, 'uv_signal_start');
}

signalWraps[type] = wrap;
}
});

process.on('removeListener', function(type) {
if (signalWraps[type] !== undefined && this.listenerCount(type) === 0) {
signalWraps[type].close();
delete signalWraps[type];
}
});
}

function setupChildProcessIpcChannel() {
// If we were spawned with env NODE_CHANNEL_FD then load that up and
// start parsing data from that stream.
if (process.env.NODE_CHANNEL_FD) {
const fd = parseInt(process.env.NODE_CHANNEL_FD, 10);
assert(fd >= 0);

// Make sure it's not accidentally inherited by child processes.
delete process.env.NODE_CHANNEL_FD;

require('child_process')._forkChild(fd);
assert(process.send);
}
}

module.exports = {
setupStdio,
setupProcessMethods,
setupSignalHandlers,
setupChildProcessIpcChannel
};
56 changes: 0 additions & 56 deletions lib/internal/process/methods.js

This file was deleted.

Loading

0 comments on commit 581390c

Please sign in to comment.