Skip to content

Commit 57f29b7

Browse files
joyeecheungtargos
authored andcommitted
bootstrap: use different scripts to setup different configurations
This patch splits the handling of `isMainThread` and `ownsProcessState` from conditionals in `lib/internal/bootstrap/node.js` into different scripts under `lib/internal/bootstrap/switches/`, and call them accordingly from C++ after `node.js` is run. This: - Creates a common denominator of the main thread and the worker thread bootstrap that can be snapshotted and shared by both. - Makes it possible to override the configurations on-the-fly. PR-URL: #30862 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
1 parent 1c17f42 commit 57f29b7

14 files changed

Lines changed: 568 additions & 545 deletions

‎lib/internal/bootstrap/node.js‎

Lines changed: 18 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
// This file is invoked by `node::RunBootstrapping()` in `src/node.cc`, and is
44
// responsible for setting up node.js core before executing main scripts
55
// under `lib/internal/main/`.
6-
// This file is currently run to bootstrap both the main thread and the worker
7-
// threads. Some setups are conditional, controlled with isMainThread and
8-
// ownsProcessState.
6+
//
97
// This file is expected not to perform any asynchronous operations itself
108
// when being executed - those should be done in either
119
// `lib/internal/bootstrap/pre_execution.js` or in main scripts. The majority
@@ -22,16 +20,21 @@
2220
// module loaders, including `process.binding()`, `process._linkedBinding()`,
2321
// `internalBinding()` and `NativeModule`.
2422
//
25-
// After this file is run, one of the main scripts under `lib/internal/main/`
26-
// will be selected by C++ to start the actual execution. The main scripts may
27-
// run additional setups exported by `lib/internal/bootstrap/pre_execution.js`,
28-
// depending on the execution mode.
23+
// This file is run to bootstrap both the main thread and the worker threads.
24+
// After this file is run, certain properties are setup according to the
25+
// configuration of the Node.js instance using the files in
26+
// `lib/internal/bootstrap/switches/`.
27+
//
28+
// Then, depending on how the Node.js instance is launched, one of the main
29+
// scripts in `lib/internal/main` will be selected by C++ to start the actual
30+
// execution. They may run additional setups exported by
31+
// `lib/internal/bootstrap/pre_execution.js` depending on the runtime states.
2932

3033
'use strict';
3134

3235
// This file is compiled as if it's wrapped in a function with arguments
3336
// passed by node::RunBootstrapping()
34-
/* global process, require, internalBinding, isMainThread, ownsProcessState */
37+
/* global process, require, internalBinding */
3538

3639
setupPrepareStackTrace();
3740

@@ -54,48 +57,12 @@ setupBuffer();
5457
process.domain=null;
5558
process._exiting=false;
5659

57-
// Bootstrappers for all threads, including worker threads and main thread
58-
constperThreadSetup=require('internal/process/per_thread');
59-
// Bootstrappers for the main thread only
60-
letmainThreadSetup;
61-
// Bootstrappers for the worker threads only
62-
letworkerThreadSetup;
63-
if(ownsProcessState){
64-
mainThreadSetup=require(
65-
'internal/process/main_thread_only'
66-
);
67-
}else{
68-
workerThreadSetup=require(
69-
'internal/process/worker_thread_only'
70-
);
71-
}
72-
7360
// process.config is serialized config.gypi
7461
process.config=JSONParse(internalBinding('native_module').config);
7562

63+
// Bootstrappers for all threads, including worker threads and main thread
64+
constperThreadSetup=require('internal/process/per_thread');
7665
constrawMethods=internalBinding('process_methods');
77-
// Set up methods and events on the process object for the main thread
78-
if(isMainThread){
79-
process.abort=rawMethods.abort;
80-
constwrapped=mainThreadSetup.wrapProcessMethods(rawMethods);
81-
process.umask=wrapped.umask;
82-
process.chdir=wrapped.chdir;
83-
process.cwd=wrapped.cwd;
84-
85-
// TODO(joyeecheung): deprecate and remove these underscore methods
86-
process._debugProcess=rawMethods._debugProcess;
87-
process._debugEnd=rawMethods._debugEnd;
88-
process._startProfilerIdleNotifier=
89-
rawMethods._startProfilerIdleNotifier;
90-
process._stopProfilerIdleNotifier=rawMethods._stopProfilerIdleNotifier;
91-
}else{
92-
constwrapped=workerThreadSetup.wrapProcessMethods(rawMethods);
93-
94-
process.abort=workerThreadSetup.unavailable('process.abort()');
95-
process.chdir=workerThreadSetup.unavailable('process.chdir()');
96-
process.umask=wrapped.umask;
97-
process.cwd=rawMethods.cwd;
98-
}
9966

