From 5f392a1d2d07b70205718928c2d2553a5615c41c Mon Sep 17 00:00:00 2001 From: James M Snell Date: Mon, 20 Aug 2018 14:07:10 -0700 Subject: [PATCH] src: move more to node_process.cc from node.cc PR-URL: https://github.com/nodejs/node/pull/22422 Reviewed-By: Gus Caplan Reviewed-By: Anna Henningsen Reviewed-By: Refael Ackermann Reviewed-By: Colin Ihrig --- src/node.cc | 225 ------------------------------------------ src/node_internals.h | 23 +++++ src/node_process.cc | 227 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 250 insertions(+), 225 deletions(-) diff --git a/src/node.cc b/src/node.cc index 97467d1649df16..baea8293c35528 100644 --- a/src/node.cc +++ b/src/node.cc @@ -114,13 +114,6 @@ typedef int mode_t; #include #endif -#ifdef __APPLE__ -#include -#define environ (*_NSGetEnviron()) -#elif !defined(_MSC_VER) -extern char **environ; -#endif - // This is used to load built-in modules. Instead of using // __attribute__((constructor)), we call the _register_ // function for each built-in modules explicitly in @@ -168,9 +161,6 @@ using v8::Undefined; using v8::V8; using v8::Value; -static Mutex process_mutex; -static Mutex environ_mutex; - static bool v8_is_profiling = false; static bool node_is_initialized = false; static uv_once_t init_modpending_once = UV_ONCE_INIT; @@ -1694,221 +1684,6 @@ static void GetLinkedBinding(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(effective_exports); } -static void ProcessTitleGetter(Local property, - const PropertyCallbackInfo& info) { - char buffer[512]; - uv_get_process_title(buffer, sizeof(buffer)); - info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), buffer, - v8::NewStringType::kNormal).ToLocalChecked()); -} - - -static void ProcessTitleSetter(Local property, - Local value, - const PropertyCallbackInfo& info) { - node::Utf8Value title(info.GetIsolate(), value); - TRACE_EVENT_METADATA1("__metadata", "process_name", "name", - TRACE_STR_COPY(*title)); - uv_set_process_title(*title); -} - - -static void EnvGetter(Local property, - const PropertyCallbackInfo& info) { - Isolate* isolate = info.GetIsolate(); - if (property->IsSymbol()) { - return info.GetReturnValue().SetUndefined(); - } - Mutex::ScopedLock lock(environ_mutex); -#ifdef __POSIX__ - node::Utf8Value key(isolate, property); - const char* val = getenv(*key); - if (val) { - return info.GetReturnValue().Set(String::NewFromUtf8(isolate, val, - v8::NewStringType::kNormal).ToLocalChecked()); - } -#else // _WIN32 - node::TwoByteValue key(isolate, property); - WCHAR buffer[32767]; // The maximum size allowed for environment variables. - SetLastError(ERROR_SUCCESS); - DWORD result = GetEnvironmentVariableW(reinterpret_cast(*key), - buffer, - arraysize(buffer)); - // If result >= sizeof buffer the buffer was too small. That should never - // happen. If result == 0 and result != ERROR_SUCCESS the variable was not - // found. - if ((result > 0 || GetLastError() == ERROR_SUCCESS) && - result < arraysize(buffer)) { - const uint16_t* two_byte_buffer = reinterpret_cast(buffer); - Local rc = String::NewFromTwoByte(isolate, two_byte_buffer); - return info.GetReturnValue().Set(rc); - } -#endif -} - - -static void EnvSetter(Local property, - Local value, - const PropertyCallbackInfo& info) { - Environment* env = Environment::GetCurrent(info); - if (env->options()->pending_deprecation && env->EmitProcessEnvWarning() && - !value->IsString() && !value->IsNumber() && !value->IsBoolean()) { - if (ProcessEmitDeprecationWarning( - env, - "Assigning any value other than a string, number, or boolean to a " - "process.env property is deprecated. Please make sure to convert the " - "value to a string before setting process.env with it.", - "DEP0104").IsNothing()) - return; - } - - Mutex::ScopedLock lock(environ_mutex); -#ifdef __POSIX__ - node::Utf8Value key(info.GetIsolate(), property); - node::Utf8Value val(info.GetIsolate(), value); - setenv(*key, *val, 1); -#else // _WIN32 - node::TwoByteValue key(info.GetIsolate(), property); - node::TwoByteValue val(info.GetIsolate(), value); - WCHAR* key_ptr = reinterpret_cast(*key); - // Environment variables that start with '=' are read-only. - if (key_ptr[0] != L'=') { - SetEnvironmentVariableW(key_ptr, reinterpret_cast(*val)); - } -#endif - // Whether it worked or not, always return value. - info.GetReturnValue().Set(value); -} - - -static void EnvQuery(Local property, - const PropertyCallbackInfo& info) { - Mutex::ScopedLock lock(environ_mutex); - int32_t rc = -1; // Not found unless proven otherwise. - if (property->IsString()) { -#ifdef __POSIX__ - node::Utf8Value key(info.GetIsolate(), property); - if (getenv(*key)) - rc = 0; -#else // _WIN32 - node::TwoByteValue key(info.GetIsolate(), property); - WCHAR* key_ptr = reinterpret_cast(*key); - SetLastError(ERROR_SUCCESS); - if (GetEnvironmentVariableW(key_ptr, nullptr, 0) > 0 || - GetLastError() == ERROR_SUCCESS) { - rc = 0; - if (key_ptr[0] == L'=') { - // Environment variables that start with '=' are hidden and read-only. - rc = static_cast(v8::ReadOnly) | - static_cast(v8::DontDelete) | - static_cast(v8::DontEnum); - } - } -#endif - } - if (rc != -1) - info.GetReturnValue().Set(rc); -} - - -static void EnvDeleter(Local property, - const PropertyCallbackInfo& info) { - Mutex::ScopedLock lock(environ_mutex); - if (property->IsString()) { -#ifdef __POSIX__ - node::Utf8Value key(info.GetIsolate(), property); - unsetenv(*key); -#else - node::TwoByteValue key(info.GetIsolate(), property); - WCHAR* key_ptr = reinterpret_cast(*key); - SetEnvironmentVariableW(key_ptr, nullptr); -#endif - } - - // process.env never has non-configurable properties, so always - // return true like the tc39 delete operator. - info.GetReturnValue().Set(true); -} - - -static void EnvEnumerator(const PropertyCallbackInfo& info) { - Environment* env = Environment::GetCurrent(info); - Isolate* isolate = env->isolate(); - Local ctx = env->context(); - Local fn = env->push_values_to_array_function(); - Local argv[NODE_PUSH_VAL_TO_ARRAY_MAX]; - size_t idx = 0; - - Mutex::ScopedLock lock(environ_mutex); -#ifdef __POSIX__ - int size = 0; - while (environ[size]) - size++; - - Local envarr = Array::New(isolate); - - for (int i = 0; i < size; ++i) { - const char* var = environ[i]; - const char* s = strchr(var, '='); - const int length = s ? s - var : strlen(var); - argv[idx] = String::NewFromUtf8(isolate, - var, - v8::NewStringType::kNormal, - length).ToLocalChecked(); - if (++idx >= arraysize(argv)) { - fn->Call(ctx, envarr, idx, argv).ToLocalChecked(); - idx = 0; - } - } - if (idx > 0) { - fn->Call(ctx, envarr, idx, argv).ToLocalChecked(); - } -#else // _WIN32 - WCHAR* environment = GetEnvironmentStringsW(); - if (environment == nullptr) - return; // This should not happen. - Local envarr = Array::New(isolate); - WCHAR* p = environment; - while (*p) { - WCHAR* s; - if (*p == L'=') { - // If the key starts with '=' it is a hidden environment variable. - p += wcslen(p) + 1; - continue; - } else { - s = wcschr(p, L'='); - } - if (!s) { - s = p + wcslen(p); - } - const uint16_t* two_byte_buffer = reinterpret_cast(p); - const size_t two_byte_buffer_len = s - p; - argv[idx] = String::NewFromTwoByte(isolate, - two_byte_buffer, - String::kNormalString, - two_byte_buffer_len); - if (++idx >= arraysize(argv)) { - fn->Call(ctx, envarr, idx, argv).ToLocalChecked(); - idx = 0; - } - p = s + wcslen(s) + 1; - } - if (idx > 0) { - fn->Call(ctx, envarr, idx, argv).ToLocalChecked(); - } - FreeEnvironmentStringsW(environment); -#endif - - info.GetReturnValue().Set(envarr); -} - - -static void GetParentProcessId(Local property, - const PropertyCallbackInfo& info) { - info.GetReturnValue().Set(Integer::New(info.GetIsolate(), uv_os_getppid())); -} - - static Local GetFeatures(Environment* env) { EscapableHandleScope scope(env->isolate()); diff --git a/src/node_internals.h b/src/node_internals.h index e988fe189f3230..c3150edda45fb6 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -170,6 +170,9 @@ struct sockaddr; namespace node { +extern Mutex process_mutex; +extern Mutex environ_mutex; + // Tells whether it is safe to call v8::Isolate::GetCurrent(). extern bool v8_initialized; @@ -888,6 +891,26 @@ void StopProfilerIdleNotifier(const v8::FunctionCallbackInfo& args); void Umask(const v8::FunctionCallbackInfo& args); void Uptime(const v8::FunctionCallbackInfo& args); +void EnvDeleter(v8::Local property, + const v8::PropertyCallbackInfo& info); +void EnvGetter(v8::Local property, + const v8::PropertyCallbackInfo& info); +void EnvSetter(v8::Local property, + v8::Local value, + const v8::PropertyCallbackInfo& info); +void EnvQuery(v8::Local property, + const v8::PropertyCallbackInfo& info); +void EnvEnumerator(const v8::PropertyCallbackInfo& info); + +void GetParentProcessId(v8::Local property, + const v8::PropertyCallbackInfo& info); + +void ProcessTitleGetter(v8::Local property, + const v8::PropertyCallbackInfo& info); +void ProcessTitleSetter(v8::Local property, + v8::Local value, + const v8::PropertyCallbackInfo& info); + #if defined(__POSIX__) && !defined(__ANDROID__) && !defined(__CloudABI__) void SetGid(const v8::FunctionCallbackInfo& args); void SetEGid(const v8::FunctionCallbackInfo& args); diff --git a/src/node_process.cc b/src/node_process.cc index 887c9fb4768f30..bb79c6cbf37af5 100644 --- a/src/node_process.cc +++ b/src/node_process.cc @@ -25,23 +25,38 @@ typedef int mode_t; #include // getgrnam() #endif +#ifdef __APPLE__ +#include +#define environ (*_NSGetEnviron()) +#elif !defined(_MSC_VER) +extern char **environ; +#endif + namespace node { using v8::Array; using v8::ArrayBuffer; using v8::BigUint64Array; +using v8::Boolean; +using v8::Context; using v8::Float64Array; +using v8::Function; using v8::FunctionCallbackInfo; using v8::HeapStatistics; using v8::Integer; using v8::Isolate; using v8::Local; +using v8::Name; using v8::Number; +using v8::PropertyCallbackInfo; using v8::String; using v8::Uint32; using v8::Uint32Array; using v8::Value; +Mutex process_mutex; +Mutex environ_mutex; + // Microseconds in a second, as a float, used in CPUUsage() below #define MICROS_PER_SEC 1e6 // used in Hrtime() below @@ -548,4 +563,216 @@ void InitGroups(const FunctionCallbackInfo& args) { #endif // __POSIX__ && !defined(__ANDROID__) && !defined(__CloudABI__) +void ProcessTitleGetter(Local property, + const PropertyCallbackInfo& info) { + char buffer[512]; + uv_get_process_title(buffer, sizeof(buffer)); + info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), buffer, + v8::NewStringType::kNormal).ToLocalChecked()); +} + + +void ProcessTitleSetter(Local property, + Local value, + const PropertyCallbackInfo& info) { + node::Utf8Value title(info.GetIsolate(), value); + TRACE_EVENT_METADATA1("__metadata", "process_name", "name", + TRACE_STR_COPY(*title)); + uv_set_process_title(*title); +} + +void EnvGetter(Local property, + const PropertyCallbackInfo& info) { + Isolate* isolate = info.GetIsolate(); + if (property->IsSymbol()) { + return info.GetReturnValue().SetUndefined(); + } + Mutex::ScopedLock lock(environ_mutex); +#ifdef __POSIX__ + node::Utf8Value key(isolate, property); + const char* val = getenv(*key); + if (val) { + return info.GetReturnValue().Set(String::NewFromUtf8(isolate, val, + v8::NewStringType::kNormal).ToLocalChecked()); + } +#else // _WIN32 + node::TwoByteValue key(isolate, property); + WCHAR buffer[32767]; // The maximum size allowed for environment variables. + SetLastError(ERROR_SUCCESS); + DWORD result = GetEnvironmentVariableW(reinterpret_cast(*key), + buffer, + arraysize(buffer)); + // If result >= sizeof buffer the buffer was too small. That should never + // happen. If result == 0 and result != ERROR_SUCCESS the variable was not + // found. + if ((result > 0 || GetLastError() == ERROR_SUCCESS) && + result < arraysize(buffer)) { + const uint16_t* two_byte_buffer = reinterpret_cast(buffer); + Local rc = String::NewFromTwoByte(isolate, two_byte_buffer); + return info.GetReturnValue().Set(rc); + } +#endif +} + + +void EnvSetter(Local property, + Local value, + const PropertyCallbackInfo& info) { + Environment* env = Environment::GetCurrent(info); + if (env->options()->pending_deprecation && env->EmitProcessEnvWarning() && + !value->IsString() && !value->IsNumber() && !value->IsBoolean()) { + if (ProcessEmitDeprecationWarning( + env, + "Assigning any value other than a string, number, or boolean to a " + "process.env property is deprecated. Please make sure to convert the " + "value to a string before setting process.env with it.", + "DEP0104").IsNothing()) + return; + } + + Mutex::ScopedLock lock(environ_mutex); +#ifdef __POSIX__ + node::Utf8Value key(info.GetIsolate(), property); + node::Utf8Value val(info.GetIsolate(), value); + setenv(*key, *val, 1); +#else // _WIN32 + node::TwoByteValue key(info.GetIsolate(), property); + node::TwoByteValue val(info.GetIsolate(), value); + WCHAR* key_ptr = reinterpret_cast(*key); + // Environment variables that start with '=' are read-only. + if (key_ptr[0] != L'=') { + SetEnvironmentVariableW(key_ptr, reinterpret_cast(*val)); + } +#endif + // Whether it worked or not, always return value. + info.GetReturnValue().Set(value); +} + + +void EnvQuery(Local property, const PropertyCallbackInfo& info) { + Mutex::ScopedLock lock(environ_mutex); + int32_t rc = -1; // Not found unless proven otherwise. + if (property->IsString()) { +#ifdef __POSIX__ + node::Utf8Value key(info.GetIsolate(), property); + if (getenv(*key)) + rc = 0; +#else // _WIN32 + node::TwoByteValue key(info.GetIsolate(), property); + WCHAR* key_ptr = reinterpret_cast(*key); + SetLastError(ERROR_SUCCESS); + if (GetEnvironmentVariableW(key_ptr, nullptr, 0) > 0 || + GetLastError() == ERROR_SUCCESS) { + rc = 0; + if (key_ptr[0] == L'=') { + // Environment variables that start with '=' are hidden and read-only. + rc = static_cast(v8::ReadOnly) | + static_cast(v8::DontDelete) | + static_cast(v8::DontEnum); + } + } +#endif + } + if (rc != -1) + info.GetReturnValue().Set(rc); +} + + +void EnvDeleter(Local property, + const PropertyCallbackInfo& info) { + Mutex::ScopedLock lock(environ_mutex); + if (property->IsString()) { +#ifdef __POSIX__ + node::Utf8Value key(info.GetIsolate(), property); + unsetenv(*key); +#else + node::TwoByteValue key(info.GetIsolate(), property); + WCHAR* key_ptr = reinterpret_cast(*key); + SetEnvironmentVariableW(key_ptr, nullptr); +#endif + } + + // process.env never has non-configurable properties, so always + // return true like the tc39 delete operator. + info.GetReturnValue().Set(true); +} + + +void EnvEnumerator(const PropertyCallbackInfo& info) { + Environment* env = Environment::GetCurrent(info); + Isolate* isolate = env->isolate(); + Local ctx = env->context(); + Local fn = env->push_values_to_array_function(); + Local argv[NODE_PUSH_VAL_TO_ARRAY_MAX]; + size_t idx = 0; + + Mutex::ScopedLock lock(environ_mutex); +#ifdef __POSIX__ + int size = 0; + while (environ[size]) + size++; + + Local envarr = Array::New(isolate); + + for (int i = 0; i < size; ++i) { + const char* var = environ[i]; + const char* s = strchr(var, '='); + const int length = s ? s - var : strlen(var); + argv[idx] = String::NewFromUtf8(isolate, + var, + v8::NewStringType::kNormal, + length).ToLocalChecked(); + if (++idx >= arraysize(argv)) { + fn->Call(ctx, envarr, idx, argv).ToLocalChecked(); + idx = 0; + } + } + if (idx > 0) { + fn->Call(ctx, envarr, idx, argv).ToLocalChecked(); + } +#else // _WIN32 + WCHAR* environment = GetEnvironmentStringsW(); + if (environment == nullptr) + return; // This should not happen. + Local envarr = Array::New(isolate); + WCHAR* p = environment; + while (*p) { + WCHAR* s; + if (*p == L'=') { + // If the key starts with '=' it is a hidden environment variable. + p += wcslen(p) + 1; + continue; + } else { + s = wcschr(p, L'='); + } + if (!s) { + s = p + wcslen(p); + } + const uint16_t* two_byte_buffer = reinterpret_cast(p); + const size_t two_byte_buffer_len = s - p; + argv[idx] = String::NewFromTwoByte(isolate, + two_byte_buffer, + String::kNormalString, + two_byte_buffer_len); + if (++idx >= arraysize(argv)) { + fn->Call(ctx, envarr, idx, argv).ToLocalChecked(); + idx = 0; + } + p = s + wcslen(s) + 1; + } + if (idx > 0) { + fn->Call(ctx, envarr, idx, argv).ToLocalChecked(); + } + FreeEnvironmentStringsW(environment); +#endif + + info.GetReturnValue().Set(envarr); +} + +void GetParentProcessId(Local property, + const PropertyCallbackInfo& info) { + info.GetReturnValue().Set(Integer::New(info.GetIsolate(), uv_os_getppid())); +} + + } // namespace node