From 736e2f59e37bf6a0edfb39318adaed2694f21a73 Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Mon, 20 Aug 2012 23:59:21 +0200 Subject: [PATCH 1/2] process: use uv_signal instead of ev_signal Since libev is on it's way out, ev_signal will be removed, so switch to the libuv equivalent. As a bonus, this sort of works on Windows too. --- node.gyp | 2 +- src/node.cc | 4 ++ src/node.js | 39 +++++++----- src/node_constants.cc | 4 ++ src/node_extensions.h | 4 +- src/signal_wrap.cc | 134 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 167 insertions(+), 20 deletions(-) create mode 100644 src/signal_wrap.cc diff --git a/node.gyp b/node.gyp index cef573b41c48..047f93ac7097 100644 --- a/node.gyp +++ b/node.gyp @@ -87,6 +87,7 @@ 'src/node_string.cc', 'src/node_zlib.cc', 'src/pipe_wrap.cc', + 'src/signal_wrap.cc', 'src/stream_wrap.cc', 'src/slab_allocator.cc', 'src/tcp_wrap.cc', @@ -205,7 +206,6 @@ }, { # POSIX 'defines': [ '__POSIX__' ], 'sources': [ - 'src/node_signal_watcher.cc', 'src/node_io_watcher.cc', ], }], diff --git a/src/node.cc b/src/node.cc index 44a77f8eb6d5..261a28e4893b 100644 --- a/src/node.cc +++ b/src/node.cc @@ -694,6 +694,10 @@ const char *signo_string(int signo) { SIGNO_CASE(SIGTSTP); #endif +#ifdef SIGBREAK + SIGNO_CASE(SIGBREAK); +#endif + #ifdef SIGTTIN SIGNO_CASE(SIGTTIN); #endif diff --git a/src/node.js b/src/node.js index 07db3f096372..3811bd32ed90 100644 --- a/src/node.js +++ b/src/node.js @@ -562,40 +562,47 @@ startup.processSignalHandlers = function() { // Load events module in order to access prototype elements on process like // process.addListener. - var signalWatchers = {}; + var signalWraps = {}; var addListener = process.addListener; var removeListener = process.removeListener; function isSignal(event) { - return event.slice(0, 3) === 'SIG' && startup.lazyConstants()[event]; + return event.slice(0, 3) === 'SIG' && + startup.lazyConstants().hasOwnProperty(event); } // Wrap addListener for the special signal types process.on = process.addListener = function(type, listener) { - var ret = addListener.apply(this, arguments); - if (isSignal(type)) { - if (!signalWatchers.hasOwnProperty(type)) { - var b = process.binding('signal_watcher'); - var w = new b.SignalWatcher(startup.lazyConstants()[type]); - w.callback = function() { process.emit(type); }; - signalWatchers[type] = w; - w.start(); - - } else if (this.listeners(type).length === 1) { - signalWatchers[type].start(); + if (isSignal(type) && + !signalWraps.hasOwnProperty(type)) { + var Signal = process.binding('signal_wrap').Signal; + var wrap = new Signal(); + + wrap.unref(); + + wrap.onsignal = function () { process.emit(type); }; + + var signum = startup.lazyConstants()[type]; + var r = wrap.start(signum); + if (r) { + wrap.close(); + throw errnoException(errno, "uv_signal_start"); } + + signalWraps[type] = wrap; } - return ret; + return addListener.apply(this, arguments); }; process.removeListener = function(type, listener) { var ret = removeListener.apply(this, arguments); if (isSignal(type)) { - assert(signalWatchers.hasOwnProperty(type)); + assert(signalWraps.hasOwnProperty(type)); if (this.listeners(type).length === 0) { - signalWatchers[type].stop(); + signalWraps[type].close(); + delete signalWraps[type]; } } diff --git a/src/node_constants.cc b/src/node_constants.cc index 7999f51ea42a..06397b92803d 100644 --- a/src/node_constants.cc +++ b/src/node_constants.cc @@ -791,6 +791,10 @@ void DefineConstants(Handle target) { NODE_DEFINE_CONSTANT(target, SIGTSTP); #endif +#ifdef SIGBREAK + NODE_DEFINE_CONSTANT(target, SIGBREAK); +#endif + #ifdef SIGTTIN NODE_DEFINE_CONSTANT(target, SIGTTIN); #endif diff --git a/src/node_extensions.h b/src/node_extensions.h index 7a7702c9fb5e..c96c670af9e6 100644 --- a/src/node_extensions.h +++ b/src/node_extensions.h @@ -29,9 +29,6 @@ NODE_EXT_LIST_ITEM(node_crypto) NODE_EXT_LIST_ITEM(node_evals) NODE_EXT_LIST_ITEM(node_fs) NODE_EXT_LIST_ITEM(node_http_parser) -#ifdef __POSIX__ -NODE_EXT_LIST_ITEM(node_signal_watcher) -#endif NODE_EXT_LIST_ITEM(node_os) NODE_EXT_LIST_ITEM(node_zlib) @@ -44,6 +41,7 @@ NODE_EXT_LIST_ITEM(node_cares_wrap) NODE_EXT_LIST_ITEM(node_tty_wrap) NODE_EXT_LIST_ITEM(node_process_wrap) NODE_EXT_LIST_ITEM(node_fs_event_wrap) +NODE_EXT_LIST_ITEM(node_signal_wrap) NODE_EXT_LIST_END diff --git a/src/signal_wrap.cc b/src/signal_wrap.cc new file mode 100644 index 000000000000..91138d6d82cd --- /dev/null +++ b/src/signal_wrap.cc @@ -0,0 +1,134 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +#include "node.h" +#include "handle_wrap.h" + + +namespace node { + +using v8::Object; +using v8::Handle; +using v8::Local; +using v8::Persistent; +using v8::Value; +using v8::HandleScope; +using v8::FunctionTemplate; +using v8::String; +using v8::Function; +using v8::TryCatch; +using v8::Context; +using v8::Arguments; +using v8::Integer; + +static Persistent onsignal_sym; + + +class SignalWrap : public HandleWrap { + public: + static void Initialize(Handle target) { + HandleScope scope; + + HandleWrap::Initialize(target); + + Local constructor = FunctionTemplate::New(New); + constructor->InstanceTemplate()->SetInternalFieldCount(1); + constructor->SetClassName(String::NewSymbol("Signal")); + + NODE_SET_PROTOTYPE_METHOD(constructor, "close", HandleWrap::Close); + NODE_SET_PROTOTYPE_METHOD(constructor, "ref", HandleWrap::Ref); + NODE_SET_PROTOTYPE_METHOD(constructor, "unref", HandleWrap::Unref); + NODE_SET_PROTOTYPE_METHOD(constructor, "start", Start); + NODE_SET_PROTOTYPE_METHOD(constructor, "stop", Stop); + + onsignal_sym = NODE_PSYMBOL("onsignal"); + + target->Set(String::NewSymbol("Signal"), constructor->GetFunction()); + } + + private: + static Handle New(const Arguments& args) { + // This constructor should not be exposed to public javascript. + // Therefore we assert that we are not trying to call this as a + // normal function. + assert(args.IsConstructCall()); + + HandleScope scope; + SignalWrap *wrap = new SignalWrap(args.This()); + assert(wrap); + + return scope.Close(args.This()); + } + + SignalWrap(Handle object) + : HandleWrap(object, (uv_handle_t*) &handle_) { + int r = uv_signal_init(uv_default_loop(), &handle_); + assert(r == 0); + handle_.data = this; + } + + ~SignalWrap() { + } + + static Handle Start(const Arguments& args) { + HandleScope scope; + + UNWRAP(SignalWrap) + + int signum = args[0]->Int32Value(); + + int r = uv_signal_start(&wrap->handle_, OnSignal, signum); + + if (r) SetErrno(uv_last_error(uv_default_loop())); + + return scope.Close(Integer::New(r)); + } + + static Handle Stop(const Arguments& args) { + HandleScope scope; + + UNWRAP(SignalWrap) + + int r = uv_signal_stop(&wrap->handle_); + + if (r) SetErrno(uv_last_error(uv_default_loop())); + + return scope.Close(Integer::New(r)); + } + + static void OnSignal(uv_signal_t* handle, int signum) { + HandleScope scope; + + SignalWrap* wrap = static_cast(handle->data); + assert(wrap); + + Local argv[1] = { Integer::New(signum) }; + MakeCallback(wrap->object_, onsignal_sym, ARRAY_SIZE(argv), argv); + } + + uv_signal_t handle_; +}; + + +} // namespace node + + +NODE_MODULE(node_signal_wrap, node::SignalWrap::Initialize) From cd27d52a08b8e161eb2cf1e422fe5f9ba75f11f5 Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Tue, 21 Aug 2012 00:14:36 +0200 Subject: [PATCH 2/2] address ben's comments --- src/signal_wrap.cc | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/signal_wrap.cc b/src/signal_wrap.cc index 91138d6d82cd..b39049001a07 100644 --- a/src/signal_wrap.cc +++ b/src/signal_wrap.cc @@ -72,17 +72,15 @@ class SignalWrap : public HandleWrap { assert(args.IsConstructCall()); HandleScope scope; - SignalWrap *wrap = new SignalWrap(args.This()); - assert(wrap); + SignalWrap* wrap = new SignalWrap(args.This()); return scope.Close(args.This()); } SignalWrap(Handle object) - : HandleWrap(object, (uv_handle_t*) &handle_) { + : HandleWrap(object, reinterpret_cast(&handle_)) { int r = uv_signal_init(uv_default_loop(), &handle_); assert(r == 0); - handle_.data = this; } ~SignalWrap() { @@ -117,7 +115,7 @@ class SignalWrap : public HandleWrap { static void OnSignal(uv_signal_t* handle, int signum) { HandleScope scope; - SignalWrap* wrap = static_cast(handle->data); + SignalWrap* wrap = container_of(handle, SignalWrap, handle_); assert(wrap); Local argv[1] = { Integer::New(signum) };