}
}
-static void *(*alloc)(void *ptr, size_t size) = realloc;
+static void *(*alloc)(void *ptr, long size);
void
-ev_set_allocator (void *(*cb)(void *ptr, size_t size))
+ev_set_allocator (void *(*cb)(void *ptr, long size))
{
alloc = cb;
}
inline_speed void *
-ev_realloc (void *ptr, size_t size)
+ev_realloc (void *ptr, long size)
{
- ptr = alloc (ptr, size);
+ ptr = alloc ? alloc (ptr, size) : realloc (ptr, size);
if (!ptr && size)
{
- fprintf (stderr, "libev: cannot allocate %ld bytes, aborting.", (long)size);
+ fprintf (stderr, "libev: cannot allocate %ld bytes, aborting.", size);
abort ();
}
int events;
} ANPENDING;
+#if EV_USE_INOTIFY
typedef struct
{
-#if EV_USE_INOTIFY
WL head;
-#endif
} ANFS;
+#endif
#if EV_MULTIPLICITY
{
int fd;
- /* this should be highly optimised to not do anything but set a flag */
for (fd = 0; fd < anfdmax; ++fd)
if (anfds [fd].events)
{
now_floor = mn_now;
rtmn_diff = ev_rt_now - mn_now;
+ /* pid check not overridable via env */
+#ifndef _WIN32
+ if (flags & EVFLAG_FORKCHECK)
+ curpid = getpid ();
+#endif
+
if (!(flags & EVFLAG_NOENV)
&& !enable_secure ()
&& getenv ("LIBEV_FLAGS"))
backend = 0;
}
+void inline_size infy_fork (EV_P);
+
void inline_size
loop_fork (EV_P)
{
#if EV_USE_EPOLL
if (backend == EVBACKEND_EPOLL ) epoll_fork (EV_A);
#endif
+#if EV_USE_INOTIFY
+ infy_fork (EV_A);
+#endif
if (ev_is_active (&sigev))
{
/* loop a few times, before making important decisions.
* on the choice of "4": one iteration isn't enough,
* in case we get preempted during the calls to
- * ev_time and get_clock. a second call is almost guarenteed
+ * ev_time and get_clock. a second call is almost guaranteed
* to succeed in that case, though. and looping a few more times
* doesn't hurt either as we only do this on time-jumps or
- * in the unlikely event of getting preempted here.
+ * in the unlikely event of having been preempted here.
*/
for (i = 4; --i; )
{
periodics_reschedule (EV_A);
#endif
- /* adjust timers. this is easy, as the offset is the same for all */
+ /* adjust timers. this is easy, as the offset is the same for all of them */
for (i = 0; i < timercnt; ++i)
((WT)timers [i])->at += ev_rt_now - mn_now;
}
? EVUNLOOP_ONE
: EVUNLOOP_CANCEL;
- while (activecnt)
+ call_pending (EV_A); /* in case we recurse, ensure ordering stays nice and clean */
+
+ while (expect_false (!activecnt))
{
- /* we might have forked, so reify kernel state if necessary */
- #if EV_FORK_ENABLE
- if (expect_false (postfork))
- if (forkcnt)
- {
- queue_events (EV_A_ (W *)forks, forkcnt, EV_FORK);
- call_pending (EV_A);
- }
- #endif
+#ifndef _WIN32
+ if (expect_false (curpid)) /* penalise the forking check even more */
+ if (expect_false (getpid () != curpid))
+ {
+ curpid = getpid ();
+ postfork = 1;
+ }
+#endif
+
+#if EV_FORK_ENABLE
+ /* we might have forked, so queue fork handlers */
+ if (expect_false (postfork))
+ if (forkcnt)
+ {
+ queue_events (EV_A_ (W *)forks, forkcnt, EV_FORK);
+ call_pending (EV_A);
+ }
+#endif
/* queue check watchers (and execute them) */
if (expect_false (preparecnt))
call_pending (EV_A);
}
+ if (expect_false (!activecnt))
+ break;
+
/* we might have forked, so reify kernel state if necessary */
if (expect_false (postfork))
loop_fork (EV_A);
/* calculate blocking time */
{
- double block;
+ ev_tstamp block;
- if (flags & EVLOOP_NONBLOCK || idlecnt)
+ if (expect_false (flags & EVLOOP_NONBLOCK || idlecnt || !activecnt))
block = 0.; /* do not block at all */
else
{
#define DEF_STAT_INTERVAL 5.0074891
#define MIN_STAT_INTERVAL 0.1074891
-void noinline stat_timer_cb (EV_P_ ev_timer *w_, int revents);
+static void noinline stat_timer_cb (EV_P_ ev_timer *w_, int revents);
#if EV_USE_INOTIFY
-# define EV_INOTIFY_BUFSIZE ((PATH_MAX + sizeof (struct inotify_event)) + 2048)
+# define EV_INOTIFY_BUFSIZE 8192
static void noinline
infy_add (EV_P_ ev_stat *w)
ev_timer_start (EV_A_ &w->timer); /* this is not race-free, so we still need to recheck periodically */
/* monitor some parent directory for speedup hints */
- if (errno == ENOENT || errno == EACCES)
+ if ((errno == ENOENT || errno == EACCES) && strlen (w->path) < 4096)
{
- char path [PATH_MAX];
+ char path [4096];
strcpy (path, w->path);
do
break; /* whoops, no '/', complain to your admin */
*pend = 0;
- w->wd = inotify_add_watch (fs_fd, path, IN_DELETE_SELF | IN_CREATE | IN_MOVED_TO | IN_MASK_ADD);
+ w->wd = inotify_add_watch (fs_fd, path, mask);
}
while (w->wd < 0 && (errno == ENOENT || errno == EACCES));
}
static void noinline
infy_del (EV_P_ ev_stat *w)
{
- WL w_;
int slot;
int wd = w->wd;
infy_add (EV_A_ w); /* re-add, no matter what */
}
- stat_timer_cb (EV_P_ &w->timer, 0);
+ stat_timer_cb (EV_A_ &w->timer, 0);
}
}
}
}
}
+void inline_size
+infy_fork (EV_P)
+{
+ int slot;
+
+ if (fs_fd < 0)
+ return;
+
+ close (fs_fd);
+ fs_fd = inotify_init ();
+
+ for (slot = 0; slot < EV_INOTIFY_HASHSIZE; ++slot)
+ {
+ WL w_ = fs_hash [slot].head;
+ fs_hash [slot].head = 0;
+
+ while (w_)
+ {
+ ev_stat *w = (ev_stat *)w_;
+ w_ = w_->next; /* lets us add this watcher */
+
+ w->wd = -1;
+
+ if (fs_fd >= 0)
+ infy_add (EV_A_ w); /* re-add, no matter what */
+ else
+ ev_timer_start (EV_A_ &w->timer);
+ }
+
+ }
+}
+
#endif
void
w->attr.st_nlink = 1;
}
-void noinline
+static void noinline
stat_timer_cb (EV_P_ ev_timer *w_, int revents)
{
ev_stat *w = (ev_stat *)(((char *)w_) - offsetof (ev_stat, timer));
w->prev = w->attr;
ev_stat_stat (EV_A_ w);
- if (memcmp (&w->prev, &w->attr, sizeof (ev_statdata)))
- {
+ /* memcmp doesn't work on netbsd, they.... do stuff to their struct stat */
+ if (
+ w->prev.st_dev != w->attr.st_dev
+ || w->prev.st_ino != w->attr.st_ino
+ || w->prev.st_mode != w->attr.st_mode
+ || w->prev.st_nlink != w->attr.st_nlink
+ || w->prev.st_uid != w->attr.st_uid
+ || w->prev.st_gid != w->attr.st_gid
+ || w->prev.st_rdev != w->attr.st_rdev
+ || w->prev.st_size != w->attr.st_size
+ || w->prev.st_atime != w->attr.st_atime
+ || w->prev.st_mtime != w->attr.st_mtime
+ || w->prev.st_ctime != w->attr.st_ctime
+ ) {
#if EV_USE_INOTIFY
infy_del (EV_A_ w);
infy_add (EV_A_ w);