Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
process: split bootstrappers by threads that can run them
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 <me@gus.host>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
  • Loading branch information
joyeecheung committed Jul 18, 2018
commit 151f24172d0bc342556b52c8c8714076c36b0732
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