Skip to content

Commit

Permalink
src: protect global state with mutexes
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
addaleax authored and targos committed May 12, 2018
1 parent 2df99ac commit a89cc28
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 4 deletions.
22 changes: 18 additions & 4 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@ using v8::Value;

using AsyncHooks = Environment::AsyncHooks;

static Mutex process_mutex;
static Mutex environ_mutex;

static bool print_eval = false;
static bool force_repl = false;
static bool syntax_check_only = false;
Expand Down Expand Up @@ -698,9 +701,12 @@ bool SafeGetenv(const char* key, std::string* text) {
goto fail;
#endif

if (const char* value = getenv(key)) {
*text = value;
return true;
{
Mutex::ScopedLock lock(environ_mutex);
if (const char* value = getenv(key)) {
*text = value;
return true;
}
}

fail:
Expand Down Expand Up @@ -1358,6 +1364,7 @@ void AppendExceptionLine(Environment* env,
if (!can_set_arrow || (mode == FATAL_ERROR && !err_obj->IsNativeError())) {
if (env->printed_error())
return;
Mutex::ScopedLock lock(process_mutex);
env->set_printed_error(true);

uv_tty_reset_mode();
Expand Down Expand Up @@ -2624,7 +2631,6 @@ static void ProcessTitleSetter(Local<Name> property,
Local<Value> value,
const PropertyCallbackInfo<void>& info) {
node::Utf8Value title(info.GetIsolate(), value);
// TODO(piscisaureus): protect with a lock
uv_set_process_title(*title);
}

Expand All @@ -2635,6 +2641,7 @@ static void EnvGetter(Local<Name> property,
if (property->IsSymbol()) {
return info.GetReturnValue().SetUndefined();
}
Mutex::ScopedLock lock(environ_mutex);
#ifdef __POSIX__
node::Utf8Value key(isolate, property);
const char* val = getenv(*key);
Expand Down Expand Up @@ -2675,6 +2682,8 @@ static void EnvSetter(Local<Name> property,
"DEP0104").IsNothing())
return;
}

Mutex::ScopedLock lock(environ_mutex);
#ifdef __POSIX__
node::Utf8Value key(info.GetIsolate(), property);
node::Utf8Value val(info.GetIsolate(), value);
Expand All @@ -2695,6 +2704,7 @@ static void EnvSetter(Local<Name> property,

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

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

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

static void DebugPortGetter(Local<Name> property,
const PropertyCallbackInfo<Value>& info) {
Mutex::ScopedLock lock(process_mutex);
int port = debug_options.port();
#if HAVE_INSPECTOR
if (port == 0) {
Expand All @@ -2879,6 +2892,7 @@ static void DebugPortGetter(Local<Name> property,
static void DebugPortSetter(Local<Name> property,
Local<Value> value,
const PropertyCallbackInfo<void>& info) {
Mutex::ScopedLock lock(process_mutex);
debug_options.set_port(value->Int32Value());
}

Expand Down
3 changes: 3 additions & 0 deletions src/node_crypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,9 @@ void SecureContext::SetCert(const FunctionCallbackInfo<Value>& args) {

static X509_STORE* NewRootCertStore() {
static std::vector<X509*> root_certs_vector;
static Mutex root_certs_vector_mutex;
Mutex::ScopedLock lock(root_certs_vector_mutex);

if (root_certs_vector.empty()) {
for (size_t i = 0; i < arraysize(root_certs); i++) {
BIO* bp = NodeBIO::NewFixed(root_certs[i], strlen(root_certs[i]));
Expand Down
1 change: 1 addition & 0 deletions src/node_internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

#include "node.h"
#include "node_mutex.h"
#include "node_persistent.h"
#include "util-inl.h"
#include "env-inl.h"
Expand Down

0 comments on commit a89cc28

Please sign in to comment.