src: move per-process global variables into node::per_process
So that it's easier to tell whether we are manipulating per-process global states that may need to be treated with care to avoid races. Also added comments about these variables and moved some of them to a more suitable compilation unit: - Move `v8_initialized` to `util.h` since it's only used in `util.cc` and `node.cc` - Rename `process_mutex` to `tty_mutex` and move it into `node_errors.cc` since that's the only place it's used to guard the tty. - Move `per_process_opts_mutex` and `per_process_opts` into `node_options.h` and rename them to `per_process::cli_options[_mutex]` - Rename `node_isolate[_mutex]` to `per_process::main_isolate[_mutex]` PR-URL: https://github.com/nodejs/node/pull/25302 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
This commit is contained in:
parent
ae2d1f0e05
commit
9db9e7e541
@ -79,7 +79,8 @@ IsolateData::IsolateData(Isolate* isolate,
|
|||||||
if (platform_ != nullptr)
|
if (platform_ != nullptr)
|
||||||
platform_->RegisterIsolate(isolate_, event_loop);
|
platform_->RegisterIsolate(isolate_, event_loop);
|
||||||
|
|
||||||
options_.reset(new PerIsolateOptions(*per_process_opts->per_isolate));
|
options_.reset(
|
||||||
|
new PerIsolateOptions(*(per_process::cli_options->per_isolate)));
|
||||||
|
|
||||||
// Create string and private symbol properties as internalized one byte
|
// Create string and private symbol properties as internalized one byte
|
||||||
// strings after the platform is properly initialized.
|
// strings after the platform is properly initialized.
|
||||||
|
90
src/node.cc
90
src/node.cc
@ -139,21 +139,31 @@ using v8::Undefined;
|
|||||||
using v8::V8;
|
using v8::V8;
|
||||||
using v8::Value;
|
using v8::Value;
|
||||||
|
|
||||||
|
namespace per_process {
|
||||||
|
// Tells whether --prof is passed.
|
||||||
|
// TODO(joyeecheung): move env->options()->prof_process to
|
||||||
|
// per_process::cli_options.prof_process and use that instead.
|
||||||
static bool v8_is_profiling = false;
|
static bool v8_is_profiling = false;
|
||||||
|
|
||||||
// Bit flag used to track security reverts (see node_revert.h)
|
// TODO(joyeecheung): these are no longer necessary. Remove them.
|
||||||
unsigned int reverted = 0;
|
// See: https://github.com/nodejs/node/pull/25302#discussion_r244924196
|
||||||
|
// Isolate on the main thread
|
||||||
|
static Mutex main_isolate_mutex;
|
||||||
|
static Isolate* main_isolate;
|
||||||
|
|
||||||
|
// node_revert.h
|
||||||
|
// Bit flag used to track security reverts.
|
||||||
|
unsigned int reverted_cve = 0;
|
||||||
|
|
||||||
|
// util.h
|
||||||
|
// Tells whether the per-process V8::Initialize() is called and
|
||||||
|
// if it is safe to call v8::Isolate::GetCurrent().
|
||||||
bool v8_initialized = false;
|
bool v8_initialized = false;
|
||||||
|
|
||||||
|
// node_internals.h
|
||||||
// process-relative uptime base, initialized at start-up
|
// process-relative uptime base, initialized at start-up
|
||||||
double prog_start_time;
|
double prog_start_time;
|
||||||
|
} // namespace per_process
|
||||||
Mutex per_process_opts_mutex;
|
|
||||||
std::shared_ptr<PerProcessOptions> per_process_opts {
|
|
||||||
new PerProcessOptions() };
|
|
||||||
static Mutex node_isolate_mutex;
|
|
||||||
static Isolate* node_isolate;
|
|
||||||
|
|
||||||
// Ensures that __metadata trace events are only emitted
|
// Ensures that __metadata trace events are only emitted
|
||||||
// when tracing is enabled.
|
// when tracing is enabled.
|
||||||
@ -269,14 +279,15 @@ static struct {
|
|||||||
#endif // HAVE_INSPECTOR
|
#endif // HAVE_INSPECTOR
|
||||||
|
|
||||||
void StartTracingAgent() {
|
void StartTracingAgent() {
|
||||||
if (per_process_opts->trace_event_categories.empty()) {
|
if (per_process::cli_options->trace_event_categories.empty()) {
|
||||||
tracing_file_writer_ = tracing_agent_->DefaultHandle();
|
tracing_file_writer_ = tracing_agent_->DefaultHandle();
|
||||||
} else {
|
} else {
|
||||||
tracing_file_writer_ = tracing_agent_->AddClient(
|
tracing_file_writer_ = tracing_agent_->AddClient(
|
||||||
ParseCommaSeparatedSet(per_process_opts->trace_event_categories),
|
ParseCommaSeparatedSet(
|
||||||
|
per_process::cli_options->trace_event_categories),
|
||||||
std::unique_ptr<tracing::AsyncTraceWriter>(
|
std::unique_ptr<tracing::AsyncTraceWriter>(
|
||||||
new tracing::NodeTraceWriter(
|
new tracing::NodeTraceWriter(
|
||||||
per_process_opts->trace_event_file_pattern)),
|
per_process::cli_options->trace_event_file_pattern)),
|
||||||
tracing::Agent::kUseDefaultCategories);
|
tracing::Agent::kUseDefaultCategories);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -500,7 +511,7 @@ const char* signo_string(int signo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void* ArrayBufferAllocator::Allocate(size_t size) {
|
void* ArrayBufferAllocator::Allocate(size_t size) {
|
||||||
if (zero_fill_field_ || per_process_opts->zero_fill_all_buffers)
|
if (zero_fill_field_ || per_process::cli_options->zero_fill_all_buffers)
|
||||||
return UncheckedCalloc(size);
|
return UncheckedCalloc(size);
|
||||||
else
|
else
|
||||||
return UncheckedMalloc(size);
|
return UncheckedMalloc(size);
|
||||||
@ -1276,12 +1287,12 @@ void ProcessArgv(std::vector<std::string>* args,
|
|||||||
{
|
{
|
||||||
// TODO(addaleax): The mutex here should ideally be held during the
|
// TODO(addaleax): The mutex here should ideally be held during the
|
||||||
// entire function, but that doesn't play well with the exit() calls below.
|
// entire function, but that doesn't play well with the exit() calls below.
|
||||||
Mutex::ScopedLock lock(per_process_opts_mutex);
|
Mutex::ScopedLock lock(per_process::cli_options_mutex);
|
||||||
options_parser::PerProcessOptionsParser::instance.Parse(
|
options_parser::PerProcessOptionsParser::instance.Parse(
|
||||||
args,
|
args,
|
||||||
exec_args,
|
exec_args,
|
||||||
&v8_args,
|
&v8_args,
|
||||||
per_process_opts.get(),
|
per_process::cli_options.get(),
|
||||||
is_env ? kAllowedInEnvironment : kDisallowedInEnvironment,
|
is_env ? kAllowedInEnvironment : kDisallowedInEnvironment,
|
||||||
&errors);
|
&errors);
|
||||||
}
|
}
|
||||||
@ -1293,20 +1304,20 @@ void ProcessArgv(std::vector<std::string>* args,
|
|||||||
exit(9);
|
exit(9);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (per_process_opts->print_version) {
|
if (per_process::cli_options->print_version) {
|
||||||
printf("%s\n", NODE_VERSION);
|
printf("%s\n", NODE_VERSION);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (per_process_opts->print_v8_help) {
|
if (per_process::cli_options->print_v8_help) {
|
||||||
V8::SetFlagsFromString("--help", 6);
|
V8::SetFlagsFromString("--help", 6);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const std::string& cve : per_process_opts->security_reverts)
|
for (const std::string& cve : per_process::cli_options->security_reverts)
|
||||||
Revert(cve.c_str());
|
Revert(cve.c_str());
|
||||||
|
|
||||||
auto env_opts = per_process_opts->per_isolate->per_env;
|
auto env_opts = per_process::cli_options->per_isolate->per_env;
|
||||||
if (std::find(v8_args.begin(), v8_args.end(),
|
if (std::find(v8_args.begin(), v8_args.end(),
|
||||||
"--abort-on-uncaught-exception") != v8_args.end() ||
|
"--abort-on-uncaught-exception") != v8_args.end() ||
|
||||||
std::find(v8_args.begin(), v8_args.end(),
|
std::find(v8_args.begin(), v8_args.end(),
|
||||||
@ -1319,14 +1330,14 @@ void ProcessArgv(std::vector<std::string>* args,
|
|||||||
// behavior but it could also interfere with the user's intentions in ways
|
// behavior but it could also interfere with the user's intentions in ways
|
||||||
// we fail to anticipate. Dillema.
|
// we fail to anticipate. Dillema.
|
||||||
if (std::find(v8_args.begin(), v8_args.end(), "--prof") != v8_args.end()) {
|
if (std::find(v8_args.begin(), v8_args.end(), "--prof") != v8_args.end()) {
|
||||||
v8_is_profiling = true;
|
per_process::v8_is_profiling = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __POSIX__
|
#ifdef __POSIX__
|
||||||
// Block SIGPROF signals when sleeping in epoll_wait/kevent/etc. Avoids the
|
// Block SIGPROF signals when sleeping in epoll_wait/kevent/etc. Avoids the
|
||||||
// performance penalty of frequent EINTR wakeups when the profiler is running.
|
// performance penalty of frequent EINTR wakeups when the profiler is running.
|
||||||
// Only do this for v8.log profiling, as it breaks v8::CpuProfiler users.
|
// Only do this for v8.log profiling, as it breaks v8::CpuProfiler users.
|
||||||
if (v8_is_profiling) {
|
if (per_process::v8_is_profiling) {
|
||||||
uv_loop_configure(uv_default_loop(), UV_LOOP_BLOCK_SIGNAL, SIGPROF);
|
uv_loop_configure(uv_default_loop(), UV_LOOP_BLOCK_SIGNAL, SIGPROF);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1355,7 +1366,7 @@ void ProcessArgv(std::vector<std::string>* args,
|
|||||||
void Init(std::vector<std::string>* argv,
|
void Init(std::vector<std::string>* argv,
|
||||||
std::vector<std::string>* exec_argv) {
|
std::vector<std::string>* exec_argv) {
|
||||||
// Initialize prog_start_time to get relative uptime.
|
// Initialize prog_start_time to get relative uptime.
|
||||||
prog_start_time = static_cast<double>(uv_now(uv_default_loop()));
|
per_process::prog_start_time = static_cast<double>(uv_now(uv_default_loop()));
|
||||||
|
|
||||||
// Register built-in modules
|
// Register built-in modules
|
||||||
binding::RegisterBuiltinModules();
|
binding::RegisterBuiltinModules();
|
||||||
@ -1371,7 +1382,7 @@ void Init(std::vector<std::string>* argv,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::shared_ptr<EnvironmentOptions> default_env_options =
|
std::shared_ptr<EnvironmentOptions> default_env_options =
|
||||||
per_process_opts->per_isolate->per_env;
|
per_process::cli_options->per_isolate->per_env;
|
||||||
{
|
{
|
||||||
std::string text;
|
std::string text;
|
||||||
default_env_options->pending_deprecation =
|
default_env_options->pending_deprecation =
|
||||||
@ -1400,7 +1411,7 @@ void Init(std::vector<std::string>* argv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if HAVE_OPENSSL
|
#if HAVE_OPENSSL
|
||||||
std::string* openssl_config = &per_process_opts->openssl_config;
|
std::string* openssl_config = &per_process::cli_options->openssl_config;
|
||||||
if (openssl_config->empty()) {
|
if (openssl_config->empty()) {
|
||||||
credentials::SafeGetenv("OPENSSL_CONF", openssl_config);
|
credentials::SafeGetenv("OPENSSL_CONF", openssl_config);
|
||||||
}
|
}
|
||||||
@ -1434,16 +1445,17 @@ void Init(std::vector<std::string>* argv,
|
|||||||
ProcessArgv(argv, exec_argv, false);
|
ProcessArgv(argv, exec_argv, false);
|
||||||
|
|
||||||
// Set the process.title immediately after processing argv if --title is set.
|
// Set the process.title immediately after processing argv if --title is set.
|
||||||
if (!per_process_opts->title.empty())
|
if (!per_process::cli_options->title.empty())
|
||||||
uv_set_process_title(per_process_opts->title.c_str());
|
uv_set_process_title(per_process::cli_options->title.c_str());
|
||||||
|
|
||||||
#if defined(NODE_HAVE_I18N_SUPPORT)
|
#if defined(NODE_HAVE_I18N_SUPPORT)
|
||||||
// If the parameter isn't given, use the env variable.
|
// If the parameter isn't given, use the env variable.
|
||||||
if (per_process_opts->icu_data_dir.empty())
|
if (per_process::cli_options->icu_data_dir.empty())
|
||||||
credentials::SafeGetenv("NODE_ICU_DATA", &per_process_opts->icu_data_dir);
|
credentials::SafeGetenv("NODE_ICU_DATA",
|
||||||
|
&per_process::cli_options->icu_data_dir);
|
||||||
// Initialize ICU.
|
// Initialize ICU.
|
||||||
// If icu_data_dir is empty here, it will load the 'minimal' data.
|
// If icu_data_dir is empty here, it will load the 'minimal' data.
|
||||||
if (!i18n::InitializeICUDirectory(per_process_opts->icu_data_dir)) {
|
if (!i18n::InitializeICUDirectory(per_process::cli_options->icu_data_dir)) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"%s: could not initialize ICU "
|
"%s: could not initialize ICU "
|
||||||
"(check NODE_ICU_DATA or --icu-data-dir parameters)\n",
|
"(check NODE_ICU_DATA or --icu-data-dir parameters)\n",
|
||||||
@ -1604,7 +1616,7 @@ Environment* CreateEnvironment(IsolateData* isolate_data,
|
|||||||
std::vector<std::string> args(argv, argv + argc);
|
std::vector<std::string> args(argv, argv + argc);
|
||||||
std::vector<std::string> exec_args(exec_argv, exec_argv + exec_argc);
|
std::vector<std::string> exec_args(exec_argv, exec_argv + exec_argc);
|
||||||
Environment* env = new Environment(isolate_data, context);
|
Environment* env = new Environment(isolate_data, context);
|
||||||
env->Start(args, exec_args, v8_is_profiling);
|
env->Start(args, exec_args, per_process::v8_is_profiling);
|
||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1678,7 +1690,7 @@ inline int Start(Isolate* isolate, IsolateData* isolate_data,
|
|||||||
Local<Context> context = NewContext(isolate);
|
Local<Context> context = NewContext(isolate);
|
||||||
Context::Scope context_scope(context);
|
Context::Scope context_scope(context);
|
||||||
Environment env(isolate_data, context);
|
Environment env(isolate_data, context);
|
||||||
env.Start(args, exec_args, v8_is_profiling);
|
env.Start(args, exec_args, per_process::v8_is_profiling);
|
||||||
|
|
||||||
const char* path = args.size() > 1 ? args[1].c_str() : nullptr;
|
const char* path = args.size() > 1 ? args[1].c_str() : nullptr;
|
||||||
StartInspector(&env, path);
|
StartInspector(&env, path);
|
||||||
@ -1785,9 +1797,9 @@ inline int Start(uv_loop_t* event_loop,
|
|||||||
return 12; // Signal internal error.
|
return 12; // Signal internal error.
|
||||||
|
|
||||||
{
|
{
|
||||||
Mutex::ScopedLock scoped_lock(node_isolate_mutex);
|
Mutex::ScopedLock scoped_lock(per_process::main_isolate_mutex);
|
||||||
CHECK_NULL(node_isolate);
|
CHECK_NULL(per_process::main_isolate);
|
||||||
node_isolate = isolate;
|
per_process::main_isolate = isolate;
|
||||||
}
|
}
|
||||||
|
|
||||||
int exit_code;
|
int exit_code;
|
||||||
@ -1812,9 +1824,9 @@ inline int Start(uv_loop_t* event_loop,
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Mutex::ScopedLock scoped_lock(node_isolate_mutex);
|
Mutex::ScopedLock scoped_lock(per_process::main_isolate_mutex);
|
||||||
CHECK_EQ(node_isolate, isolate);
|
CHECK_EQ(per_process::main_isolate, isolate);
|
||||||
node_isolate = nullptr;
|
per_process::main_isolate = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
isolate->Dispose();
|
isolate->Dispose();
|
||||||
@ -1862,14 +1874,14 @@ int Start(int argc, char** argv) {
|
|||||||
V8::SetEntropySource(crypto::EntropySource);
|
V8::SetEntropySource(crypto::EntropySource);
|
||||||
#endif // HAVE_OPENSSL
|
#endif // HAVE_OPENSSL
|
||||||
|
|
||||||
InitializeV8Platform(per_process_opts->v8_thread_pool_size);
|
InitializeV8Platform(per_process::cli_options->v8_thread_pool_size);
|
||||||
V8::Initialize();
|
V8::Initialize();
|
||||||
performance::performance_v8_start = PERFORMANCE_NOW();
|
performance::performance_v8_start = PERFORMANCE_NOW();
|
||||||
v8_initialized = true;
|
per_process::v8_initialized = true;
|
||||||
const int exit_code =
|
const int exit_code =
|
||||||
Start(uv_default_loop(), args, exec_args);
|
Start(uv_default_loop(), args, exec_args);
|
||||||
v8_platform.StopTracingAgent();
|
v8_platform.StopTracingAgent();
|
||||||
v8_initialized = false;
|
per_process::v8_initialized = false;
|
||||||
V8::Dispose();
|
V8::Dispose();
|
||||||
|
|
||||||
// uv_run cannot be called from the time before the beforeExit callback
|
// uv_run cannot be called from the time before the beforeExit callback
|
||||||
|
@ -59,9 +59,9 @@ namespace node {
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
inline void* BufferMalloc(size_t length) {
|
inline void* BufferMalloc(size_t length) {
|
||||||
return per_process_opts->zero_fill_all_buffers ?
|
return per_process::cli_options->zero_fill_all_buffers ?
|
||||||
node::UncheckedCalloc(length) :
|
node::UncheckedCalloc(length) :
|
||||||
node::UncheckedMalloc(length);
|
node::UncheckedMalloc(length);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -41,7 +41,7 @@ static void Initialize(Local<Object> target,
|
|||||||
#ifdef NODE_FIPS_MODE
|
#ifdef NODE_FIPS_MODE
|
||||||
READONLY_TRUE_PROPERTY(target, "fipsMode");
|
READONLY_TRUE_PROPERTY(target, "fipsMode");
|
||||||
// TODO(addaleax): Use options parser variable instead.
|
// TODO(addaleax): Use options parser variable instead.
|
||||||
if (per_process_opts->force_fips_crypto)
|
if (per_process::cli_options->force_fips_crypto)
|
||||||
READONLY_TRUE_PROPERTY(target, "fipsForced");
|
READONLY_TRUE_PROPERTY(target, "fipsForced");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1234,9 +1234,10 @@ void DefineCryptoConstants(Local<Object> target) {
|
|||||||
NODE_DEFINE_STRING_CONSTANT(target,
|
NODE_DEFINE_STRING_CONSTANT(target,
|
||||||
"defaultCoreCipherList",
|
"defaultCoreCipherList",
|
||||||
DEFAULT_CIPHER_LIST_CORE);
|
DEFAULT_CIPHER_LIST_CORE);
|
||||||
NODE_DEFINE_STRING_CONSTANT(target,
|
NODE_DEFINE_STRING_CONSTANT(
|
||||||
"defaultCipherList",
|
target,
|
||||||
per_process_opts->tls_cipher_list.c_str());
|
"defaultCipherList",
|
||||||
|
per_process::cli_options->tls_cipher_list.c_str());
|
||||||
|
|
||||||
NODE_DEFINE_CONSTANT(target, TLS1_VERSION);
|
NODE_DEFINE_CONSTANT(target, TLS1_VERSION);
|
||||||
NODE_DEFINE_CONSTANT(target, TLS1_1_VERSION);
|
NODE_DEFINE_CONSTANT(target, TLS1_1_VERSION);
|
||||||
|
@ -38,7 +38,7 @@ bool SafeGetenv(const char* key, std::string* text) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
{
|
{
|
||||||
Mutex::ScopedLock lock(environ_mutex);
|
Mutex::ScopedLock lock(per_process::env_var_mutex);
|
||||||
if (const char* value = getenv(key)) {
|
if (const char* value = getenv(key)) {
|
||||||
*text = value;
|
*text = value;
|
||||||
return true;
|
return true;
|
||||||
|
@ -787,7 +787,7 @@ static X509_STORE* NewRootCertStore() {
|
|||||||
if (*system_cert_path != '\0') {
|
if (*system_cert_path != '\0') {
|
||||||
X509_STORE_load_locations(store, system_cert_path, nullptr);
|
X509_STORE_load_locations(store, system_cert_path, nullptr);
|
||||||
}
|
}
|
||||||
if (per_process_opts->ssl_openssl_cert_store) {
|
if (per_process::cli_options->ssl_openssl_cert_store) {
|
||||||
X509_STORE_set_default_paths(store);
|
X509_STORE_set_default_paths(store);
|
||||||
} else {
|
} else {
|
||||||
for (X509* cert : root_certs_vector) {
|
for (X509* cert : root_certs_vector) {
|
||||||
@ -6183,16 +6183,15 @@ void InitCryptoOnce() {
|
|||||||
OPENSSL_no_config();
|
OPENSSL_no_config();
|
||||||
|
|
||||||
// --openssl-config=...
|
// --openssl-config=...
|
||||||
if (!per_process_opts->openssl_config.empty()) {
|
if (!per_process::cli_options->openssl_config.empty()) {
|
||||||
OPENSSL_load_builtin_modules();
|
OPENSSL_load_builtin_modules();
|
||||||
#ifndef OPENSSL_NO_ENGINE
|
#ifndef OPENSSL_NO_ENGINE
|
||||||
ENGINE_load_builtin_engines();
|
ENGINE_load_builtin_engines();
|
||||||
#endif
|
#endif
|
||||||
ERR_clear_error();
|
ERR_clear_error();
|
||||||
CONF_modules_load_file(
|
CONF_modules_load_file(per_process::cli_options->openssl_config.c_str(),
|
||||||
per_process_opts->openssl_config.c_str(),
|
nullptr,
|
||||||
nullptr,
|
CONF_MFLAGS_DEFAULT_SECTION);
|
||||||
CONF_MFLAGS_DEFAULT_SECTION);
|
|
||||||
int err = ERR_get_error();
|
int err = ERR_get_error();
|
||||||
if (0 != err) {
|
if (0 != err) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@ -6208,8 +6207,8 @@ void InitCryptoOnce() {
|
|||||||
#ifdef NODE_FIPS_MODE
|
#ifdef NODE_FIPS_MODE
|
||||||
/* Override FIPS settings in cnf file, if needed. */
|
/* Override FIPS settings in cnf file, if needed. */
|
||||||
unsigned long err = 0; // NOLINT(runtime/int)
|
unsigned long err = 0; // NOLINT(runtime/int)
|
||||||
if (per_process_opts->enable_fips_crypto ||
|
if (per_process::cli_options->enable_fips_crypto ||
|
||||||
per_process_opts->force_fips_crypto) {
|
per_process::cli_options->force_fips_crypto) {
|
||||||
if (0 == FIPS_mode() && !FIPS_mode_set(1)) {
|
if (0 == FIPS_mode() && !FIPS_mode_set(1)) {
|
||||||
err = ERR_get_error();
|
err = ERR_get_error();
|
||||||
}
|
}
|
||||||
@ -6272,7 +6271,7 @@ void GetFipsCrypto(const FunctionCallbackInfo<Value>& args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SetFipsCrypto(const FunctionCallbackInfo<Value>& args) {
|
void SetFipsCrypto(const FunctionCallbackInfo<Value>& args) {
|
||||||
CHECK(!per_process_opts->force_fips_crypto);
|
CHECK(!per_process::cli_options->force_fips_crypto);
|
||||||
Environment* env = Environment::GetCurrent(args);
|
Environment* env = Environment::GetCurrent(args);
|
||||||
const bool enabled = FIPS_mode();
|
const bool enabled = FIPS_mode();
|
||||||
bool enable = args[0]->BooleanValue(env->isolate());
|
bool enable = args[0]->BooleanValue(env->isolate());
|
||||||
|
@ -25,13 +25,17 @@ using v8::PropertyCallbackInfo;
|
|||||||
using v8::String;
|
using v8::String;
|
||||||
using v8::Value;
|
using v8::Value;
|
||||||
|
|
||||||
|
namespace per_process {
|
||||||
|
Mutex env_var_mutex;
|
||||||
|
} // namespace per_process
|
||||||
|
|
||||||
static void EnvGetter(Local<Name> property,
|
static void EnvGetter(Local<Name> property,
|
||||||
const PropertyCallbackInfo<Value>& info) {
|
const PropertyCallbackInfo<Value>& info) {
|
||||||
Isolate* isolate = info.GetIsolate();
|
Isolate* isolate = info.GetIsolate();
|
||||||
if (property->IsSymbol()) {
|
if (property->IsSymbol()) {
|
||||||
return info.GetReturnValue().SetUndefined();
|
return info.GetReturnValue().SetUndefined();
|
||||||
}
|
}
|
||||||
Mutex::ScopedLock lock(environ_mutex);
|
Mutex::ScopedLock lock(per_process::env_var_mutex);
|
||||||
#ifdef __POSIX__
|
#ifdef __POSIX__
|
||||||
node::Utf8Value key(isolate, property);
|
node::Utf8Value key(isolate, property);
|
||||||
const char* val = getenv(*key);
|
const char* val = getenv(*key);
|
||||||
@ -80,7 +84,7 @@ static void EnvSetter(Local<Name> property,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Mutex::ScopedLock lock(environ_mutex);
|
Mutex::ScopedLock lock(per_process::env_var_mutex);
|
||||||
#ifdef __POSIX__
|
#ifdef __POSIX__
|
||||||
node::Utf8Value key(info.GetIsolate(), property);
|
node::Utf8Value key(info.GetIsolate(), property);
|
||||||
node::Utf8Value val(info.GetIsolate(), value);
|
node::Utf8Value val(info.GetIsolate(), value);
|
||||||
@ -100,7 +104,7 @@ static void EnvSetter(Local<Name> property,
|
|||||||
|
|
||||||
static void EnvQuery(Local<Name> property,
|
static void EnvQuery(Local<Name> property,
|
||||||
const PropertyCallbackInfo<Integer>& info) {
|
const PropertyCallbackInfo<Integer>& info) {
|
||||||
Mutex::ScopedLock lock(environ_mutex);
|
Mutex::ScopedLock lock(per_process::env_var_mutex);
|
||||||
int32_t rc = -1; // Not found unless proven otherwise.
|
int32_t rc = -1; // Not found unless proven otherwise.
|
||||||
if (property->IsString()) {
|
if (property->IsString()) {
|
||||||
#ifdef __POSIX__
|
#ifdef __POSIX__
|
||||||
@ -127,7 +131,7 @@ static void EnvQuery(Local<Name> property,
|
|||||||
|
|
||||||
static void EnvDeleter(Local<Name> property,
|
static void EnvDeleter(Local<Name> property,
|
||||||
const PropertyCallbackInfo<Boolean>& info) {
|
const PropertyCallbackInfo<Boolean>& info) {
|
||||||
Mutex::ScopedLock lock(environ_mutex);
|
Mutex::ScopedLock lock(per_process::env_var_mutex);
|
||||||
if (property->IsString()) {
|
if (property->IsString()) {
|
||||||
#ifdef __POSIX__
|
#ifdef __POSIX__
|
||||||
node::Utf8Value key(info.GetIsolate(), property);
|
node::Utf8Value key(info.GetIsolate(), property);
|
||||||
@ -148,7 +152,7 @@ static void EnvEnumerator(const PropertyCallbackInfo<Array>& info) {
|
|||||||
Environment* env = Environment::GetCurrent(info);
|
Environment* env = Environment::GetCurrent(info);
|
||||||
Isolate* isolate = env->isolate();
|
Isolate* isolate = env->isolate();
|
||||||
|
|
||||||
Mutex::ScopedLock lock(environ_mutex);
|
Mutex::ScopedLock lock(per_process::env_var_mutex);
|
||||||
Local<Array> envarr;
|
Local<Array> envarr;
|
||||||
int env_size = 0;
|
int env_size = 0;
|
||||||
#ifdef __POSIX__
|
#ifdef __POSIX__
|
||||||
|
@ -35,6 +35,10 @@ bool IsExceptionDecorated(Environment* env, Local<Value> er) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace per_process {
|
||||||
|
static Mutex tty_mutex;
|
||||||
|
} // namespace per_process
|
||||||
|
|
||||||
void AppendExceptionLine(Environment* env,
|
void AppendExceptionLine(Environment* env,
|
||||||
Local<Value> er,
|
Local<Value> er,
|
||||||
Local<Message> message,
|
Local<Message> message,
|
||||||
@ -137,7 +141,7 @@ void AppendExceptionLine(Environment* env,
|
|||||||
// by the caller.
|
// by the caller.
|
||||||
if (!can_set_arrow || (mode == FATAL_ERROR && !err_obj->IsNativeError())) {
|
if (!can_set_arrow || (mode == FATAL_ERROR && !err_obj->IsNativeError())) {
|
||||||
if (env->printed_error()) return;
|
if (env->printed_error()) return;
|
||||||
Mutex::ScopedLock lock(process_mutex);
|
Mutex::ScopedLock lock(per_process::tty_mutex);
|
||||||
env->set_printed_error(true);
|
env->set_printed_error(true);
|
||||||
|
|
||||||
uv_tty_reset_mode();
|
uv_tty_reset_mode();
|
||||||
|
@ -830,7 +830,7 @@ class Parser : public AsyncWrap, public StreamListener {
|
|||||||
int TrackHeader(size_t len) {
|
int TrackHeader(size_t len) {
|
||||||
#ifdef NODE_EXPERIMENTAL_HTTP
|
#ifdef NODE_EXPERIMENTAL_HTTP
|
||||||
header_nread_ += len;
|
header_nread_ += len;
|
||||||
if (header_nread_ >= per_process_opts->max_http_header_size) {
|
if (header_nread_ >= per_process::cli_options->max_http_header_size) {
|
||||||
llhttp_set_error_reason(&parser_, "HPE_HEADER_OVERFLOW:Header overflow");
|
llhttp_set_error_reason(&parser_, "HPE_HEADER_OVERFLOW:Header overflow");
|
||||||
return HPE_USER;
|
return HPE_USER;
|
||||||
}
|
}
|
||||||
@ -915,7 +915,8 @@ const parser_settings_t Parser::settings = {
|
|||||||
|
|
||||||
#ifndef NODE_EXPERIMENTAL_HTTP
|
#ifndef NODE_EXPERIMENTAL_HTTP
|
||||||
void InitMaxHttpHeaderSizeOnce() {
|
void InitMaxHttpHeaderSizeOnce() {
|
||||||
const uint32_t max_http_header_size = per_process_opts->max_http_header_size;
|
const uint32_t max_http_header_size =
|
||||||
|
per_process::cli_options->max_http_header_size;
|
||||||
http_parser_set_max_header_size(max_http_header_size);
|
http_parser_set_max_header_size(max_http_header_size);
|
||||||
}
|
}
|
||||||
#endif /* NODE_EXPERIMENTAL_HTTP */
|
#endif /* NODE_EXPERIMENTAL_HTTP */
|
||||||
|
@ -83,14 +83,10 @@ namespace native_module {
|
|||||||
class NativeModuleLoader;
|
class NativeModuleLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern Mutex process_mutex;
|
namespace per_process {
|
||||||
extern Mutex environ_mutex;
|
extern Mutex env_var_mutex;
|
||||||
|
extern double prog_start_time;
|
||||||
// Tells whether it is safe to call v8::Isolate::GetCurrent().
|
} // namespace per_process
|
||||||
extern bool v8_initialized;
|
|
||||||
|
|
||||||
extern Mutex per_process_opts_mutex;
|
|
||||||
extern std::shared_ptr<PerProcessOptions> per_process_opts;
|
|
||||||
|
|
||||||
// Forward declaration
|
// Forward declaration
|
||||||
class Environment;
|
class Environment;
|
||||||
@ -699,8 +695,6 @@ static inline const char* errno_string(int errorno) {
|
|||||||
|
|
||||||
// Functions defined in node.cc that are exposed via the bootstrapper object
|
// Functions defined in node.cc that are exposed via the bootstrapper object
|
||||||
|
|
||||||
extern double prog_start_time;
|
|
||||||
|
|
||||||
void RawDebug(const v8::FunctionCallbackInfo<v8::Value>& args);
|
void RawDebug(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||||
|
|
||||||
void DebugPortGetter(v8::Local<v8::Name> property,
|
void DebugPortGetter(v8::Local<v8::Name> property,
|
||||||
|
@ -17,6 +17,11 @@ using v8::Value;
|
|||||||
|
|
||||||
namespace node {
|
namespace node {
|
||||||
|
|
||||||
|
namespace per_process {
|
||||||
|
Mutex cli_options_mutex;
|
||||||
|
std::shared_ptr<PerProcessOptions> cli_options{new PerProcessOptions()};
|
||||||
|
} // namespace per_process
|
||||||
|
|
||||||
void PerProcessOptions::CheckOptions(std::vector<std::string>* errors) {
|
void PerProcessOptions::CheckOptions(std::vector<std::string>* errors) {
|
||||||
#if HAVE_OPENSSL
|
#if HAVE_OPENSSL
|
||||||
if (use_openssl_ca && use_bundled_ca) {
|
if (use_openssl_ca && use_bundled_ca) {
|
||||||
@ -397,7 +402,7 @@ HostPort SplitHostPort(const std::string& arg,
|
|||||||
// Return a map containing all the options and their metadata as well
|
// Return a map containing all the options and their metadata as well
|
||||||
// as the aliases
|
// as the aliases
|
||||||
void GetOptions(const FunctionCallbackInfo<Value>& args) {
|
void GetOptions(const FunctionCallbackInfo<Value>& args) {
|
||||||
Mutex::ScopedLock lock(per_process_opts_mutex);
|
Mutex::ScopedLock lock(per_process::cli_options_mutex);
|
||||||
Environment* env = Environment::GetCurrent(args);
|
Environment* env = Environment::GetCurrent(args);
|
||||||
Isolate* isolate = env->isolate();
|
Isolate* isolate = env->isolate();
|
||||||
Local<Context> context = env->context();
|
Local<Context> context = env->context();
|
||||||
@ -405,13 +410,13 @@ void GetOptions(const FunctionCallbackInfo<Value>& args) {
|
|||||||
// Temporarily act as if the current Environment's/IsolateData's options were
|
// Temporarily act as if the current Environment's/IsolateData's options were
|
||||||
// the default options, i.e. like they are the ones we'd access for global
|
// the default options, i.e. like they are the ones we'd access for global
|
||||||
// options parsing, so that all options are available from the main parser.
|
// options parsing, so that all options are available from the main parser.
|
||||||
auto original_per_isolate = per_process_opts->per_isolate;
|
auto original_per_isolate = per_process::cli_options->per_isolate;
|
||||||
per_process_opts->per_isolate = env->isolate_data()->options();
|
per_process::cli_options->per_isolate = env->isolate_data()->options();
|
||||||
auto original_per_env = per_process_opts->per_isolate->per_env;
|
auto original_per_env = per_process::cli_options->per_isolate->per_env;
|
||||||
per_process_opts->per_isolate->per_env = env->options();
|
per_process::cli_options->per_isolate->per_env = env->options();
|
||||||
OnScopeLeave on_scope_leave([&]() {
|
OnScopeLeave on_scope_leave([&]() {
|
||||||
per_process_opts->per_isolate->per_env = original_per_env;
|
per_process::cli_options->per_isolate->per_env = original_per_env;
|
||||||
per_process_opts->per_isolate = original_per_isolate;
|
per_process::cli_options->per_isolate = original_per_isolate;
|
||||||
});
|
});
|
||||||
|
|
||||||
const auto& parser = PerProcessOptionsParser::instance;
|
const auto& parser = PerProcessOptionsParser::instance;
|
||||||
@ -421,7 +426,7 @@ void GetOptions(const FunctionCallbackInfo<Value>& args) {
|
|||||||
Local<Value> value;
|
Local<Value> value;
|
||||||
const auto& option_info = item.second;
|
const auto& option_info = item.second;
|
||||||
auto field = option_info.field;
|
auto field = option_info.field;
|
||||||
PerProcessOptions* opts = per_process_opts.get();
|
PerProcessOptions* opts = per_process::cli_options.get();
|
||||||
switch (option_info.type) {
|
switch (option_info.type) {
|
||||||
case kNoOp:
|
case kNoOp:
|
||||||
case kV8Option:
|
case kV8Option:
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "node_constants.h"
|
#include "node_constants.h"
|
||||||
|
#include "node_mutex.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
namespace node {
|
namespace node {
|
||||||
@ -422,6 +423,13 @@ class PerProcessOptionsParser : public OptionsParser<PerProcessOptions> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
} // namespace options_parser
|
} // namespace options_parser
|
||||||
|
|
||||||
|
namespace per_process {
|
||||||
|
|
||||||
|
extern Mutex cli_options_mutex;
|
||||||
|
extern std::shared_ptr<PerProcessOptions> cli_options;
|
||||||
|
|
||||||
|
} // namespace per_process
|
||||||
} // namespace node
|
} // namespace node
|
||||||
|
|
||||||
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
|
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
|
||||||
|
@ -50,9 +50,6 @@ using v8::Uint32;
|
|||||||
using v8::Uint32Array;
|
using v8::Uint32Array;
|
||||||
using v8::Value;
|
using v8::Value;
|
||||||
|
|
||||||
Mutex process_mutex;
|
|
||||||
Mutex environ_mutex;
|
|
||||||
|
|
||||||
// Microseconds in a second, as a float, used in CPUUsage() below
|
// Microseconds in a second, as a float, used in CPUUsage() below
|
||||||
#define MICROS_PER_SEC 1e6
|
#define MICROS_PER_SEC 1e6
|
||||||
// used in Hrtime() below
|
// used in Hrtime() below
|
||||||
@ -244,7 +241,7 @@ static void Uptime(const FunctionCallbackInfo<Value>& args) {
|
|||||||
double uptime;
|
double uptime;
|
||||||
|
|
||||||
uv_update_time(env->event_loop());
|
uv_update_time(env->event_loop());
|
||||||
uptime = uv_now(env->event_loop()) - prog_start_time;
|
uptime = uv_now(env->event_loop()) - per_process::prog_start_time;
|
||||||
|
|
||||||
args.GetReturnValue().Set(uptime / 1000);
|
args.GetReturnValue().Set(uptime / 1000);
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,9 @@ enum reversion {
|
|||||||
#undef V
|
#undef V
|
||||||
};
|
};
|
||||||
|
|
||||||
extern unsigned int reverted;
|
namespace per_process {
|
||||||
|
extern unsigned int reverted_cve;
|
||||||
|
}
|
||||||
|
|
||||||
inline const char* RevertMessage(const reversion cve) {
|
inline const char* RevertMessage(const reversion cve) {
|
||||||
#define V(code, label, msg) case SECURITY_REVERT_##code: return label ": " msg;
|
#define V(code, label, msg) case SECURITY_REVERT_##code: return label ": " msg;
|
||||||
@ -37,7 +39,7 @@ inline const char* RevertMessage(const reversion cve) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void Revert(const reversion cve) {
|
inline void Revert(const reversion cve) {
|
||||||
reverted |= 1 << cve;
|
per_process::reverted_cve |= 1 << cve;
|
||||||
printf("SECURITY WARNING: Reverting %s\n", RevertMessage(cve));
|
printf("SECURITY WARNING: Reverting %s\n", RevertMessage(cve));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +53,7 @@ inline void Revert(const char* cve) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool IsReverted(const reversion cve) {
|
inline bool IsReverted(const reversion cve) {
|
||||||
return reverted & (1 << cve);
|
return per_process::reverted_cve & (1 << cve);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool IsReverted(const char* cve) {
|
inline bool IsReverted(const char* cve) {
|
||||||
|
@ -101,7 +101,7 @@ BufferValue::BufferValue(Isolate* isolate, Local<Value> value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LowMemoryNotification() {
|
void LowMemoryNotification() {
|
||||||
if (v8_initialized) {
|
if (per_process::v8_initialized) {
|
||||||
auto isolate = Isolate::GetCurrent();
|
auto isolate = Isolate::GetCurrent();
|
||||||
if (isolate != nullptr) {
|
if (isolate != nullptr) {
|
||||||
isolate->LowMemoryNotification();
|
isolate->LowMemoryNotification();
|
||||||
|
@ -74,6 +74,12 @@ inline char* UncheckedCalloc(size_t n);
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
inline T MultiplyWithOverflowCheck(T a, T b);
|
inline T MultiplyWithOverflowCheck(T a, T b);
|
||||||
|
|
||||||
|
namespace per_process {
|
||||||
|
// Tells whether the per-process V8::Initialize() is called and
|
||||||
|
// if it is safe to call v8::Isolate::GetCurrent().
|
||||||
|
extern bool v8_initialized;
|
||||||
|
} // namespace per_process
|
||||||
|
|
||||||
// Used by the allocation functions when allocation fails.
|
// Used by the allocation functions when allocation fails.
|
||||||
// Thin wrapper around v8::Isolate::LowMemoryNotification() that checks
|
// Thin wrapper around v8::Isolate::LowMemoryNotification() that checks
|
||||||
// whether V8 is initialized.
|
// whether V8 is initialized.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user