Skip to content

Commit 2c52f65

Browse files
committed
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 <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]>
1 parent ccdee34 commit 2c52f65

File tree

3 files changed

+22
-4
lines changed

3 files changed

+22
-4
lines changed

src/node.cc

+18-4
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,9 @@ using v8::Value;
172172

173173
using AsyncHooks = Environment::AsyncHooks;
174174

175+
static Mutex process_mutex;
176+
static Mutex environ_mutex;
177+
175178
static bool print_eval = false;
176179
static bool force_repl = false;
177180
static bool syntax_check_only = false;
@@ -699,9 +702,12 @@ bool SafeGetenv(const char* key, std::string* text) {
699702
goto fail;
700703
#endif
701704

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

707713
fail:
@@ -1359,6 +1365,7 @@ void AppendExceptionLine(Environment* env,
13591365
if (!can_set_arrow || (mode == FATAL_ERROR && !err_obj->IsNativeError())) {
13601366
if (env->printed_error())
13611367
return;
1368+
Mutex::ScopedLock lock(process_mutex);
13621369
env->set_printed_error(true);
13631370

13641371
uv_tty_reset_mode();
@@ -2610,7 +2617,6 @@ static void ProcessTitleSetter(Local<Name> property,
26102617
Local<Value> value,
26112618
const PropertyCallbackInfo<void>& info) {
26122619
node::Utf8Value title(info.GetIsolate(), value);
2613-
// TODO(piscisaureus): protect with a lock
26142620
uv_set_process_title(*title);
26152621
}
26162622

@@ -2621,6 +2627,7 @@ static void EnvGetter(Local<Name> property,
26212627
if (property->IsSymbol()) {
26222628
return info.GetReturnValue().SetUndefined();
26232629
}
2630+
Mutex::ScopedLock lock(environ_mutex);
26242631
#ifdef __POSIX__
26252632
node::Utf8Value key(isolate, property);
26262633
const char* val = getenv(*key);
@@ -2661,6 +2668,8 @@ static void EnvSetter(Local<Name> property,
26612668
"DEP0104").IsNothing())
26622669
return;
26632670
}
2671+
2672+
Mutex::ScopedLock lock(environ_mutex);
26642673
#ifdef __POSIX__
26652674
node::Utf8Value key(info.GetIsolate(), property);
26662675
node::Utf8Value val(info.GetIsolate(), value);
@@ -2681,6 +2690,7 @@ static void EnvSetter(Local<Name> property,
26812690

26822691
static void EnvQuery(Local<Name> property,
26832692
const PropertyCallbackInfo<Integer>& info) {
2693+
Mutex::ScopedLock lock(environ_mutex);
26842694
int32_t rc = -1; // Not found unless proven otherwise.
26852695
if (property->IsString()) {
26862696
#ifdef __POSIX__
@@ -2710,6 +2720,7 @@ static void EnvQuery(Local<Name> property,
27102720

27112721
static void EnvDeleter(Local<Name> property,
27122722
const PropertyCallbackInfo<Boolean>& info) {
2723+
Mutex::ScopedLock lock(environ_mutex);
27132724
if (property->IsString()) {
27142725
#ifdef __POSIX__
27152726
node::Utf8Value key(info.GetIsolate(), property);
@@ -2735,6 +2746,7 @@ static void EnvEnumerator(const PropertyCallbackInfo<Array>& info) {
27352746
Local<Value> argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
27362747
size_t idx = 0;
27372748

2749+
Mutex::ScopedLock lock(environ_mutex);
27382750
#ifdef __POSIX__
27392751
int size = 0;
27402752
while (environ[size])
@@ -2850,6 +2862,7 @@ static Local<Object> GetFeatures(Environment* env) {
28502862

28512863
static void DebugPortGetter(Local<Name> property,
28522864
const PropertyCallbackInfo<Value>& info) {
2865+
Mutex::ScopedLock lock(process_mutex);
28532866
int port = debug_options.port();
28542867
#if HAVE_INSPECTOR
28552868
if (port == 0) {
@@ -2865,6 +2878,7 @@ static void DebugPortGetter(Local<Name> property,
28652878
static void DebugPortSetter(Local<Name> property,
28662879
Local<Value> value,
28672880
const PropertyCallbackInfo<void>& info) {
2881+
Mutex::ScopedLock lock(process_mutex);
28682882
debug_options.set_port(value->Int32Value());
28692883
}
28702884

src/node_crypto.cc

+3
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,9 @@ void SecureContext::SetCert(const FunctionCallbackInfo<Value>& args) {
721721

722722
static X509_STORE* NewRootCertStore() {
723723
static std::vector<X509*> root_certs_vector;
724+
static Mutex root_certs_vector_mutex;
725+
Mutex::ScopedLock lock(root_certs_vector_mutex);
726+
724727
if (root_certs_vector.empty()) {
725728
for (size_t i = 0; i < arraysize(root_certs); i++) {
726729
BIO* bp = NodeBIO::NewFixed(root_certs[i], strlen(root_certs[i]));

src/node_internals.h

+1
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)