From f0682514940baa5d737065af6673b404221cb08c Mon Sep 17 00:00:00 2001 From: Brandon Beacher Date: Mon, 5 Oct 2009 20:56:33 -0400 Subject: [PATCH] Added signal handler. To be used internally. Needs an exposed interface. --- src/node.cc | 2 + src/signal_handler.cc | 69 +++++++++++++++++++++++++++++ src/signal_handler.h | 33 ++++++++++++++ test/mjsunit/test-signal-handler.js | 35 +++++++++++++++ wscript | 1 + 5 files changed, 140 insertions(+) create mode 100644 src/signal_handler.cc create mode 100644 src/signal_handler.h create mode 100644 test/mjsunit/test-signal-handler.js diff --git a/src/node.cc b/src/node.cc index b86c04c5eb..cfca8a87a5 100644 --- a/src/node.cc +++ b/src/node.cc @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -380,6 +381,7 @@ static Local Load(int argc, char *argv[]) { Stdio::Initialize(node_obj); Timer::Initialize(node_obj); + SignalHandler::Initialize(node_obj); ChildProcess::Initialize(node_obj); DefineConstants(node_obj); diff --git a/src/signal_handler.cc b/src/signal_handler.cc new file mode 100644 index 0000000000..ff00719219 --- /dev/null +++ b/src/signal_handler.cc @@ -0,0 +1,69 @@ +// Copyright 2009 Ryan Dahl +#include +#include + +namespace node { + +using namespace v8; + +Persistent SignalHandler::constructor_template; + +void SignalHandler::Initialize(Handle target) { + HandleScope scope; + + Local t = FunctionTemplate::New(SignalHandler::New); + constructor_template = Persistent::New(t); + constructor_template->Inherit(EventEmitter::constructor_template); + constructor_template->InstanceTemplate()->SetInternalFieldCount(1); + constructor_template->SetClassName(String::NewSymbol("SignalHandler")); + + NODE_SET_PROTOTYPE_METHOD(constructor_template, "stop", SignalHandler::Stop); + + target->Set(String::NewSymbol("SignalHandler"), + constructor_template->GetFunction()); +} + +void SignalHandler::OnSignal(EV_P_ ev_signal *watcher, int revents) { + SignalHandler *handler = static_cast(watcher->data); + HandleScope scope; + + assert(revents == EV_SIGNAL); + + handler->Emit("signal", 0, NULL); +} + +SignalHandler::~SignalHandler() { + ev_signal_stop(EV_DEFAULT_UC_ &watcher_); +} + +Handle SignalHandler::New(const Arguments& args) { + HandleScope scope; + + if (args.Length() != 1 || !args[0]->IsInt32()) { + return ThrowException(String::New("Bad arguments")); + } + + int sig = args[0]->Int32Value(); + + SignalHandler *handler = new SignalHandler(); + handler->Wrap(args.Holder()); + + ev_signal_init(&handler->watcher_, SignalHandler::OnSignal, sig); + handler->watcher_.data = handler; + ev_signal_start(EV_DEFAULT_UC_ &handler->watcher_); + + handler->Attach(); + + return args.This(); +} + +Handle SignalHandler::Stop(const Arguments& args) { + HandleScope scope; + + SignalHandler *handler = ObjectWrap::Unwrap(args.Holder()); + ev_signal_stop(EV_DEFAULT_UC_ &handler->watcher_); + handler->Detach(); + return Undefined(); +} + +} // namespace node diff --git a/src/signal_handler.h b/src/signal_handler.h new file mode 100644 index 0000000000..88098b45ca --- /dev/null +++ b/src/signal_handler.h @@ -0,0 +1,33 @@ +// Copyright 2009 Ryan Dahl +#ifndef SRC_SIGNAL_HANDLER_H_ +#define SRC_SIGNAL_HANDLER_H_ + +#include +#include + +#include +#include + +namespace node { + +class SignalHandler : EventEmitter { + public: + static void Initialize(v8::Handle target); + + protected: + static v8::Persistent constructor_template; + + SignalHandler() : EventEmitter() { } + ~SignalHandler(); + + static v8::Handle New(const v8::Arguments& args); + static v8::Handle Stop(const v8::Arguments& args); + + private: + static void OnSignal(EV_P_ ev_signal *watcher, int revents); + ev_signal watcher_; +}; + +} // namespace node +#endif // SRC_SIGNAL_HANDLER_H_ + diff --git a/test/mjsunit/test-signal-handler.js b/test/mjsunit/test-signal-handler.js new file mode 100644 index 0000000000..a7d6a58539 --- /dev/null +++ b/test/mjsunit/test-signal-handler.js @@ -0,0 +1,35 @@ +node.mixin(require("common.js")); + +if (process.ARGV[2] === "-child") { + node.stdio.open(); + var handler = new node.SignalHandler(node.SIGUSR1); + handler.addListener("signal", function() { + node.stdio.write("handled SIGUSR1"); + process.exit(0); + }); + debug("CHILD!!!"); + +} else { + + var child = node.createChildProcess(ARGV[0], ['--', ARGV[1], '-child']); + + var output = ""; + + child.addListener('output', function (chunk) { + puts("Child (stdout) said: " + JSON.stringify(chunk)); + if (chunk) { output += chunk }; + }); + + child.addListener('error', function (chunk) { + if (/CHILD!!!/.exec(chunk)) { + puts("Sending SIGUSR1 to " + child.pid); + child.kill(node.SIGUSR1) + } + puts("Child (stderr) said: " + JSON.stringify(chunk)); + }); + + process.addListener("exit", function () { + assertEquals("handled SIGUSR1", output); + }); + +} diff --git a/wscript b/wscript index ddf618e10a..f0431d5740 100644 --- a/wscript +++ b/wscript @@ -311,6 +311,7 @@ def build(bld): src/node_stdio.cc src/dns.cc src/file.cc + src/signal_handler.cc src/timer.cc src/child_process.cc src/constants.cc