From d0beac70f4d494c4c481281d6c8f672deae9a5d8 Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Thu, 16 Dec 2010 18:40:23 -0800 Subject: [PATCH] Revert "Simplify next tick logic by looping around ev_loop" This reverts commit 241ea7e5954e4a049af85cd8d51b84202cf0ea3a. Fixes GH-511: https://github.com/ry/node/issues/issue/511 --- deps/libev/ev.c | 6 ------ deps/libev/ev.h | 1 - src/node.cc | 34 ++++++++++++++++++++++------------ 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/deps/libev/ev.c b/deps/libev/ev.c index 59b5e23306..168f93b7d1 100644 --- a/deps/libev/ev.c +++ b/deps/libev/ev.c @@ -2469,12 +2469,6 @@ ev_unref (EV_P) --activecnt; } -int -ev_activecnt (EV_P) -{ - return activecnt; -} - void ev_now_update (EV_P) { diff --git a/deps/libev/ev.h b/deps/libev/ev.h index 45a53acd34..96e735871a 100644 --- a/deps/libev/ev.h +++ b/deps/libev/ev.h @@ -603,7 +603,6 @@ void ev_break (EV_P_ int how); /* set to 1 to break out of event loop, set to 2 */ void ev_ref (EV_P); void ev_unref (EV_P); -int ev_activecnt (EV_P); /* * convenience function, wait for a single event, without registering an event watcher diff --git a/src/node.cc b/src/node.cc index fa80180836..b4d4c90b5e 100644 --- a/src/node.cc +++ b/src/node.cc @@ -83,6 +83,7 @@ static int max_stack_size = 0; static ev_check check_tick_watcher; static ev_prepare prepare_tick_watcher; +static ev_idle tick_spinner; static bool need_tick_cb; static Persistent tick_callback_sym; @@ -172,15 +173,28 @@ static void Check(EV_P_ ev_check *watcher, int revents) { static Handle NeedTickCallback(const Arguments& args) { HandleScope scope; need_tick_cb = true; + // TODO: this tick_spinner shouldn't be necessary. An ev_prepare should be + // sufficent, the problem is only in the case of the very last "tick" - + // there is nothing left to do in the event loop and libev will exit. The + // ev_prepare callback isn't called before exiting. Thus we start this + // tick_spinner to keep the event loop alive long enough to handle it. + ev_idle_start(EV_DEFAULT_UC_ &tick_spinner); return Undefined(); } +static void Spin(EV_P_ ev_idle *watcher, int revents) { + assert(watcher == &tick_spinner); + assert(revents == EV_IDLE); +} + + static void Tick(void) { // Avoid entering a V8 scope. if (!need_tick_cb) return; need_tick_cb = false; + ev_idle_stop(EV_DEFAULT_UC_ &tick_spinner); HandleScope scope; @@ -1920,6 +1934,8 @@ int Start(int argc, char *argv[]) { ev_check_start(EV_DEFAULT_UC_ &node::check_tick_watcher); ev_unref(EV_DEFAULT_UC); + ev_idle_init(&node::tick_spinner, node::Spin); + ev_check_init(&node::gc_check, node::Check); ev_check_start(EV_DEFAULT_UC_ &node::gc_check); ev_unref(EV_DEFAULT_UC); @@ -1998,18 +2014,12 @@ int Start(int argc, char *argv[]) { // Avoids failing on test/simple/test-eio-race3.js though ev_idle_start(EV_DEFAULT_UC_ &eio_poller); - - do { - // All our arguments are loaded. We've evaluated all of the scripts. We - // might even have created TCP servers. Now we enter the main eventloop. If - // there are no watchers on the loop (except for the ones that were - // ev_unref'd) then this function exits. As long as there are active - // watchers, it blocks. - ev_loop(EV_DEFAULT_UC_ 0); - - Tick(); - - } while (need_tick_cb || ev_activecnt(EV_DEFAULT_UC) > 0); + // All our arguments are loaded. We've evaluated all of the scripts. We + // might even have created TCP servers. Now we enter the main eventloop. If + // there are no watchers on the loop (except for the ones that were + // ev_unref'd) then this function exits. As long as there are active + // watchers, it blocks. + ev_loop(EV_DEFAULT_UC_ 0); // process.emit('exit')