Skip to content

Commit

Permalink
refactor: convert to n-api
Browse files Browse the repository at this point in the history
  • Loading branch information
deepak1556 committed Aug 13, 2019
1 parent 277683b commit 4cb3040
Show file tree
Hide file tree
Showing 2 changed files with 168 additions and 23 deletions.
60 changes: 60 additions & 0 deletions src/common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include <node_api.h>

// Empty value so that macros here are able to return NULL or void
#define NAPI_RETVAL_NOTHING // Intentionally blank #define

#define GET_AND_THROW_LAST_ERROR(env) \
do \
{ \
const napi_extended_error_info *error_info; \
napi_get_last_error_info((env), &error_info); \
bool is_pending; \
napi_is_exception_pending((env), &is_pending); \
/* If an exception is already pending, don't rethrow it */ \
if (!is_pending) \
{ \
const char *error_message = error_info->error_message != NULL ? error_info->error_message : "empty error message"; \
napi_throw_error((env), NULL, error_message); \
} \
} while (0)

#define NAPI_ASSERT_BASE(env, assertion, message, ret_val) \
do \
{ \
if (!(assertion)) \
{ \
napi_throw_error( \
(env), \
NULL, \
"assertion (" #assertion ") failed: " message); \
return ret_val; \
} \
} while (0)

// Returns NULL on failed assertion.
// This is meant to be used inside napi_callback methods.
#define NAPI_ASSERT(env, assertion, message) \
NAPI_ASSERT_BASE(env, assertion, message, NULL)

#define NAPI_CALL_BASE(env, the_call, ret_val) \
do \
{ \
if ((the_call) != napi_ok) \
{ \
GET_AND_THROW_LAST_ERROR((env)); \
return ret_val; \
} \
} while (0)

// Returns NULL if the_call doesn't return napi_ok.
#define NAPI_CALL(env, the_call) \
NAPI_CALL_BASE(env, the_call, NULL)

// Returns empty if the_call doesn't return napi_ok.
#define NAPI_CALL_RETURN_VOID(env, the_call) \
NAPI_CALL_BASE(env, the_call, NAPI_RETVAL_NOTHING)

#define DECLARE_NAPI_PROPERTY(name, func) \
{ \
(name), NULL, (func), NULL, NULL, NULL, napi_default, NULL \
}
131 changes: 108 additions & 23 deletions src/watchdog.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,37 @@
* Licensed under the MIT License. See LICENSE in the project root for license information.
*--------------------------------------------------------------------------------------------*/

#include <node.h>
#include <uv.h>
#include "common.h"
#include <time.h>
#include <stdlib.h>

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32)
#else
#if defined(_WIN32) || defined(__WIN32)
#ifndef WIN32
#define WIN32
#endif
#endif

#if !defined(WIN32)
#include <unistd.h>
#include <signal.h>
#else
#include <windows.h>
#endif

using namespace v8;
namespace
{

using WorkerInfo = struct
{
int64_t parent_pid = 0;
napi_async_work request = nullptr;
};

WorkerInfo worker_info;

bool w_processIsRunning(long pid)
{
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32)
#if defined(WIN32)
HANDLE process = OpenProcess(SYNCHRONIZE, FALSE, pid);
DWORD ret = WaitForSingleObject(process, 0);
CloseHandle(process);
Expand All @@ -29,44 +45,113 @@ bool w_processIsRunning(long pid)

void w_sleep(int seconds)
{
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32)
#if defined(WIN32)
Sleep(seconds * 1000);
#else
sleep(seconds);
#endif
}

long w_parentpid = 0; // id of the parent process
uv_thread_t w_monitor_thread_id; // id of the monitor thread

void w_monitor(void *arg)
void Execute(napi_env env, void *data)
{
auto *info = static_cast<WorkerInfo *>(data);

if (info != &worker_info)
{
return;
}

while (true)
{
if (!w_processIsRunning(w_parentpid))
if (!w_processIsRunning(info->parent_pid))
{
w_sleep(5);
exit(87);
return;
}
w_sleep(1);
}
}

void _Start(const FunctionCallbackInfo<Value> &args)
void Complete(napi_env env, napi_status status, void *data)
{
auto *info = static_cast<WorkerInfo *>(data);

if (info != &worker_info)
{
napi_throw_type_error(env, nullptr, "Wrong data parameter to Complete.");
return;
}

if (status != napi_ok)
{
napi_throw_type_error(env, nullptr, "Execute callback failed.");
return;
}

NAPI_CALL_RETURN_VOID(env, napi_delete_async_work(env, info->request));

exit(87);
}

} // namespace

napi_value Start(napi_env env, napi_callback_info info)
{
w_parentpid = (long)Local<Number>::Cast(args[0])->Value();
uv_thread_create(&w_monitor_thread_id, w_monitor, NULL);
size_t argc = 1;
napi_value argv[1];
NAPI_CALL(env,
napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));

NAPI_ASSERT(env, argc == 1, "Wrong number of arguments, expected 1.");

napi_valuetype t;
NAPI_CALL(env, napi_typeof(env, argv[0], &t));
NAPI_ASSERT(env, t == napi_number,
"Wrong argument, number expected.");

NAPI_CALL(env, napi_get_value_int64(env, argv[0], &worker_info.parent_pid));

napi_value resource_name;
NAPI_CALL(env, napi_create_string_utf8(
env, "StartWorkerProcess", NAPI_AUTO_LENGTH, &resource_name));
NAPI_CALL(env, napi_create_async_work(env, nullptr, resource_name,
Execute, Complete, &worker_info, &worker_info.request));
NAPI_CALL(env, napi_queue_async_work(env, worker_info.request));

return nullptr;
}

void _Exit(const FunctionCallbackInfo<Value> &args)
napi_value Exit(napi_env env, napi_callback_info info)
{
exit(args[0]->Int32Value());
size_t argc = 1;
napi_value argv[1];
NAPI_CALL(env,
napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));

NAPI_ASSERT(env, argc == 1, "Wrong number of arguments, expected 1.");

napi_valuetype t;
NAPI_CALL(env, napi_typeof(env, argv[0], &t));
NAPI_ASSERT(env, t == napi_number,
"Wrong argument, number expected.");

int32_t code;
NAPI_CALL(env, napi_get_value_int32(env, argv[0], &code));

exit(code);

return nullptr;
}

void init(Local<Object> exports)
napi_value Init(napi_env env, napi_value exports)
{
NODE_SET_METHOD(exports, "start", _Start);
NODE_SET_METHOD(exports, "exit", _Exit);
napi_property_descriptor properties[] = {
DECLARE_NAPI_PROPERTY("start", Start),
DECLARE_NAPI_PROPERTY("exit", Exit)};

NAPI_CALL(env, napi_define_properties(
env, exports, sizeof(properties) / sizeof(*properties), properties));

return exports;
}

NODE_MODULE(addon, init)
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init);

0 comments on commit 4cb3040

Please sign in to comment.