diff --git a/src/node.js b/src/node.js index 4a6ed96006..0ec16f2692 100644 --- a/src/node.js +++ b/src/node.js @@ -74,9 +74,10 @@ process.addListener("newListener", function (event) { if (isSignal(event) && process.listeners(event).length === 0) { var b = process.binding('signal_watcher'); var w = new b.SignalWatcher(process[event]); - w.addListener("signal", function () { + w.callback = function () { process.emit(event); - }); + }; + w.start(); } }); diff --git a/src/node_signal_watcher.cc b/src/node_signal_watcher.cc index 1eff3ba283..c8dd3c7381 100644 --- a/src/node_signal_watcher.cc +++ b/src/node_signal_watcher.cc @@ -7,38 +7,46 @@ namespace node { using namespace v8; Persistent SignalWatcher::constructor_template; -static Persistent signal_symbol; +static Persistent callback_symbol; void SignalWatcher::Initialize(Handle target) { HandleScope scope; Local t = FunctionTemplate::New(SignalWatcher::New); constructor_template = Persistent::New(t); - constructor_template->Inherit(EventEmitter::constructor_template); constructor_template->InstanceTemplate()->SetInternalFieldCount(1); constructor_template->SetClassName(String::NewSymbol("SignalWatcher")); + NODE_SET_PROTOTYPE_METHOD(constructor_template, "start", SignalWatcher::Start); NODE_SET_PROTOTYPE_METHOD(constructor_template, "stop", SignalWatcher::Stop); - signal_symbol = NODE_PSYMBOL("signal"); - target->Set(String::NewSymbol("SignalWatcher"), constructor_template->GetFunction()); + + callback_symbol = NODE_PSYMBOL("callback"); } -void SignalWatcher::OnSignal(EV_P_ ev_signal *watcher, int revents) { +void SignalWatcher::Callback(EV_P_ ev_signal *watcher, int revents) { SignalWatcher *w = static_cast(watcher->data); + + assert(watcher == &w->watcher_); + HandleScope scope; - assert(revents == EV_SIGNAL); + Local callback_v = w->handle_->Get(callback_symbol); + if (!callback_v->IsFunction()) { + w->Stop(); + return; + } - w->Emit(signal_symbol, 0, NULL); -} + Local callback = Local::Cast(callback_v); -SignalWatcher::~SignalWatcher() { - if (watcher_.active) { - ev_ref(EV_DEFAULT_UC); - ev_signal_stop(EV_DEFAULT_UC_ &watcher_); + TryCatch try_catch; + + callback->Call(w->handle_, 0, NULL); + + if (try_catch.HasCaught()) { + FatalException(try_catch); } } @@ -51,30 +59,40 @@ Handle SignalWatcher::New(const Arguments& args) { int sig = args[0]->Int32Value(); - SignalWatcher *w = new SignalWatcher(); + SignalWatcher *w = new SignalWatcher(sig); w->Wrap(args.Holder()); - ev_signal_init(&w->watcher_, SignalWatcher::OnSignal, sig); - w->watcher_.data = w; - // Give signal handlers very high priority. The only thing that has higher - // priority is the garbage collector check. - ev_set_priority(&w->watcher_, EV_MAXPRI-1); - ev_signal_start(EV_DEFAULT_UC_ &w->watcher_); - ev_unref(EV_DEFAULT_UC); + return args.This(); +} - w->Ref(); +Handle SignalWatcher::Start(const Arguments& args) { + HandleScope scope; + SignalWatcher *w = ObjectWrap::Unwrap(args.Holder()); + w->Start(); + return Undefined(); +} - return args.This(); +void SignalWatcher::Start () { + if (!watcher_.active) { + ev_signal_start(EV_DEFAULT_UC_ &watcher_); + ev_unref(EV_DEFAULT_UC); + Ref(); + } } Handle SignalWatcher::Stop(const Arguments& args) { HandleScope scope; - SignalWatcher *w = ObjectWrap::Unwrap(args.Holder()); - ev_ref(EV_DEFAULT_UC); - ev_signal_stop(EV_DEFAULT_UC_ &w->watcher_); - w->Unref(); + w->Stop(); return Undefined(); } +void SignalWatcher::Stop () { + if (watcher_.active) { + ev_ref(EV_DEFAULT_UC); + ev_signal_stop(EV_DEFAULT_UC_ &watcher_); + Unref(); + } +} + } // namespace node diff --git a/src/node_signal_watcher.h b/src/node_signal_watcher.h index dc66e969c9..a875dd1f0d 100644 --- a/src/node_signal_watcher.h +++ b/src/node_signal_watcher.h @@ -10,21 +10,32 @@ namespace node { -class SignalWatcher : EventEmitter { +class SignalWatcher : ObjectWrap { public: static void Initialize(v8::Handle target); protected: static v8::Persistent constructor_template; - SignalWatcher() : EventEmitter() { } - ~SignalWatcher(); + SignalWatcher(int sig) : ObjectWrap() { + ev_signal_init(&watcher_, SignalWatcher::Callback, sig); + watcher_.data = this; + } + + ~SignalWatcher() { + ev_signal_stop(EV_DEFAULT_UC_ &watcher_); + } static v8::Handle New(const v8::Arguments& args); + static v8::Handle Start(const v8::Arguments& args); static v8::Handle Stop(const v8::Arguments& args); private: - static void OnSignal(EV_P_ ev_signal *watcher, int revents); + static void Callback(EV_P_ ev_signal *watcher, int revents); + + void Start(); + void Stop(); + ev_signal watcher_; };