+ fd_intern (sigpipe [0]);
+ fd_intern (sigpipe [1]);
+
+ ev_io_set (&sigev, sigpipe [0], EV_READ);
+ ev_io_start (EV_A_ &sigev);
+ ev_unref (EV_A); /* child watcher should not keep loop alive */
+}
+
+/*****************************************************************************/
+
+static struct ev_child *childs [PID_HASHSIZE];
+
+#ifndef _WIN32
+
+static struct ev_signal childev;
+
+#ifndef WCONTINUED
+# define WCONTINUED 0
+#endif
+
+static void
+child_reap (EV_P_ struct ev_signal *sw, int chain, int pid, int status)
+{
+ struct ev_child *w;
+
+ for (w = (struct ev_child *)childs [chain & (PID_HASHSIZE - 1)]; w; w = (struct ev_child *)((WL)w)->next)
+ if (w->pid == pid || !w->pid)
+ {
+ ev_priority (w) = ev_priority (sw); /* need to do it *now* */
+ w->rpid = pid;
+ w->rstatus = status;
+ ev_feed_event (EV_A_ (W)w, EV_CHILD);
+ }
+}
+
+static void
+childcb (EV_P_ struct ev_signal *sw, int revents)
+{
+ int pid, status;
+
+ if (0 < (pid = waitpid (-1, &status, WNOHANG | WUNTRACED | WCONTINUED)))
+ {
+ /* make sure we are called again until all childs have been reaped */
+ ev_feed_event (EV_A_ (W)sw, EV_SIGNAL);
+
+ child_reap (EV_A_ sw, pid, pid, status);
+ child_reap (EV_A_ sw, 0, pid, status); /* this might trigger a watcher twice, but event catches that */
+ }
+}
+
+#endif
+
+/*****************************************************************************/
+
+#if EV_USE_KQUEUE
+# include "ev_kqueue.c"
+#endif
+#if EV_USE_EPOLL
+# include "ev_epoll.c"
+#endif
+#if EV_USE_POLL
+# include "ev_poll.c"
+#endif
+#if EV_USE_SELECT
+# include "ev_select.c"
+#endif
+
+int
+ev_version_major (void)
+{
+ return EV_VERSION_MAJOR;
+}
+
+int
+ev_version_minor (void)
+{
+ return EV_VERSION_MINOR;
+}
+
+/* return true if we are running with elevated privileges and should ignore env variables */
+static int
+enable_secure (void)
+{
+#ifdef _WIN32
+ return 0;
+#else
+ return getuid () != geteuid ()
+ || getgid () != getegid ();
+#endif
+}
+
+int
+ev_method (EV_P)
+{
+ return method;
+}
+
+static void
+loop_init (EV_P_ unsigned int flags)
+{
+ if (!method)
+ {
+#if EV_USE_MONOTONIC
+ {
+ struct timespec ts;
+ if (!clock_gettime (CLOCK_MONOTONIC, &ts))
+ have_monotonic = 1;
+ }
+#endif
+
+ ev_rt_now = ev_time ();
+ mn_now = get_clock ();
+ now_floor = mn_now;
+ rtmn_diff = ev_rt_now - mn_now;
+
+ if (!(flags & EVMETHOD_NOENV) && !enable_secure () && getenv ("LIBEV_FLAGS"))
+ flags = atoi (getenv ("LIBEV_FLAGS"));
+
+ if (!(flags & 0x0000ffff))
+ flags |= 0x0000ffff;
+
+ method = 0;
+#if EV_USE_KQUEUE
+ if (!method && (flags & EVMETHOD_KQUEUE)) method = kqueue_init (EV_A_ flags);
+#endif
+#if EV_USE_EPOLL
+ if (!method && (flags & EVMETHOD_EPOLL )) method = epoll_init (EV_A_ flags);
+#endif
+#if EV_USE_POLL
+ if (!method && (flags & EVMETHOD_POLL )) method = poll_init (EV_A_ flags);
+#endif
+#if EV_USE_SELECT
+ if (!method && (flags & EVMETHOD_SELECT)) method = select_init (EV_A_ flags);
+#endif
+
+ ev_init (&sigev, sigcb);
+ ev_set_priority (&sigev, EV_MAXPRI);
+ }
+}
+
+void
+loop_destroy (EV_P)
+{
+ int i;
+
+#if EV_USE_KQUEUE
+ if (method == EVMETHOD_KQUEUE) kqueue_destroy (EV_A);
+#endif
+#if EV_USE_EPOLL
+ if (method == EVMETHOD_EPOLL ) epoll_destroy (EV_A);
+#endif
+#if EV_USE_POLL
+ if (method == EVMETHOD_POLL ) poll_destroy (EV_A);
+#endif
+#if EV_USE_SELECT
+ if (method == EVMETHOD_SELECT) select_destroy (EV_A);
+#endif
+
+ for (i = NUMPRI; i--; )
+ array_free (pending, [i]);
+
+ /* have to use the microsoft-never-gets-it-right macro */
+ array_free (fdchange, EMPTY);
+ array_free (timer, EMPTY);
+#if EV_PERIODICS
+ array_free (periodic, EMPTY);
+#endif
+ array_free (idle, EMPTY);
+ array_free (prepare, EMPTY);
+ array_free (check, EMPTY);
+
+ method = 0;
+}
+
+static void
+loop_fork (EV_P)
+{
+#if EV_USE_EPOLL
+ if (method == EVMETHOD_EPOLL ) epoll_fork (EV_A);
+#endif
+#if EV_USE_KQUEUE
+ if (method == EVMETHOD_KQUEUE) kqueue_fork (EV_A);
+#endif
+
+ if (ev_is_active (&sigev))
+ {
+ /* default loop */
+
+ ev_ref (EV_A);
+ ev_io_stop (EV_A_ &sigev);
+ close (sigpipe [0]);
+ close (sigpipe [1]);