summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoyee Cheung <joyeec9h3@gmail.com>2018-12-19 09:53:12 +0800
committerJoyee Cheung <joyeec9h3@gmail.com>2018-12-21 16:33:09 +0800
commit75d0a9335f2f9bab72cdcbe9297d5617133a1d9c (patch)
treea6ad676cc33bead265fb78cbeaef13accf61f7cc /src
parent4884ca6428c0069468beea0826d228e167ad9cea (diff)
downloadandroid-node-v8-75d0a9335f2f9bab72cdcbe9297d5617133a1d9c.tar.gz
android-node-v8-75d0a9335f2f9bab72cdcbe9297d5617133a1d9c.tar.bz2
android-node-v8-75d0a9335f2f9bab72cdcbe9297d5617133a1d9c.zip
src: move more process methods initialization in bootstrap/node.js
Instead of: - Writing methods onto the process directly in C++ during `SetupProcessObject()` and overwrite with argument checks later - Or, wrapping and writing them in `internal/process/*.js` Do: - Move the C++ implementations in node_process.cc and mark them static wherever possible - Expose the C++ methods through a new `internalBinding('process_methods')` - Wrap the methods in `internal/process/*.js` in a side-effect-free manner and return them back to `internal/bootstrap/node.js` - Centralize the write to the process object based on conditions in `bootstrap/node.js` So it's easier to see what methods are attached to the process object during bootstrap under what condition and in what order. The eventual goal is to figure out the dependency of process methods and the write/read access to the process object during bootstrap, group these access properly and remove the process properties that should not be exposed to users this way. Also correct the NODE_PERFORMANCE_MILESTONE_BOOTSTRAP_COMPLETE milestone which should be marked before code execution. Refs: https://github.com/nodejs/node/issues/24961 PR-URL: https://github.com/nodejs/node/pull/25127 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/bootstrapper.cc14
-rw-r--r--src/node.cc155
-rw-r--r--src/node_binding.cc1
-rw-r--r--src/node_internals.h15
-rw-r--r--src/node_process.cc187
5 files changed, 174 insertions, 198 deletions
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 0a1cfed210..60c05a58a6 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -139,20 +139,6 @@ void SetupBootstrapObject(Environment* env,
BOOTSTRAP_METHOD(_setupTraceCategoryState, SetupTraceCategoryState);
BOOTSTRAP_METHOD(_setupNextTick, SetupNextTick);
BOOTSTRAP_METHOD(_setupPromises, SetupPromises);
- BOOTSTRAP_METHOD(_chdir, Chdir);
- BOOTSTRAP_METHOD(_cpuUsage, CPUUsage);
- BOOTSTRAP_METHOD(_hrtime, Hrtime);
- BOOTSTRAP_METHOD(_hrtimeBigInt, HrtimeBigInt);
- BOOTSTRAP_METHOD(_memoryUsage, MemoryUsage);
- BOOTSTRAP_METHOD(_rawDebug, RawDebug);
- BOOTSTRAP_METHOD(_umask, Umask);
-
- Local<String> should_abort_on_uncaught_toggle =
- FIXED_ONE_BYTE_STRING(env->isolate(), "_shouldAbortOnUncaughtToggle");
- CHECK(bootstrapper->Set(env->context(),
- should_abort_on_uncaught_toggle,
- env->should_abort_on_uncaught_toggle().GetJSArray())
- .FromJust());
}
#undef BOOTSTRAP_METHOD
diff --git a/src/node.cc b/src/node.cc
index 077d9c4996..9bd2ac9ff6 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -95,8 +95,6 @@
#if defined(_MSC_VER)
#include <direct.h>
#include <io.h>
-#define umask _umask
-typedef int mode_t;
#else
#include <pthread.h>
#include <sys/resource.h> // getrlimit, setrlimit
@@ -689,8 +687,7 @@ static void WaitForInspectorDisconnect(Environment* env) {
#endif
}
-
-static void Exit(const FunctionCallbackInfo<Value>& args) {
+void Exit(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
WaitForInspectorDisconnect(env);
v8_platform.StopTracingAgent();
@@ -1114,29 +1111,6 @@ void SetupProcessObject(Environment* env,
DebugPortGetter,
env->is_main_thread() ? DebugPortSetter : nullptr,
env->as_external()).FromJust());
-
- // define various internal methods
- if (env->is_main_thread()) {
- env->SetMethod(process, "_debugProcess", DebugProcess);
- env->SetMethod(process, "_debugEnd", DebugEnd);
- env->SetMethod(process,
- "_startProfilerIdleNotifier",
- StartProfilerIdleNotifier);
- env->SetMethod(process,
- "_stopProfilerIdleNotifier",
- StopProfilerIdleNotifier);
- env->SetMethod(process, "abort", Abort);
- env->SetMethod(process, "chdir", Chdir);
- env->SetMethod(process, "umask", Umask);
- }
- env->SetMethod(process, "_getActiveRequests", GetActiveRequests);
- env->SetMethod(process, "_getActiveHandles", GetActiveHandles);
- env->SetMethod(process, "_kill", Kill);
-
- env->SetMethodNoSideEffect(process, "cwd", Cwd);
- env->SetMethod(process, "dlopen", binding::DLOpen);
- env->SetMethod(process, "reallyExit", Exit);
- env->SetMethodNoSideEffect(process, "uptime", Uptime);
}
@@ -1278,135 +1252,8 @@ void RegisterSignalHandler(int signal,
CHECK_EQ(sigaction(signal, &sa, nullptr), 0);
}
-
-void DebugProcess(const FunctionCallbackInfo<Value>& args) {
- Environment* env = Environment::GetCurrent(args);
-
- if (args.Length() != 1) {
- return env->ThrowError("Invalid number of arguments.");
- }
-
- CHECK(args[0]->IsNumber());
- pid_t pid = args[0].As<Integer>()->Value();
- int r = kill(pid, SIGUSR1);
-
- if (r != 0) {
- return env->ThrowErrnoException(errno, "kill");
- }
-}
#endif // __POSIX__
-
-#ifdef _WIN32
-static int GetDebugSignalHandlerMappingName(DWORD pid, wchar_t* buf,
- size_t buf_len) {
- return _snwprintf(buf, buf_len, L"node-debug-handler-%u", pid);
-}
-
-
-static void DebugProcess(const FunctionCallbackInfo<Value>& args) {
- Environment* env = Environment::GetCurrent(args);
- Isolate* isolate = args.GetIsolate();
-
- if (args.Length() != 1) {
- env->ThrowError("Invalid number of arguments.");
- return;
- }
-
- HANDLE process = nullptr;
- HANDLE thread = nullptr;
- HANDLE mapping = nullptr;
- wchar_t mapping_name[32];
- LPTHREAD_START_ROUTINE* handler = nullptr;
- DWORD pid = 0;
-
- OnScopeLeave cleanup([&]() {
- if (process != nullptr)
- CloseHandle(process);
- if (thread != nullptr)
- CloseHandle(thread);
- if (handler != nullptr)
- UnmapViewOfFile(handler);
- if (mapping != nullptr)
- CloseHandle(mapping);
- });
-
- CHECK(args[0]->IsNumber());
- pid = args[0].As<Integer>()->Value();
-
- process = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
- PROCESS_VM_OPERATION | PROCESS_VM_WRITE |
- PROCESS_VM_READ,
- FALSE,
- pid);
- if (process == nullptr) {
- isolate->ThrowException(
- WinapiErrnoException(isolate, GetLastError(), "OpenProcess"));
- return;
- }
-
- if (GetDebugSignalHandlerMappingName(pid,
- mapping_name,
- arraysize(mapping_name)) < 0) {
- env->ThrowErrnoException(errno, "sprintf");
- return;
- }
-
- mapping = OpenFileMappingW(FILE_MAP_READ, FALSE, mapping_name);
- if (mapping == nullptr) {
- isolate->ThrowException(WinapiErrnoException(isolate,
- GetLastError(),
- "OpenFileMappingW"));
- return;
- }
-
- handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
- MapViewOfFile(mapping,
- FILE_MAP_READ,
- 0,
- 0,
- sizeof *handler));
- if (handler == nullptr || *handler == nullptr) {
- isolate->ThrowException(
- WinapiErrnoException(isolate, GetLastError(), "MapViewOfFile"));
- return;
- }
-
- thread = CreateRemoteThread(process,
- nullptr,
- 0,
- *handler,
- nullptr,
- 0,
- nullptr);
- if (thread == nullptr) {
- isolate->ThrowException(WinapiErrnoException(isolate,
- GetLastError(),
- "CreateRemoteThread"));
- return;
- }
-
- // Wait for the thread to terminate
- if (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0) {
- isolate->ThrowException(WinapiErrnoException(isolate,
- GetLastError(),
- "WaitForSingleObject"));
- return;
- }
-}
-#endif // _WIN32
-
-
-static void DebugEnd(const FunctionCallbackInfo<Value>& args) {
-#if HAVE_INSPECTOR
- Environment* env = Environment::GetCurrent(args);
- if (env->inspector_agent()->IsListening()) {
- env->inspector_agent()->Stop();
- }
-#endif
-}
-
-
inline void PlatformInit() {
#ifdef __POSIX__
#if HAVE_INSPECTOR
diff --git a/src/node_binding.cc b/src/node_binding.cc
index 0758741ffc..46ae5f6840 100644
--- a/src/node_binding.cc
+++ b/src/node_binding.cc
@@ -44,6 +44,7 @@
V(performance) \
V(pipe_wrap) \
V(process_wrap) \
+ V(process_methods) \
V(serdes) \
V(signal_wrap) \
V(spawn_sync) \
diff --git a/src/node_internals.h b/src/node_internals.h
index 03017fb4f5..99498a6218 100644
--- a/src/node_internals.h
+++ b/src/node_internals.h
@@ -119,6 +119,7 @@ void GetSockOrPeerName(const v8::FunctionCallbackInfo<v8::Value>& args) {
args.GetReturnValue().Set(err);
}
+void Exit(const v8::FunctionCallbackInfo<v8::Value>& args);
void SignalExit(int signo);
#ifdef __POSIX__
void RegisterSignalHandler(int signal,
@@ -698,21 +699,7 @@ static inline const char* errno_string(int errorno) {
extern double prog_start_time;
-void Abort(const v8::FunctionCallbackInfo<v8::Value>& args);
-void Chdir(const v8::FunctionCallbackInfo<v8::Value>& args);
-void CPUUsage(const v8::FunctionCallbackInfo<v8::Value>& args);
-void Cwd(const v8::FunctionCallbackInfo<v8::Value>& args);
-void GetActiveHandles(const v8::FunctionCallbackInfo<v8::Value>& args);
-void GetActiveRequests(const v8::FunctionCallbackInfo<v8::Value>& args);
-void Hrtime(const v8::FunctionCallbackInfo<v8::Value>& args);
-void HrtimeBigInt(const v8::FunctionCallbackInfo<v8::Value>& args);
-void Kill(const v8::FunctionCallbackInfo<v8::Value>& args);
-void MemoryUsage(const v8::FunctionCallbackInfo<v8::Value>& args);
void RawDebug(const v8::FunctionCallbackInfo<v8::Value>& args);
-void StartProfilerIdleNotifier(const v8::FunctionCallbackInfo<v8::Value>& args);
-void StopProfilerIdleNotifier(const v8::FunctionCallbackInfo<v8::Value>& args);
-void Umask(const v8::FunctionCallbackInfo<v8::Value>& args);
-void Uptime(const v8::FunctionCallbackInfo<v8::Value>& args);
void DebugPortGetter(v8::Local<v8::Name> property,
const v8::PropertyCallbackInfo<v8::Value>& info);
diff --git a/src/node_process.cc b/src/node_process.cc
index b9376953e2..477ac2adc8 100644
--- a/src/node_process.cc
+++ b/src/node_process.cc
@@ -8,6 +8,8 @@
#include "uv.h"
#include "v8.h"
+#include <vector>
+
#if HAVE_INSPECTOR
#include "inspector_io.h"
#endif
@@ -36,10 +38,12 @@ 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::NewStringType;
+using v8::Object;
using v8::PropertyCallbackInfo;
using v8::String;
using v8::Uint32;
@@ -61,11 +65,11 @@ Mutex environ_mutex;
#define CHDIR_BUFSIZE (PATH_MAX)
#endif
-void Abort(const FunctionCallbackInfo<Value>& args) {
+static void Abort(const FunctionCallbackInfo<Value>& args) {
Abort();
}
-void Chdir(const FunctionCallbackInfo<Value>& args) {
+static void Chdir(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
CHECK(env->is_main_thread());
@@ -88,7 +92,7 @@ void Chdir(const FunctionCallbackInfo<Value>& args) {
// which are uv_timeval_t structs (long tv_sec, long tv_usec).
// Returns those values as Float64 microseconds in the elements of the array
// passed to the function.
-void CPUUsage(const FunctionCallbackInfo<Value>& args) {
+static void CPUUsage(const FunctionCallbackInfo<Value>& args) {
uv_rusage_t rusage;
// Call libuv to get the values we'll return.
@@ -111,7 +115,7 @@ void CPUUsage(const FunctionCallbackInfo<Value>& args) {
fields[1] = MICROS_PER_SEC * rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec;
}
-void Cwd(const FunctionCallbackInfo<Value>& args) {
+static void Cwd(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
char buf[CHDIR_BUFSIZE];
size_t cwd_len = sizeof(buf);
@@ -138,7 +142,7 @@ void Cwd(const FunctionCallbackInfo<Value>& args) {
// broken into the upper/lower 32 bits to be converted back in JS,
// because there is no Uint64Array in JS.
// The third entry contains the remaining nanosecond part of the value.
-void Hrtime(const FunctionCallbackInfo<Value>& args) {
+static void Hrtime(const FunctionCallbackInfo<Value>& args) {
uint64_t t = uv_hrtime();
Local<ArrayBuffer> ab = args[0].As<Uint32Array>()->Buffer();
@@ -149,13 +153,13 @@ void Hrtime(const FunctionCallbackInfo<Value>& args) {
fields[2] = t % NANOS_PER_SEC;
}
-void HrtimeBigInt(const FunctionCallbackInfo<Value>& args) {
+static void HrtimeBigInt(const FunctionCallbackInfo<Value>& args) {
Local<ArrayBuffer> ab = args[0].As<BigUint64Array>()->Buffer();
uint64_t* fields = static_cast<uint64_t*>(ab->GetContents().Data());
fields[0] = uv_hrtime();
}
-void Kill(const FunctionCallbackInfo<Value>& args) {
+static void Kill(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
Local<Context> context = env->context();
@@ -170,8 +174,7 @@ void Kill(const FunctionCallbackInfo<Value>& args) {
args.GetReturnValue().Set(err);
}
-
-void MemoryUsage(const FunctionCallbackInfo<Value>& args) {
+static void MemoryUsage(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
size_t rss;
@@ -209,18 +212,17 @@ void RawDebug(const FunctionCallbackInfo<Value>& args) {
fflush(stderr);
}
-void StartProfilerIdleNotifier(const FunctionCallbackInfo<Value>& args) {
+static void StartProfilerIdleNotifier(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
env->StartProfilerIdleNotifier();
}
-
-void StopProfilerIdleNotifier(const FunctionCallbackInfo<Value>& args) {
+static void StopProfilerIdleNotifier(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
env->StopProfilerIdleNotifier();
}
-void Umask(const FunctionCallbackInfo<Value>& args) {
+static void Umask(const FunctionCallbackInfo<Value>& args) {
uint32_t old;
CHECK_EQ(args.Length(), 1);
@@ -237,7 +239,7 @@ void Umask(const FunctionCallbackInfo<Value>& args) {
args.GetReturnValue().Set(old);
}
-void Uptime(const FunctionCallbackInfo<Value>& args) {
+static void Uptime(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
double uptime;
@@ -255,7 +257,6 @@ void ProcessTitleGetter(Local<Name> property,
NewStringType::kNormal).ToLocalChecked());
}
-
void ProcessTitleSetter(Local<Name> property,
Local<Value> value,
const PropertyCallbackInfo<void>& info) {
@@ -270,7 +271,7 @@ void GetParentProcessId(Local<Name> property,
info.GetReturnValue().Set(uv_os_getppid());
}
-void GetActiveRequests(const FunctionCallbackInfo<Value>& args) {
+static void GetActiveRequests(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
std::vector<Local<Value>> request_v;
@@ -315,5 +316,159 @@ void DebugPortSetter(Local<Name> property,
env->inspector_host_port()->set_port(static_cast<int>(port));
}
+#ifdef __POSIX__
+static void DebugProcess(const FunctionCallbackInfo<Value>& args) {
+ Environment* env = Environment::GetCurrent(args);
+
+ if (args.Length() != 1) {
+ return env->ThrowError("Invalid number of arguments.");
+ }
+
+ CHECK(args[0]->IsNumber());
+ pid_t pid = args[0].As<Integer>()->Value();
+ int r = kill(pid, SIGUSR1);
+
+ if (r != 0) {
+ return env->ThrowErrnoException(errno, "kill");
+ }
+}
+#endif // __POSIX__
+
+#ifdef _WIN32
+static int GetDebugSignalHandlerMappingName(DWORD pid,
+ wchar_t* buf,
+ size_t buf_len) {
+ return _snwprintf(buf, buf_len, L"node-debug-handler-%u", pid);
+}
+
+static void DebugProcess(const FunctionCallbackInfo<Value>& args) {
+ Environment* env = Environment::GetCurrent(args);
+ Isolate* isolate = args.GetIsolate();
+
+ if (args.Length() != 1) {
+ env->ThrowError("Invalid number of arguments.");
+ return;
+ }
+
+ HANDLE process = nullptr;
+ HANDLE thread = nullptr;
+ HANDLE mapping = nullptr;
+ wchar_t mapping_name[32];
+ LPTHREAD_START_ROUTINE* handler = nullptr;
+ DWORD pid = 0;
+
+ OnScopeLeave cleanup([&]() {
+ if (process != nullptr) CloseHandle(process);
+ if (thread != nullptr) CloseHandle(thread);
+ if (handler != nullptr) UnmapViewOfFile(handler);
+ if (mapping != nullptr) CloseHandle(mapping);
+ });
+
+ CHECK(args[0]->IsNumber());
+ pid = args[0].As<Integer>()->Value();
+
+ process =
+ OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
+ PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ,
+ FALSE,
+ pid);
+ if (process == nullptr) {
+ isolate->ThrowException(
+ WinapiErrnoException(isolate, GetLastError(), "OpenProcess"));
+ return;
+ }
+
+ if (GetDebugSignalHandlerMappingName(
+ pid, mapping_name, arraysize(mapping_name)) < 0) {
+ env->ThrowErrnoException(errno, "sprintf");
+ return;
+ }
+
+ mapping = OpenFileMappingW(FILE_MAP_READ, FALSE, mapping_name);
+ if (mapping == nullptr) {
+ isolate->ThrowException(
+ WinapiErrnoException(isolate, GetLastError(), "OpenFileMappingW"));
+ return;
+ }
+
+ handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
+ MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, sizeof *handler));
+ if (handler == nullptr || *handler == nullptr) {
+ isolate->ThrowException(
+ WinapiErrnoException(isolate, GetLastError(), "MapViewOfFile"));
+ return;
+ }
+
+ thread =
+ CreateRemoteThread(process, nullptr, 0, *handler, nullptr, 0, nullptr);
+ if (thread == nullptr) {
+ isolate->ThrowException(
+ WinapiErrnoException(isolate, GetLastError(), "CreateRemoteThread"));
+ return;
+ }
+
+ // Wait for the thread to terminate
+ if (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0) {
+ isolate->ThrowException(
+ WinapiErrnoException(isolate, GetLastError(), "WaitForSingleObject"));
+ return;
+ }
+}
+#endif // _WIN32
+
+static void DebugEnd(const FunctionCallbackInfo<Value>& args) {
+#if HAVE_INSPECTOR
+ Environment* env = Environment::GetCurrent(args);
+ if (env->inspector_agent()->IsListening()) {
+ env->inspector_agent()->Stop();
+ }
+#endif
+}
+
+static void InitializeProcessMethods(Local<Object> target,
+ Local<Value> unused,
+ Local<Context> context,
+ void* priv) {
+ Environment* env = Environment::GetCurrent(context);
+
+ // define various internal methods
+ if (env->is_main_thread()) {
+ env->SetMethod(target, "_debugProcess", DebugProcess);
+ env->SetMethod(target, "_debugEnd", DebugEnd);
+ env->SetMethod(
+ target, "_startProfilerIdleNotifier", StartProfilerIdleNotifier);
+ env->SetMethod(
+ target, "_stopProfilerIdleNotifier", StopProfilerIdleNotifier);
+ env->SetMethod(target, "abort", Abort);
+ env->SetMethod(target, "chdir", Chdir);
+ env->SetMethod(target, "umask", Umask);
+ }
+
+ env->SetMethod(target, "_rawDebug", RawDebug);
+ env->SetMethod(target, "memoryUsage", MemoryUsage);
+ env->SetMethod(target, "cpuUsage", CPUUsage);
+ env->SetMethod(target, "hrtime", Hrtime);
+ env->SetMethod(target, "hrtimeBigInt", HrtimeBigInt);
+
+ env->SetMethod(target, "_getActiveRequests", GetActiveRequests);
+ env->SetMethod(target, "_getActiveHandles", GetActiveHandles);
+ env->SetMethod(target, "_kill", Kill);
+
+ env->SetMethodNoSideEffect(target, "cwd", Cwd);
+ env->SetMethod(target, "dlopen", binding::DLOpen);
+ env->SetMethod(target, "reallyExit", Exit);
+ env->SetMethodNoSideEffect(target, "uptime", Uptime);
+
+ Local<String> should_abort_on_uncaught_toggle =
+ FIXED_ONE_BYTE_STRING(env->isolate(), "shouldAbortOnUncaughtToggle");
+ CHECK(target
+ ->Set(env->context(),
+ should_abort_on_uncaught_toggle,
+ env->should_abort_on_uncaught_toggle().GetJSArray())
+ .FromJust());
+}
} // namespace node
+
+NODE_MODULE_CONTEXT_AWARE_INTERNAL(process_methods,
+ node::InitializeProcessMethods)