[fuchsia] Fuchsia support to Node
diff --git a/src/api/environment.cc b/src/api/environment.cc
index a99201e..8d04d99 100644
--- a/src/api/environment.cc
+++ b/src/api/environment.cc
@@ -201,6 +201,7 @@
}
void SetIsolateCreateParamsForNode(Isolate::CreateParams* params) {
+#ifndef __Fuchsia__
const uint64_t constrained_memory = uv_get_constrained_memory();
const uint64_t total_memory = constrained_memory > 0 ?
std::min(uv_get_total_memory(), constrained_memory) :
@@ -213,6 +214,7 @@
}
params->embedder_wrapper_object_index = BaseObject::InternalFields::kSlot;
params->embedder_wrapper_type_index = std::numeric_limits<int>::max();
+#endif
}
void SetIsolateErrorHandlers(v8::Isolate* isolate, const IsolateSettings& s) {
diff --git a/src/debug_utils.cc b/src/debug_utils.cc
index a601c5e..45269b6 100644
--- a/src/debug_utils.cc
+++ b/src/debug_utils.cc
@@ -13,7 +13,8 @@
#if defined(__linux__) && !defined(__GLIBC__) || \
defined(__UCLIBC__) || \
- defined(_AIX)
+ defined(_AIX) || \
+ defined(__Fuchsia__)
#define HAVE_EXECINFO_H 0
#else
#define HAVE_EXECINFO_H 1
diff --git a/src/inspector_agent.cc b/src/inspector_agent.cc
index 4b7997a..62ef8f5 100644
--- a/src/inspector_agent.cc
+++ b/src/inspector_agent.cc
@@ -131,11 +131,13 @@
// receiving the signal would terminate the process.
return -err;
}
+#ifndef __Fuchsia__
RegisterSignalHandler(SIGUSR1, StartIoThreadWakeup);
// Unblock SIGUSR1. A pending SIGUSR1 signal will now be delivered.
sigemptyset(&sigmask);
sigaddset(&sigmask, SIGUSR1);
CHECK_EQ(0, pthread_sigmask(SIG_UNBLOCK, &sigmask, nullptr));
+#endif
return 0;
}
#endif // __POSIX__
diff --git a/src/node.cc b/src/node.cc
index d68c6d8..737bb73 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -101,7 +101,9 @@
#define STDIN_FILENO 0
#else
#include <pthread.h>
+#ifndef __Fuchsia__
#include <sys/resource.h> // getrlimit, setrlimit
+#endif
#include <termios.h> // tcgetattr, tcsetattr
#include <unistd.h> // STDIN_FILENO, STDERR_FILENO
#endif
@@ -527,7 +529,7 @@
}
#endif // NODE_USE_V8_WASM_TRAP_HANDLER
-#ifdef __POSIX__
+#if defined(POSIX) && !defined(__Fuchsia__)
void RegisterSignalHandler(int signal,
sigaction_cb handler,
bool reset_handler) {
@@ -572,6 +574,10 @@
// Make sure file descriptors 0-2 are valid before we start logging anything.
for (auto& s : stdio) {
const int fd = &s - stdio;
+#ifdef __Fuchsia__
+ // In fuchsia stdin is not readily available.
+ if (fd == 0) continue;
+#endif
if (fstat(fd, &s.stat) == 0)
continue;
// Anything but EBADF means something is seriously wrong. We don't
@@ -589,7 +595,7 @@
#endif // HAVE_INSPECTOR
// TODO(addaleax): NODE_SHARED_MODE does not really make sense here.
-#ifndef NODE_SHARED_MODE
+#if !defined(NODE_SHARED_MODE) && !defined(__Fuchsia__)
// Restore signal dispositions, the parent process may have changed them.
struct sigaction act;
memset(&act, 0, sizeof(act));
@@ -611,6 +617,10 @@
for (auto& s : stdio) {
const int fd = &s - stdio;
int err;
+#ifdef __Fuchsia__
+ // In fuchsia stdin is not readily available.
+ if (fd == 0) continue;
+#endif
do
s.flags = fcntl(fd, F_GETFL);
@@ -626,6 +636,7 @@
CHECK_EQ(err, 0);
}
+#ifndef __Fuchsia__
RegisterSignalHandler(SIGINT, SignalExit, true);
RegisterSignalHandler(SIGTERM, SignalExit, true);
@@ -663,6 +674,7 @@
}
} while (min + 1 < max);
}
+#endif // __Fuchsia__
#endif // __POSIX__
#ifdef _WIN32
for (int fd = 0; fd <= 2; ++fd) {
@@ -687,6 +699,11 @@
for (auto& s : stdio) {
const int fd = &s - stdio;
+#ifdef __Fuchsia__
+ // In fuchsia stdin is not readily available.
+ if (fd == 0) continue;
+#endif
+
struct stat tmp;
if (-1 == fstat(fd, &tmp)) {
CHECK_EQ(errno, EBADF); // Program closed file descriptor.
diff --git a/src/node_os.cc b/src/node_os.cc
index 2e151ac..8cd38ab 100644
--- a/src/node_os.cc
+++ b/src/node_os.cc
@@ -77,7 +77,15 @@
static void GetOSInformation(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
uv_utsname_t info;
- int err = uv_os_uname(&info);
+ int err = 0;
+#ifdef __Fuchsia__
+ // TODO(victor): Update uv_os_uname to get these informations for Fuchsia
+ info.sysname[0] = 0;
+ info.version[0] = 0;
+ info.release[0] = 0;
+#else
+ err = uv_os_uname(&info);
+#endif
if (err != 0) {
CHECK_GE(args.Length(), 1);
@@ -328,6 +336,7 @@
args.GetReturnValue().Set(entry);
}
+#ifndef __Fuchsia__
static void SetPriority(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
@@ -367,7 +376,7 @@
args.GetReturnValue().Set(priority);
}
-
+#endif // !__Fuchsia__
void Initialize(Local<Object> target,
Local<Value> unused,
@@ -383,9 +392,12 @@
env->SetMethod(target, "getInterfaceAddresses", GetInterfaceAddresses);
env->SetMethod(target, "getHomeDirectory", GetHomeDirectory);
env->SetMethod(target, "getUserInfo", GetUserInfo);
+#ifndef __Fuchsia__
env->SetMethod(target, "setPriority", SetPriority);
env->SetMethod(target, "getPriority", GetPriority);
+#endif
env->SetMethod(target, "getOSInformation", GetOSInformation);
+
target->Set(env->context(),
FIXED_ONE_BYTE_STRING(env->isolate(), "isBigEndian"),
Boolean::New(env->isolate(), IsBigEndian())).Check();
diff --git a/src/node_process_methods.cc b/src/node_process_methods.cc
index 826dad1..be9d75a 100644
--- a/src/node_process_methods.cc
+++ b/src/node_process_methods.cc
@@ -28,7 +28,9 @@
typedef int mode_t;
#else
#include <pthread.h>
+#if !defined(__Fuchsia__)
#include <sys/resource.h> // getrlimit, setrlimit
+#endif
#include <termios.h> // tcgetattr, tcsetattr
#endif
@@ -89,6 +91,7 @@
}
}
+#ifndef __Fuchsia__
// CPUUsage use libuv's uv_getrusage() this-process resource usage accessor,
// to access ru_utime (user CPU time used) and ru_stime (system CPU time used),
// which are uv_timeval_t structs (long tv_sec, long tv_usec).
@@ -116,6 +119,7 @@
fields[0] = MICROS_PER_SEC * rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec;
fields[1] = MICROS_PER_SEC * rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec;
}
+#endif
static void Cwd(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
@@ -145,7 +149,7 @@
int sig;
if (!args[1]->Int32Value(context).To(&sig)) return;
- uv_pid_t own_pid = uv_os_getpid();
+ int own_pid = uv_os_getpid();
if (sig > 0 &&
(pid == 0 || pid == -1 || pid == own_pid || pid == -own_pid) &&
!HasSignalJSHandler(sig)) {
@@ -267,6 +271,7 @@
Array::New(env->isolate(), handle_v.data(), handle_v.size()));
}
+#ifndef __Fuchsia__
static void ResourceUsage(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
@@ -298,6 +303,7 @@
fields[14] = rusage.ru_nvcsw;
fields[15] = rusage.ru_nivcsw;
}
+#endif
#ifdef __POSIX__
static void DebugProcess(const FunctionCallbackInfo<Value>& args) {
@@ -547,8 +553,11 @@
env->SetMethod(target, "umask", Umask);
env->SetMethod(target, "_rawDebug", RawDebug);
env->SetMethod(target, "memoryUsage", MemoryUsage);
+
+ #ifndef __Fuchsia__
env->SetMethod(target, "cpuUsage", CPUUsage);
env->SetMethod(target, "resourceUsage", ResourceUsage);
+ #endif
env->SetMethod(target, "_getActiveRequests", GetActiveRequests);
env->SetMethod(target, "_getActiveHandles", GetActiveHandles);
@@ -573,8 +582,10 @@
registry->Register(Umask);
registry->Register(RawDebug);
registry->Register(MemoryUsage);
+#ifndef __Fuchsia__
registry->Register(CPUUsage);
registry->Register(ResourceUsage);
+#endif
registry->Register(GetActiveRequests);
registry->Register(GetActiveHandles);
diff --git a/src/node_report.cc b/src/node_report.cc
index e7bfe7f..dc3ea42 100644
--- a/src/node_report.cc
+++ b/src/node_report.cc
@@ -12,7 +12,9 @@
#ifdef _WIN32
#include <Windows.h>
#else // !_WIN32
+#ifndef __Fuchsia__
#include <sys/resource.h>
+#endif
#include <cxxabi.h>
#include <dlfcn.h>
#endif
@@ -608,6 +610,7 @@
(uv_hrtime() - node::per_process::node_start_time) / (NANOS_PER_SEC);
if (uptime == 0) uptime = 1; // avoid division by zero.
+#ifndef __Fuchsia__
// Process and current thread usage statistics
uv_rusage_t rusage;
writer->json_objectstart("resourceUsage");
@@ -632,6 +635,7 @@
writer->json_objectend();
}
writer->json_objectend();
+#endif
#ifdef RUSAGE_THREAD
struct rusage stats;
if (getrusage(RUSAGE_THREAD, &stats) == 0) {
@@ -676,7 +680,7 @@
writer->json_objectend();
-#ifndef _WIN32
+#if !defined(_WIN32) && !defined(__Fuchsia__)
static struct {
const char* description;
int id;
@@ -723,7 +727,7 @@
}
}
writer->json_objectend();
-#endif // _WIN32
+#endif // _WIN32 && __Fuchsia__
PrintLoadedLibraries(writer);
}
diff --git a/src/node_watchdog.cc b/src/node_watchdog.cc
index 8bd3b28..d10abf4 100644
--- a/src/node_watchdog.cc
+++ b/src/node_watchdog.cc
@@ -297,6 +297,7 @@
return 0;
}
+#ifndef __Fuchsia__
#ifdef __POSIX__
CHECK_EQ(has_running_thread_, false);
has_pending_signal_ = false;
@@ -322,6 +323,7 @@
SetConsoleCtrlHandler(WinCtrlCHandlerRoutine, TRUE);
}
#endif
+#endif
return 0;
}
@@ -349,6 +351,7 @@
watchdogs_.clear();
}
+#ifndef __Fuchsia__
#ifdef __POSIX__
if (!has_running_thread_) {
has_pending_signal_ = false;
@@ -369,7 +372,7 @@
had_pending_signal = has_pending_signal_;
has_pending_signal_ = false;
-
+#endif
return had_pending_signal;
}
diff --git a/test/cctest/gtest/gtest-all.cc b/test/cctest/gtest/gtest-all.cc
index ffa5f77..eca8143 100644
--- a/test/cctest/gtest/gtest-all.cc
+++ b/test/cctest/gtest/gtest-all.cc
@@ -8401,12 +8401,10 @@
: DeathTestImpl(a_statement, std::move(matcher)),
file_(file),
line_(line) {}
-
// All of these virtual functions are inherited from DeathTest.
int Wait() override;
TestRole AssumeRole() override;
std::string GetErrorLogs() override;
-
private:
// The name of the file in which the death test is located.
const char* const file_;
@@ -8414,17 +8412,14 @@
const int line_;
// The stderr data captured by the child process.
std::string captured_stderr_;
-
zx::process child_process_;
- zx::port port_;
+ zx::channel exception_channel_;
zx::socket stderr_socket_;
};
-
// Utility class for accumulating command-line arguments.
class Arguments {
public:
Arguments() { args_.push_back(nullptr); }
-
~Arguments() {
for (std::vector<char*>::iterator i = args_.begin(); i != args_.end();
++i) {
@@ -8434,7 +8429,6 @@
void AddArgument(const char* argument) {
args_.insert(args_.end() - 1, posix::StrDup(argument));
}
-
template <typename Str>
void AddArguments(const ::std::vector<Str>& arguments) {
for (typename ::std::vector<Str>::const_iterator i = arguments.begin();
@@ -8446,58 +8440,58 @@
char* const* Argv() {
return &args_[0];
}
-
int size() {
return args_.size() - 1;
}
-
private:
std::vector<char*> args_;
};
-
// Waits for the child in a death test to exit, returning its exit
// status, or 0 if no child process exists. As a side effect, sets the
// outcome data member.
int FuchsiaDeathTest::Wait() {
const int kProcessKey = 0;
const int kSocketKey = 1;
-
+ const int kExceptionKey = 2;
if (!spawned())
return 0;
-
- // Register to wait for the child process to terminate.
+ // Create a port to wait for socket/task/exception events.
zx_status_t status_zx;
+ zx::port port;
+ status_zx = zx::port::create(0, &port);
+ GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
+ // Register to wait for the child process to terminate.
status_zx = child_process_.wait_async(
- port_, kProcessKey, ZX_PROCESS_TERMINATED, ZX_WAIT_ASYNC_ONCE);
+ port, kProcessKey, ZX_PROCESS_TERMINATED, ZX_WAIT_ASYNC_ONCE);
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
// Register to wait for the socket to be readable or closed.
status_zx = stderr_socket_.wait_async(
- port_, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED,
- ZX_WAIT_ASYNC_REPEATING);
+ port, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED,
+ ZX_WAIT_ASYNC_ONCE);
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
-
+ // Register to wait for an exception.
+ status_zx = exception_channel_.wait_async(
+ port, kExceptionKey, ZX_CHANNEL_READABLE, ZX_WAIT_ASYNC_ONCE);
+ GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
bool process_terminated = false;
bool socket_closed = false;
do {
zx_port_packet_t packet = {};
- status_zx = port_.wait(zx::time::infinite(), &packet);
+ status_zx = port.wait(zx::time::infinite(), &packet);
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
-
- if (packet.key == kProcessKey) {
- if (ZX_PKT_IS_EXCEPTION(packet.type)) {
- // Process encountered an exception. Kill it directly rather than
- // letting other handlers process the event. We will get a second
- // kProcessKey event when the process actually terminates.
- status_zx = child_process_.kill();
- GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
- } else {
- // Process terminated.
- GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_ONE(packet.type));
- GTEST_DEATH_TEST_CHECK_(packet.signal.observed & ZX_PROCESS_TERMINATED);
- process_terminated = true;
- }
+ if (packet.key == kExceptionKey) {
+ // Process encountered an exception. Kill it directly rather than
+ // letting other handlers process the event. We will get a kProcessKey
+ // event when the process actually terminates.
+ status_zx = child_process_.kill();
+ GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
+ } else if (packet.key == kProcessKey) {
+ // Process terminated.
+ GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_ONE(packet.type));
+ GTEST_DEATH_TEST_CHECK_(packet.signal.observed & ZX_PROCESS_TERMINATED);
+ process_terminated = true;
} else if (packet.key == kSocketKey) {
- GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_REP(packet.type));
+ GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_ONE(packet.type));
if (packet.signal.observed & ZX_SOCKET_READABLE) {
// Read data from the socket.
constexpr size_t kBufferSize = 1024;
@@ -8514,6 +8508,10 @@
socket_closed = true;
} else {
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_ERR_SHOULD_WAIT);
+ status_zx = stderr_socket_.wait_async(
+ port, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED,
+ ZX_WAIT_ASYNC_ONCE);
+ GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
}
} else {
GTEST_DEATH_TEST_CHECK_(packet.signal.observed & ZX_SOCKET_PEER_CLOSED);
@@ -8521,19 +8519,15 @@
}
}
} while (!process_terminated && !socket_closed);
-
ReadAndInterpretStatusByte();
-
zx_info_process_t buffer;
status_zx = child_process_.get_info(
ZX_INFO_PROCESS, &buffer, sizeof(buffer), nullptr, nullptr);
GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
-
GTEST_DEATH_TEST_CHECK_(buffer.exited);
set_status(buffer.return_code);
return status();
}
-
// The AssumeRole process for a Fuchsia death test. It creates a child
// process with the same executable as the current process to run the
// death test. The child process is given the --gtest_filter and
@@ -8545,17 +8539,14 @@
impl->internal_run_death_test_flag();
const TestInfo* const info = impl->current_test_info();
const int death_test_index = info->result()->death_test_count();
-
if (flag != nullptr) {
// ParseInternalRunDeathTestFlag() has performed all the necessary
// processing.
set_write_fd(kFuchsiaReadPipeFd);
return EXECUTE_TEST;
}
-
// Flush the log buffers since the log streams are shared with the child.
FlushInfoLog();
-
// Build the child process command line.
const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
kFilterFlag + "=" + info->test_suite_name() +
@@ -8569,22 +8560,19 @@
args.AddArguments(GetInjectableArgvs());
args.AddArgument(filter_flag.c_str());
args.AddArgument(internal_flag.c_str());
-
// Build the pipe for communication with the child.
zx_status_t status;
zx_handle_t child_pipe_handle;
int child_pipe_fd;
- status = fdio_pipe_half2(&child_pipe_fd, &child_pipe_handle);
- GTEST_DEATH_TEST_CHECK_(status != ZX_OK);
+ status = fdio_pipe_half(&child_pipe_fd, &child_pipe_handle);
+ GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
set_read_fd(child_pipe_fd);
-
// Set the pipe handle for the child.
fdio_spawn_action_t spawn_actions[2] = {};
fdio_spawn_action_t* add_handle_action = &spawn_actions[0];
add_handle_action->action = FDIO_SPAWN_ACTION_ADD_HANDLE;
add_handle_action->h.id = PA_HND(PA_FD, kFuchsiaReadPipeFd);
add_handle_action->h.handle = child_pipe_handle;
-
// Create a socket pair will be used to receive the child process' stderr.
zx::socket stderr_producer_socket;
status =
@@ -8594,15 +8582,12 @@
status =
fdio_fd_create(stderr_producer_socket.release(), &stderr_producer_fd);
GTEST_DEATH_TEST_CHECK_(status >= 0);
-
// Make the stderr socket nonblocking.
GTEST_DEATH_TEST_CHECK_(fcntl(stderr_producer_fd, F_SETFL, 0) == 0);
-
fdio_spawn_action_t* add_stderr_action = &spawn_actions[1];
add_stderr_action->action = FDIO_SPAWN_ACTION_CLONE_FD;
add_stderr_action->fd.local_fd = stderr_producer_fd;
add_stderr_action->fd.target_fd = STDERR_FILENO;
-
// Create a child job.
zx_handle_t child_job = ZX_HANDLE_INVALID;
status = zx_job_create(zx_job_default(), 0, & child_job);
@@ -8613,25 +8598,20 @@
status = zx_job_set_policy(
child_job, ZX_JOB_POL_RELATIVE, ZX_JOB_POL_BASIC, &policy, 1);
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
-
- // Create an exception port and attach it to the |child_job|, to allow
+ // Create an exception channel attached to the |child_job|, to allow
// us to suppress the system default exception handler from firing.
- status = zx::port::create(0, &port_);
+ status =
+ zx_task_create_exception_channel(
+ child_job, 0, exception_channel_.reset_and_get_address());
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
- status = zx_task_bind_exception_port(
- child_job, port_.get(), 0 /* key */, 0 /*options */);
- GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
-
// Spawn the child process.
status = fdio_spawn_etc(
child_job, FDIO_SPAWN_CLONE_ALL, args.Argv()[0], args.Argv(), nullptr,
2, spawn_actions, child_process_.reset_and_get_address(), nullptr);
GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
-
set_spawned(true);
return OVERSEE_TEST;
}
-
std::string FuchsiaDeathTest::GetErrorLogs() {
return captured_stderr_;
}