10067
// Set up methods on the process object for all threads
10168
{
@@ -119,6 +86,11 @@ if (isMainThread) {
11986
process.memoryUsage=wrapped.memoryUsage;
12087
process.kill=wrapped.kill;
12188
process.exit=wrapped.exit;
89+
90+
process.openStdin=function(){
91+
process.stdin.resume();
92+
returnprocess.stdin;
93+
};
12294
}
12395

12496
constcredentials=internalBinding('credentials');
@@ -128,34 +100,6 @@ if (credentials.implementsPosixCredentials) {
128100
process.getgid=credentials.getgid;
129101
process.getegid=credentials.getegid;
130102
process.getgroups=credentials.getgroups;
131-
132-
if(ownsProcessState){
133-
constwrapped=mainThreadSetup.wrapPosixCredentialSetters(credentials);
134-
process.initgroups=wrapped.initgroups;
135-
process.setgroups=wrapped.setgroups;
136-
process.setegid=wrapped.setegid;
137-
process.seteuid=wrapped.seteuid;
138-
process.setgid=wrapped.setgid;
139-
process.setuid=wrapped.setuid;
140-
}else{
141-
process.initgroups=
142-
workerThreadSetup.unavailable('process.initgroups()');
143-
process.setgroups=workerThreadSetup.unavailable('process.setgroups()');
144-
process.setegid=workerThreadSetup.unavailable('process.setegid()');
145-
process.seteuid=workerThreadSetup.unavailable('process.seteuid()');
146-
process.setgid=workerThreadSetup.unavailable('process.setgid()');
147-
process.setuid=workerThreadSetup.unavailable('process.setuid()');
148-
}
149-
}
150-
151-
if(isMainThread){
152-
const{ getStdout, getStdin, getStderr }=
153-
require('internal/process/stdio').getMainThreadStdio();
154-
setupProcessStdio(getStdout,getStdin,getStderr);
155-
}else{
156-
const{ getStdout, getStdin, getStderr }=
157-
workerThreadSetup.createStdioGetters();
158-
setupProcessStdio(getStdout,getStdin,getStderr);
159103
}
160104

161105
// Setup the callbacks that node::AsyncWrap will call when there are hooks to
@@ -343,31 +287,6 @@ function setupProcessObject() {
343287
});
344288
}
345289

