Skip to content

Commit a89cc28

Browse files
addaleaxtargos
authored andcommitted
src: protect global state with mutexes
Protect environment variables and inherently per-process state with mutexes, to better accommodate Node’s usage in multi-threading environments. Thanks to Stephen Belanger for reviewing this change in its original PR. Refs: ayojs/ayo#82 PR-URL: #20542 Reviewed-By: Gus Caplan <me@gus.host> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
1 parent 2df99ac commit a89cc28

File tree

3 files changed

+22
-4
lines changed

3 files changed

+22
-4
lines changed

src/node.cc

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,9 @@ using v8::Value;
171171

172172
using AsyncHooks = Environment::AsyncHooks;
173173

174+
static Mutex process_mutex;
175+
static Mutex environ_mutex;
176+
174177
static bool print_eval = false;
175178
static bool force_repl = false;
176179
static bool syntax_check_only = false;
@@ -698,9 +701,12 @@ bool SafeGetenv(const char* key, std::string* text) {
698701
goto fail;
699702
#endif
700703

701-
if (const char* value = getenv(key)) {
702-
*text = value;
703-
return true;
704+
{
705+
Mutex::ScopedLock lock(environ_mutex);
706+
if (const char* value = getenv(key)) {
707+
*text = value;
708+
return true;
709+
}
704710
}
705711

706712
fail:
@@ -1358,6 +1364,7 @@ void AppendExceptionLine(Environment* env,
13581364
if (!can_set_arrow || (mode == FATAL_ERROR && !err_obj->IsNativeError())) {
13591365
if (env->printed_error())
13601366
return;
1367+
Mutex::ScopedLock lock(process_mutex);
13611368
env->set_printed_error(true);
13621369

13631370
uv_tty_reset_mode();
@@ -2624,7 +2631,6 @@ static void ProcessTitleSetter(Local<Name> property,
26242631
Local<Value> value,
26252632
const PropertyCallbackInfo<void>& info) {
26262633
node::Utf8Value title(info.GetIsolate(), value);
2627-
// TODO(piscisaureus): protect with a lock
26282634
uv_set_process_title(*title);
26292635
}
26302636

@@ -2635,6 +2641,7 @@ static void EnvGetter(Local<Name> property,
26352641
if (property->IsSymbol()) {
26362642
return info.GetReturnValue().SetUndefined();
26372643
}
2644+
Mutex::ScopedLock lock(environ_mutex);
26382645
#ifdef __POSIX__
26392646
node::Utf8Value key(isolate, property);
26402647
const char* val = getenv(*key);
@@ -2675,6 +2682,8 @@ static void EnvSetter(Local<Name> property,
26752682
"DEP0104").IsNothing())
26762683
return;
26772684
}
2685+
2686+
Mutex::ScopedLock lock(environ_mutex);
26782687
#ifdef __POSIX__
26792688
node::Utf8Value key(info.GetIsolate(), property);
26802689
node::Utf8Value val(info.GetIsolate(), value);
@@ -2695,6 +2704,7 @@ static void EnvSetter(Local<Name> property,
26952704

26962705
static void EnvQuery(Local<Name> property,
26972706
const PropertyCallbackInfo<Integer>& info) {
2707+
Mutex::ScopedLock lock(environ_mutex);
26982708
int32_t rc = -1; // Not found unless proven otherwise.
26992709
if (property->IsString()) {
27002710
#ifdef __POSIX__
@@ -2724,6 +2734,7 @@ static void EnvQuery(Local<Name> property,
27242734

27252735
static void EnvDeleter(Local<Name> property,
27262736
const PropertyCallbackInfo<Boolean>& info) {
2737+
Mutex::ScopedLock lock(environ_mutex);
27272738
if (property->IsString()) {
27282739
#ifdef __POSIX__
27292740
node::Utf8Value key(info.GetIsolate(), property);
@@ -2749,6 +2760,7 @@ static void EnvEnumerator(const PropertyCallbackInfo<Array>& info) {
27492760
Local<Value> argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
27502761
size_t idx = 0;
27512762

2763+
Mutex::ScopedLock lock(environ_mutex);
27522764
#ifdef __POSIX__
27532765
int size = 0;
27542766
while (environ[size])
@@ -2864,6 +2876,7 @@ static Local<Object> GetFeatures(Environment* env) {
28642876

28652877
static void DebugPortGetter(Local<Name> property,
28662878
const PropertyCallbackInfo<Value>& info) {
2879+
Mutex::ScopedLock lock(process_mutex);
28672880
int port = debug_options.port();
28682881
#if HAVE_INSPECTOR
28692882
if (port == 0) {
@@ -2879,6 +2892,7 @@ static void DebugPortGetter(Local<Name> property,
28792892
static void DebugPortSetter(Local<Name> property,
28802893
Local<Value> value,
28812894
const PropertyCallbackInfo<void>& info) {
2895+
Mutex::ScopedLock lock(process_mutex);
28822896
debug_options.set_port(value->Int32Value());
28832897
}
28842898

src/node_crypto.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,9 @@ void SecureContext::SetCert(const FunctionCallbackInfo<Value>& args) {
715715

716716
static X509_STORE* NewRootCertStore() {
717717
static std::vector<X509*> root_certs_vector;
718+
static Mutex root_certs_vector_mutex;
719+
Mutex::ScopedLock lock(root_certs_vector_mutex);
720+
718721
if (root_certs_vector.empty()) {
719722
for (size_t i = 0; i < arraysize(root_certs); i++) {
720723
BIO* bp = NodeBIO::NewFixed(root_certs[i], strlen(root_certs[i]));

src/node_internals.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
2626

2727
#include "node.h"
28+
#include "node_mutex.h"
2829
#include "node_persistent.h"
2930
#include "util-inl.h"
3031
#include "env-inl.h"

0 commit comments

Comments
 (0)