--- EV/EV.xs 2008/11/23 17:44:46 1.120 +++ EV/EV.xs 2009/04/15 17:49:26 1.121 @@ -48,21 +48,27 @@ #define e_loop(w) INT2PTR (struct ev_loop *, SvIVX ((w)->loop)) #define WFLAG_KEEPALIVE 1 +#define WFLAG_UNREFED 2 /* has been unref'ed */ #define UNREF(w) \ - if (!((w)->e_flags & WFLAG_KEEPALIVE) \ - && !ev_is_active (w)) \ - ev_unref (e_loop (w)); + if (!((w)->e_flags & (WFLAG_KEEPALIVE | WFLAG_UNREFED)) \ + && ev_is_active (w)) \ + { \ + ev_unref (e_loop (w)); \ + (w)->e_flags |= WFLAG_UNREFED; \ + } #define REF(w) \ - if (!((w)->e_flags & WFLAG_KEEPALIVE) \ - && ev_is_active (w)) \ - ev_ref (e_loop (w)); + if ((w)->e_flags & WFLAG_UNREFED) \ + { \ + (w)->e_flags &= ~WFLAG_UNREFED; \ + ev_ref (e_loop (w)); \ + } #define START(type,w) \ do { \ - UNREF (w); \ ev_ ## type ## _start (e_loop (w), w); \ + UNREF (w); \ } while (0) #define STOP(type,w) \ @@ -221,6 +227,11 @@ I32 mark = SP - PL_stack_base; SV *sv_self, *sv_events; + /* libev might have stopped the watcher */ + if (expect_false (w->e_flags & WFLAG_UNREFED) + && !ev_is_active (w)) + REF (w); + if (expect_true (sv_self_cache)) { sv_self = sv_self_cache; sv_self_cache = 0; @@ -749,8 +760,8 @@ if (items > 1 && ((new_value ^ w->e_flags) & WFLAG_KEEPALIVE)) { - REF (w); w->e_flags = (w->e_flags & ~WFLAG_KEEPALIVE) | new_value; + REF (w); UNREF (w); } } @@ -935,7 +946,6 @@ INIT: CHECK_REPEAT (w->repeat); CODE: - REF (w); ev_timer_again (e_loop (w), w); UNREF (w); @@ -964,7 +974,6 @@ void ev_periodic_again (ev_periodic *w) CODE: - REF (w); ev_periodic_again (e_loop (w), w); UNREF (w);