346-
functionsetupProcessStdio(getStdout,getStdin,getStderr){
347-
ObjectDefineProperty(process,'stdout',{
348-
configurable: true,
349-
enumerable: true,
350-
get: getStdout
351-
});
352-
353-
ObjectDefineProperty(process,'stderr',{
354-
configurable: true,
355-
enumerable: true,
356-
get: getStderr
357-
});
358-
359-
ObjectDefineProperty(process,'stdin',{
360-
configurable: true,
361-
enumerable: true,
362-
get: getStdin
363-
});
364-
365-
process.openStdin=function(){
366-
process.stdin.resume();
367-
returnprocess.stdin;
368-
};
369-
}
370-
371290
functionsetupGlobalProxy(){
372291
ObjectDefineProperty(global,SymbolToStringTag,{
373292
value: 'global',

‎lib/internal/bootstrap/pre_execution.js‎

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,6 @@ function prepareMainThreadExecution(expandArgv1 = false) {
3737

3838
setupDebugEnv();
3939

40-
// Only main thread receives signals.
41-
setupSignalHandlers();
42-
4340
// Process initial diagnostic reporting configuration, if present.
4441
initializeReport();
4542
initializeReportSignalHandlers();// Main-thread-only.
@@ -175,20 +172,7 @@ function setupDebugEnv() {
175172
}
176173
}
177174

178-
functionsetupSignalHandlers(){
179-
const{
180-
createSignalHandlers
181-
}=require('internal/process/main_thread_only');
182-
const{
183-
startListeningIfSignal,
184-
stopListeningIfSignal
185-
}=createSignalHandlers();
186-
process.on('newListener',startListeningIfSignal);
187-
process.on('removeListener',stopListeningIfSignal);
188-
}
189-
190-
// This has to be called after both initializeReport() and
191-
// setupSignalHandlers() are called
175+
// This has to be called after initializeReport() is called
192176
functioninitializeReportSignalHandlers(){
193177
if(!getOptionValue('--experimental-report')){
194178
return;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
'use strict';
2+
3+
constcredentials=internalBinding('credentials');
4+
5+
if(credentials.implementsPosixCredentials){
6+
// TODO: this should be detached from ERR_WORKER_UNSUPPORTED_OPERATION
7+
const{ unavailable }=require('internal/process/worker_thread_only');
8+
9+
process.initgroups=unavailable('process.initgroups()');
10+
process.setgroups=unavailable('process.setgroups()');
11+
process.setegid=unavailable('process.setegid()');
12+
process.seteuid=unavailable('process.seteuid()');
13+
process.setgid=unavailable('process.setgid()');
14+
process.setuid=unavailable('process.setuid()');
15+
}
16+
17+
// ---- keep the attachment of the wrappers above so that it's easier to ----
18+
// ---- compare the setups side-by-side -----
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
'use strict';
2+
3+
constcredentials=internalBinding('credentials');
4+
5+
if(credentials.implementsPosixCredentials){
6+
constwrapped=wrapPosixCredentialSetters(credentials);
7+
8+
process.initgroups=wrapped.initgroups;
9+
process.setgroups=wrapped.setgroups;
10+
process.setegid=wrapped.setegid;
11+
process.seteuid=wrapped.seteuid;
12+
process.setgid=wrapped.setgid;
13+
process.setuid=wrapped.setuid;
14+
}
15+
16+
// ---- keep the attachment of the wrappers above so that it's easier to ----
17+
// ---- compare the setups side-by-side -----
18+
19+
functionwrapPosixCredentialSetters(credentials){
20+
const{
21+
ArrayIsArray,
22+
}=primordials;
23+
const{
24+
codes: {
25+
ERR_INVALID_ARG_TYPE,
26+
ERR_UNKNOWN_CREDENTIAL
27+
}
28+
}=require('internal/errors');
29+
const{
30+
validateUint32
31+
}=require('internal/validators');
32+
33+
const{
34+
initgroups: _initgroups,
35+
setgroups: _setgroups,
36+
setegid: _setegid,
37+
seteuid: _seteuid,
38+
setgid: _setgid,
39+
setuid: _setuid
40+
}=credentials;
41+
42+
functioninitgroups(user,extraGroup){
43+
validateId(user,'user');
44+
validateId(extraGroup,'extraGroup');
45+
// Result is 0 on success, 1 if user is unknown, 2 if group is unknown.
46+
constresult=_initgroups(user,extraGroup);
47+
if(result===1){
48+
thrownewERR_UNKNOWN_CREDENTIAL('User',user);
49+
}elseif(result===2){
50+
thrownewERR_UNKNOWN_CREDENTIAL('Group',extraGroup);
51+
}
52+
}
53+
54+
functionsetgroups(groups){
55+
if(!ArrayIsArray(groups)){
56+
thrownewERR_INVALID_ARG_TYPE('groups','Array',groups);
57+
}
58+
for(leti=0;i<groups.length;i++){
59+
validateId(groups[i],`groups[${i}]`);
60+
}
61+
// Result is 0 on success. A positive integer indicates that the
62+
// corresponding group was not found.
63+
constresult=_setgroups(groups);
64+
if(result>0){
65+
thrownewERR_UNKNOWN_CREDENTIAL('Group',groups[result-1]);
66+
}
67+
}
68+
69+
functionwrapIdSetter(type,method){
70+
returnfunction(id){
71+
validateId(id,'id');
72+
// Result is 0 on success, 1 if credential is unknown.
73+
constresult=method(id);
74+
if(result===1){
75+
thrownewERR_UNKNOWN_CREDENTIAL(type,id);
76+
}
77+
};
78+
}
79+
80+
functionvalidateId(id,name){
81+
if(typeofid==='number'){
82+
validateUint32(id,name);
83+
}elseif(typeofid!=='string'){
84+
thrownewERR_INVALID_ARG_TYPE(name,['number','string'],id);
85+
}
86+
}
87+
88+
return{
89+
initgroups,
90+
setgroups,
91+
setegid: wrapIdSetter('Group',_setegid),
92+
seteuid: wrapIdSetter('User',_seteuid),
93+
setgid: wrapIdSetter('Group',_setgid),
94+
setuid: wrapIdSetter('User',_setuid)
95+
};
96+
}

0 commit comments

Comments
 (0)