rev 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +11 -0
- data/README +10 -3
- data/Rakefile +2 -2
- data/examples/echo_client.rb +35 -0
- data/examples/google.rb +8 -0
- data/examples/httpclient.rb +35 -0
- data/ext/http11_client/Makefile +149 -0
- data/ext/http11_client/http11_client.bundle +0 -0
- data/ext/http11_client/http11_client.o +0 -0
- data/ext/http11_client/http11_parser.o +0 -0
- data/ext/http11_client/mkmf.log +12 -0
- data/ext/libev/Changes +114 -1
- data/ext/libev/ev.c +212 -97
- data/ext/libev/ev.h +13 -7
- data/ext/libev/ev_epoll.c +44 -11
- data/ext/libev/ev_kqueue.c +2 -2
- data/ext/libev/ev_poll.c +3 -1
- data/ext/libev/ev_port.c +4 -4
- data/ext/libev/ev_select.c +58 -19
- data/ext/libev/ev_vars.h +5 -1
- data/ext/libev/ev_win32.c +32 -3
- data/ext/libev/ev_wrap.h +4 -0
- data/ext/libev/test_libev_win32.c +123 -0
- data/ext/libev/update_ev_wrap +0 -0
- data/ext/rev/Makefile +149 -0
- data/ext/rev/ev_wrap.h +8 -0
- data/ext/rev/extconf.rb +17 -0
- data/ext/rev/libev.c +8 -0
- data/ext/rev/libev.o +0 -0
- data/ext/rev/mkmf.log +221 -0
- data/ext/rev/rev.h +8 -2
- data/ext/rev/rev_buffer.c +2 -3
- data/ext/rev/rev_buffer.o +0 -0
- data/ext/rev/rev_ext.bundle +0 -0
- data/ext/rev/rev_ext.c +4 -3
- data/ext/rev/rev_ext.o +0 -0
- data/ext/rev/rev_io_watcher.c +1 -2
- data/ext/rev/rev_io_watcher.o +0 -0
- data/ext/rev/rev_loop.c +4 -4
- data/ext/rev/rev_loop.o +0 -0
- data/ext/rev/rev_ssl.o +0 -0
- data/ext/rev/rev_timer_watcher.c +1 -2
- data/ext/rev/rev_timer_watcher.o +0 -0
- data/ext/rev/rev_utils.c +14 -0
- data/ext/rev/rev_utils.o +0 -0
- data/ext/rev/rev_watcher.c +7 -6
- data/ext/rev/rev_watcher.o +0 -0
- data/lib/http11_client.bundle +0 -0
- data/lib/rev.rb +1 -1
- data/lib/rev/dns_resolver.rb +29 -9
- data/lib/rev/io.rb +6 -4
- data/lib/rev/listener.rb +5 -1
- data/lib/rev/loop.rb +8 -4
- data/lib/rev/server.rb +3 -2
- data/lib/rev/socket.rb +14 -5
- data/lib/rev_ext.bundle +0 -0
- data/lib/revem.rb +210 -0
- data/rev.gemspec +2 -2
- metadata +29 -3
data/ext/libev/ev.c
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
/*
|
2
2
|
* libev event processing core, watcher management
|
3
3
|
*
|
4
|
-
* Copyright (c) 2007,2008 Marc Alexander Lehmann <libev@schmorp.de>
|
4
|
+
* Copyright (c) 2007,2008,2009 Marc Alexander Lehmann <libev@schmorp.de>
|
5
5
|
* All rights reserved.
|
6
6
|
*
|
7
7
|
* Redistribution and use in source and binary forms, with or without modifica-
|
@@ -49,6 +49,18 @@ extern "C" {
|
|
49
49
|
# include "config.h"
|
50
50
|
# endif
|
51
51
|
|
52
|
+
# if HAVE_CLOCK_SYSCALL
|
53
|
+
# ifndef EV_USE_CLOCK_SYSCALL
|
54
|
+
# define EV_USE_CLOCK_SYSCALL 1
|
55
|
+
# ifndef EV_USE_REALTIME
|
56
|
+
# define EV_USE_REALTIME 0
|
57
|
+
# endif
|
58
|
+
# ifndef EV_USE_MONOTONIC
|
59
|
+
# define EV_USE_MONOTONIC 1
|
60
|
+
# endif
|
61
|
+
# endif
|
62
|
+
# endif
|
63
|
+
|
52
64
|
# if HAVE_CLOCK_GETTIME
|
53
65
|
# ifndef EV_USE_MONOTONIC
|
54
66
|
# define EV_USE_MONOTONIC 1
|
@@ -156,6 +168,7 @@ extern "C" {
|
|
156
168
|
# include <sys/wait.h>
|
157
169
|
# include <unistd.h>
|
158
170
|
#else
|
171
|
+
# include <io.h>
|
159
172
|
# define WIN32_LEAN_AND_MEAN
|
160
173
|
# include <windows.h>
|
161
174
|
# ifndef EV_SELECT_IS_WINSOCKET
|
@@ -165,8 +178,20 @@ extern "C" {
|
|
165
178
|
|
166
179
|
/* this block tries to deduce configuration from header-defined symbols and defaults */
|
167
180
|
|
181
|
+
#ifndef EV_USE_CLOCK_SYSCALL
|
182
|
+
# if __linux && __GLIBC__ >= 2
|
183
|
+
# define EV_USE_CLOCK_SYSCALL 1
|
184
|
+
# else
|
185
|
+
# define EV_USE_CLOCK_SYSCALL 0
|
186
|
+
# endif
|
187
|
+
#endif
|
188
|
+
|
168
189
|
#ifndef EV_USE_MONOTONIC
|
169
|
-
#
|
190
|
+
# if defined (_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0
|
191
|
+
# define EV_USE_MONOTONIC 1
|
192
|
+
# else
|
193
|
+
# define EV_USE_MONOTONIC 0
|
194
|
+
# endif
|
170
195
|
#endif
|
171
196
|
|
172
197
|
#ifndef EV_USE_REALTIME
|
@@ -174,7 +199,11 @@ extern "C" {
|
|
174
199
|
#endif
|
175
200
|
|
176
201
|
#ifndef EV_USE_NANOSLEEP
|
177
|
-
#
|
202
|
+
# if _POSIX_C_SOURCE >= 199309L
|
203
|
+
# define EV_USE_NANOSLEEP 1
|
204
|
+
# else
|
205
|
+
# define EV_USE_NANOSLEEP 0
|
206
|
+
# endif
|
178
207
|
#endif
|
179
208
|
|
180
209
|
#ifndef EV_USE_SELECT
|
@@ -279,13 +308,29 @@ extern "C" {
|
|
279
308
|
#endif
|
280
309
|
|
281
310
|
#if EV_USE_INOTIFY
|
311
|
+
# include <sys/utsname.h>
|
312
|
+
# include <sys/statfs.h>
|
282
313
|
# include <sys/inotify.h>
|
314
|
+
/* some very old inotify.h headers don't have IN_DONT_FOLLOW */
|
315
|
+
# ifndef IN_DONT_FOLLOW
|
316
|
+
# undef EV_USE_INOTIFY
|
317
|
+
# define EV_USE_INOTIFY 0
|
318
|
+
# endif
|
283
319
|
#endif
|
284
320
|
|
285
321
|
#if EV_SELECT_IS_WINSOCKET
|
286
322
|
# include <winsock.h>
|
287
323
|
#endif
|
288
324
|
|
325
|
+
/* on linux, we can use a (slow) syscall to avoid a dependency on pthread, */
|
326
|
+
/* which makes programs even slower. might work on other unices, too. */
|
327
|
+
#if EV_USE_CLOCK_SYSCALL
|
328
|
+
# include <syscall.h>
|
329
|
+
# define clock_gettime(id, ts) syscall (SYS_clock_gettime, (id), (ts))
|
330
|
+
# undef EV_USE_MONOTONIC
|
331
|
+
# define EV_USE_MONOTONIC 1
|
332
|
+
#endif
|
333
|
+
|
289
334
|
#if EV_USE_EVENTFD
|
290
335
|
/* our minimum requirement is glibc 2.7 which has the stub, but not the header */
|
291
336
|
# include <stdint.h>
|
@@ -375,7 +420,7 @@ ev_set_syserr_cb (void (*cb)(const char *msg))
|
|
375
420
|
}
|
376
421
|
|
377
422
|
static void noinline
|
378
|
-
|
423
|
+
ev_syserr (const char *msg)
|
379
424
|
{
|
380
425
|
if (!msg)
|
381
426
|
msg = "(libev) system error";
|
@@ -436,6 +481,11 @@ typedef struct
|
|
436
481
|
WL head;
|
437
482
|
unsigned char events;
|
438
483
|
unsigned char reify;
|
484
|
+
unsigned char emask; /* the epoll backend stores the actual kernel mask in here */
|
485
|
+
unsigned char unused;
|
486
|
+
#if EV_USE_EPOLL
|
487
|
+
unsigned int egen; /* generation counter to counter epoll bugs */
|
488
|
+
#endif
|
439
489
|
#if EV_SELECT_IS_WINSOCKET
|
440
490
|
SOCKET handle;
|
441
491
|
#endif
|
@@ -558,6 +608,9 @@ ev_sleep (ev_tstamp delay)
|
|
558
608
|
tv.tv_sec = (time_t)delay;
|
559
609
|
tv.tv_usec = (long)((delay - (ev_tstamp)(tv.tv_sec)) * 1e6);
|
560
610
|
|
611
|
+
/* here we rely on sys/time.h + sys/types.h + unistd.h providing select */
|
612
|
+
/* somehting nto guaranteed by newer posix versions, but guaranteed */
|
613
|
+
/* by older ones */
|
561
614
|
select (0, 0, 0, 0, &tv);
|
562
615
|
#endif
|
563
616
|
}
|
@@ -595,6 +648,9 @@ array_realloc (int elem, void *base, int *cur, int cnt)
|
|
595
648
|
return ev_realloc (base, elem * *cur);
|
596
649
|
}
|
597
650
|
|
651
|
+
#define array_init_zero(base,count) \
|
652
|
+
memset ((void *)(base), 0, sizeof (*(base)) * (count))
|
653
|
+
|
598
654
|
#define array_needsize(type,base,cur,cnt,init) \
|
599
655
|
if (expect_false ((cnt) > (cur))) \
|
600
656
|
{ \
|
@@ -647,19 +703,6 @@ queue_events (EV_P_ W *events, int eventcnt, int type)
|
|
647
703
|
|
648
704
|
/*****************************************************************************/
|
649
705
|
|
650
|
-
void inline_size
|
651
|
-
anfds_init (ANFD *base, int count)
|
652
|
-
{
|
653
|
-
while (count--)
|
654
|
-
{
|
655
|
-
base->head = 0;
|
656
|
-
base->events = EV_NONE;
|
657
|
-
base->reify = 0;
|
658
|
-
|
659
|
-
++base;
|
660
|
-
}
|
661
|
-
}
|
662
|
-
|
663
706
|
void inline_speed
|
664
707
|
fd_event (EV_P_ int fd, int revents)
|
665
708
|
{
|
@@ -701,13 +744,13 @@ fd_reify (EV_P)
|
|
701
744
|
#if EV_SELECT_IS_WINSOCKET
|
702
745
|
if (events)
|
703
746
|
{
|
704
|
-
unsigned long
|
747
|
+
unsigned long arg;
|
705
748
|
#ifdef EV_FD_TO_WIN32_HANDLE
|
706
749
|
anfd->handle = EV_FD_TO_WIN32_HANDLE (fd);
|
707
750
|
#else
|
708
751
|
anfd->handle = _get_osfhandle (fd);
|
709
752
|
#endif
|
710
|
-
assert (("libev only
|
753
|
+
assert (("libev: only socket fds supported in this configuration", ioctlsocket (anfd->handle, FIONREAD, &arg) == 0));
|
711
754
|
}
|
712
755
|
#endif
|
713
756
|
|
@@ -770,7 +813,7 @@ fd_ebadf (EV_P)
|
|
770
813
|
|
771
814
|
for (fd = 0; fd < anfdmax; ++fd)
|
772
815
|
if (anfds [fd].events)
|
773
|
-
if (!fd_valid (fd)
|
816
|
+
if (!fd_valid (fd) && errno == EBADF)
|
774
817
|
fd_kill (EV_A_ fd);
|
775
818
|
}
|
776
819
|
|
@@ -798,6 +841,7 @@ fd_rearm_all (EV_P)
|
|
798
841
|
if (anfds [fd].events)
|
799
842
|
{
|
800
843
|
anfds [fd].events = 0;
|
844
|
+
anfds [fd].emask = 0;
|
801
845
|
fd_change (EV_A_ fd, EV_IOFDSET | 1);
|
802
846
|
}
|
803
847
|
}
|
@@ -959,25 +1003,13 @@ static int signalmax;
|
|
959
1003
|
|
960
1004
|
static EV_ATOMIC_T gotsig;
|
961
1005
|
|
962
|
-
void inline_size
|
963
|
-
signals_init (ANSIG *base, int count)
|
964
|
-
{
|
965
|
-
while (count--)
|
966
|
-
{
|
967
|
-
base->head = 0;
|
968
|
-
base->gotsig = 0;
|
969
|
-
|
970
|
-
++base;
|
971
|
-
}
|
972
|
-
}
|
973
|
-
|
974
1006
|
/*****************************************************************************/
|
975
1007
|
|
976
1008
|
void inline_speed
|
977
1009
|
fd_intern (int fd)
|
978
1010
|
{
|
979
1011
|
#ifdef _WIN32
|
980
|
-
|
1012
|
+
unsigned long arg = 1;
|
981
1013
|
ioctlsocket (_get_osfhandle (fd), FIONBIO, &arg);
|
982
1014
|
#else
|
983
1015
|
fcntl (fd, F_SETFD, FD_CLOEXEC);
|
@@ -1001,7 +1033,7 @@ evpipe_init (EV_P)
|
|
1001
1033
|
#endif
|
1002
1034
|
{
|
1003
1035
|
while (pipe (evpipe))
|
1004
|
-
|
1036
|
+
ev_syserr ("(libev) error creating signal/async pipe");
|
1005
1037
|
|
1006
1038
|
fd_intern (evpipe [0]);
|
1007
1039
|
fd_intern (evpipe [1]);
|
@@ -1101,7 +1133,7 @@ ev_feed_signal_event (EV_P_ int signum)
|
|
1101
1133
|
WL w;
|
1102
1134
|
|
1103
1135
|
#if EV_MULTIPLICITY
|
1104
|
-
assert (("feeding signal events is only supported in the default loop", loop == ev_default_loop_ptr));
|
1136
|
+
assert (("libev: feeding signal events is only supported in the default loop", loop == ev_default_loop_ptr));
|
1105
1137
|
#endif
|
1106
1138
|
|
1107
1139
|
--signum;
|
@@ -1240,8 +1272,9 @@ ev_recommended_backends (void)
|
|
1240
1272
|
flags &= ~EVBACKEND_KQUEUE;
|
1241
1273
|
#endif
|
1242
1274
|
#ifdef __APPLE__
|
1243
|
-
|
1244
|
-
flags &= ~
|
1275
|
+
/* only select works correctly on that "unix-certified" platform */
|
1276
|
+
flags &= ~EVBACKEND_KQUEUE; /* horribly broken, even for sockets */
|
1277
|
+
flags &= ~EVBACKEND_POLL; /* poll is based on kqueue from 10.5 onwards */
|
1245
1278
|
#endif
|
1246
1279
|
|
1247
1280
|
return flags;
|
@@ -1501,13 +1534,13 @@ ev_loop_fork (EV_P)
|
|
1501
1534
|
}
|
1502
1535
|
|
1503
1536
|
#if EV_VERIFY
|
1504
|
-
void noinline
|
1537
|
+
static void noinline
|
1505
1538
|
verify_watcher (EV_P_ W w)
|
1506
1539
|
{
|
1507
|
-
assert (("watcher has invalid priority", ABSPRI (w) >= 0 && ABSPRI (w) < NUMPRI));
|
1540
|
+
assert (("libev: watcher has invalid priority", ABSPRI (w) >= 0 && ABSPRI (w) < NUMPRI));
|
1508
1541
|
|
1509
1542
|
if (w->pending)
|
1510
|
-
assert (("pending watcher not on pending queue", pendings [ABSPRI (w)][w->pending - 1].w == w));
|
1543
|
+
assert (("libev: pending watcher not on pending queue", pendings [ABSPRI (w)][w->pending - 1].w == w));
|
1511
1544
|
}
|
1512
1545
|
|
1513
1546
|
static void noinline
|
@@ -1517,9 +1550,9 @@ verify_heap (EV_P_ ANHE *heap, int N)
|
|
1517
1550
|
|
1518
1551
|
for (i = HEAP0; i < N + HEAP0; ++i)
|
1519
1552
|
{
|
1520
|
-
assert (("active index mismatch in heap", ev_active (ANHE_w (heap [i])) == i));
|
1521
|
-
assert (("heap condition violated", i == HEAP0 || ANHE_at (heap [HPARENT (i)]) <= ANHE_at (heap [i])));
|
1522
|
-
assert (("heap at cache mismatch", ANHE_at (heap [i]) == ev_at (ANHE_w (heap [i]))));
|
1553
|
+
assert (("libev: active index mismatch in heap", ev_active (ANHE_w (heap [i])) == i));
|
1554
|
+
assert (("libev: heap condition violated", i == HEAP0 || ANHE_at (heap [HPARENT (i)]) <= ANHE_at (heap [i])));
|
1555
|
+
assert (("libev: heap at cache mismatch", ANHE_at (heap [i]) == ev_at (ANHE_w (heap [i]))));
|
1523
1556
|
|
1524
1557
|
verify_watcher (EV_A_ (W)ANHE_w (heap [i]));
|
1525
1558
|
}
|
@@ -1530,7 +1563,7 @@ array_verify (EV_P_ W *ws, int cnt)
|
|
1530
1563
|
{
|
1531
1564
|
while (cnt--)
|
1532
1565
|
{
|
1533
|
-
assert (("active index mismatch", ev_active (ws [cnt]) == cnt + 1));
|
1566
|
+
assert (("libev: active index mismatch", ev_active (ws [cnt]) == cnt + 1));
|
1534
1567
|
verify_watcher (EV_A_ ws [cnt]);
|
1535
1568
|
}
|
1536
1569
|
}
|
@@ -1547,15 +1580,15 @@ ev_loop_verify (EV_P)
|
|
1547
1580
|
|
1548
1581
|
assert (fdchangemax >= fdchangecnt);
|
1549
1582
|
for (i = 0; i < fdchangecnt; ++i)
|
1550
|
-
assert (("negative fd in fdchanges", fdchanges [i] >= 0));
|
1583
|
+
assert (("libev: negative fd in fdchanges", fdchanges [i] >= 0));
|
1551
1584
|
|
1552
1585
|
assert (anfdmax >= 0);
|
1553
1586
|
for (i = 0; i < anfdmax; ++i)
|
1554
1587
|
for (w = anfds [i].head; w; w = w->next)
|
1555
1588
|
{
|
1556
1589
|
verify_watcher (EV_A_ (W)w);
|
1557
|
-
assert (("inactive fd watcher on anfd list", ev_active (w) == 1));
|
1558
|
-
assert (("fd mismatch between watcher and anfd", ((ev_io *)w)->fd == i));
|
1590
|
+
assert (("libev: inactive fd watcher on anfd list", ev_active (w) == 1));
|
1591
|
+
assert (("libev: fd mismatch between watcher and anfd", ((ev_io *)w)->fd == i));
|
1559
1592
|
}
|
1560
1593
|
|
1561
1594
|
assert (timermax >= timercnt);
|
@@ -1642,6 +1675,8 @@ ev_default_destroy (void)
|
|
1642
1675
|
struct ev_loop *loop = ev_default_loop_ptr;
|
1643
1676
|
#endif
|
1644
1677
|
|
1678
|
+
ev_default_loop_ptr = 0;
|
1679
|
+
|
1645
1680
|
#ifndef _WIN32
|
1646
1681
|
ev_ref (EV_A); /* child watcher */
|
1647
1682
|
ev_signal_stop (EV_A_ &childev);
|
@@ -1657,8 +1692,7 @@ ev_default_fork (void)
|
|
1657
1692
|
struct ev_loop *loop = ev_default_loop_ptr;
|
1658
1693
|
#endif
|
1659
1694
|
|
1660
|
-
|
1661
|
-
postfork = 1; /* must be in line with ev_loop_fork */
|
1695
|
+
postfork = 1; /* must be in line with ev_loop_fork */
|
1662
1696
|
}
|
1663
1697
|
|
1664
1698
|
/*****************************************************************************/
|
@@ -1681,7 +1715,7 @@ call_pending (EV_P)
|
|
1681
1715
|
|
1682
1716
|
if (expect_true (p->w))
|
1683
1717
|
{
|
1684
|
-
/*assert (("non-pending watcher on pending list", p->w->pending));*/
|
1718
|
+
/*assert (("libev: non-pending watcher on pending list", p->w->pending));*/
|
1685
1719
|
|
1686
1720
|
p->w->pending = 0;
|
1687
1721
|
EV_CB_INVOKE (p->w, p->events);
|
@@ -1722,7 +1756,7 @@ timers_reify (EV_P)
|
|
1722
1756
|
{
|
1723
1757
|
ev_timer *w = (ev_timer *)ANHE_w (timers [HEAP0]);
|
1724
1758
|
|
1725
|
-
/*assert (("inactive timer on timer heap detected", ev_is_active (w)));*/
|
1759
|
+
/*assert (("libev: inactive timer on timer heap detected", ev_is_active (w)));*/
|
1726
1760
|
|
1727
1761
|
/* first reschedule or stop timer */
|
1728
1762
|
if (w->repeat)
|
@@ -1731,7 +1765,7 @@ timers_reify (EV_P)
|
|
1731
1765
|
if (ev_at (w) < mn_now)
|
1732
1766
|
ev_at (w) = mn_now;
|
1733
1767
|
|
1734
|
-
assert (("negative ev_timer repeat value found while processing timers", w->repeat > 0.));
|
1768
|
+
assert (("libev: negative ev_timer repeat value found while processing timers", w->repeat > 0.));
|
1735
1769
|
|
1736
1770
|
ANHE_at_cache (timers [HEAP0]);
|
1737
1771
|
downheap (timers, timercnt, HEAP0);
|
@@ -1754,14 +1788,14 @@ periodics_reify (EV_P)
|
|
1754
1788
|
{
|
1755
1789
|
ev_periodic *w = (ev_periodic *)ANHE_w (periodics [HEAP0]);
|
1756
1790
|
|
1757
|
-
/*assert (("inactive timer on periodic heap detected", ev_is_active (w)));*/
|
1791
|
+
/*assert (("libev: inactive timer on periodic heap detected", ev_is_active (w)));*/
|
1758
1792
|
|
1759
1793
|
/* first reschedule or stop timer */
|
1760
1794
|
if (w->reschedule_cb)
|
1761
1795
|
{
|
1762
1796
|
ev_at (w) = w->reschedule_cb (w, ev_rt_now);
|
1763
1797
|
|
1764
|
-
assert (("ev_periodic reschedule callback returned time in the past", ev_at (w) >= ev_rt_now));
|
1798
|
+
assert (("libev: ev_periodic reschedule callback returned time in the past", ev_at (w) >= ev_rt_now));
|
1765
1799
|
|
1766
1800
|
ANHE_at_cache (periodics [HEAP0]);
|
1767
1801
|
downheap (periodics, periodiccnt, HEAP0);
|
@@ -1899,6 +1933,12 @@ ev_unref (EV_P)
|
|
1899
1933
|
--activecnt;
|
1900
1934
|
}
|
1901
1935
|
|
1936
|
+
void
|
1937
|
+
ev_now_update (EV_P)
|
1938
|
+
{
|
1939
|
+
time_update (EV_A_ 1e100);
|
1940
|
+
}
|
1941
|
+
|
1902
1942
|
static int loop_done;
|
1903
1943
|
|
1904
1944
|
void
|
@@ -2116,12 +2156,13 @@ ev_io_start (EV_P_ ev_io *w)
|
|
2116
2156
|
if (expect_false (ev_is_active (w)))
|
2117
2157
|
return;
|
2118
2158
|
|
2119
|
-
assert (("ev_io_start called with negative fd", fd >= 0));
|
2159
|
+
assert (("libev: ev_io_start called with negative fd", fd >= 0));
|
2160
|
+
assert (("libev: ev_io start called with illegal event mask", !(w->events & ~(EV_IOFDSET | EV_READ | EV_WRITE))));
|
2120
2161
|
|
2121
2162
|
EV_FREQUENT_CHECK;
|
2122
2163
|
|
2123
2164
|
ev_start (EV_A_ (W)w, 1);
|
2124
|
-
array_needsize (ANFD, anfds, anfdmax, fd + 1,
|
2165
|
+
array_needsize (ANFD, anfds, anfdmax, fd + 1, array_init_zero);
|
2125
2166
|
wlist_add (&anfds[fd].head, (WL)w);
|
2126
2167
|
|
2127
2168
|
fd_change (EV_A_ fd, w->events & EV_IOFDSET | 1);
|
@@ -2137,7 +2178,7 @@ ev_io_stop (EV_P_ ev_io *w)
|
|
2137
2178
|
if (expect_false (!ev_is_active (w)))
|
2138
2179
|
return;
|
2139
2180
|
|
2140
|
-
assert (("ev_io_stop called with illegal fd (must stay constant after start!)", w->fd >= 0 && w->fd < anfdmax));
|
2181
|
+
assert (("libev: ev_io_stop called with illegal fd (must stay constant after start!)", w->fd >= 0 && w->fd < anfdmax));
|
2141
2182
|
|
2142
2183
|
EV_FREQUENT_CHECK;
|
2143
2184
|
|
@@ -2157,7 +2198,7 @@ ev_timer_start (EV_P_ ev_timer *w)
|
|
2157
2198
|
|
2158
2199
|
ev_at (w) += mn_now;
|
2159
2200
|
|
2160
|
-
assert (("ev_timer_start called with negative timer repeat value", w->repeat >= 0.));
|
2201
|
+
assert (("libev: ev_timer_start called with negative timer repeat value", w->repeat >= 0.));
|
2161
2202
|
|
2162
2203
|
EV_FREQUENT_CHECK;
|
2163
2204
|
|
@@ -2170,7 +2211,7 @@ ev_timer_start (EV_P_ ev_timer *w)
|
|
2170
2211
|
|
2171
2212
|
EV_FREQUENT_CHECK;
|
2172
2213
|
|
2173
|
-
/*assert (("internal timer heap corruption", timers [ev_active (w)] == (WT)w));*/
|
2214
|
+
/*assert (("libev: internal timer heap corruption", timers [ev_active (w)] == (WT)w));*/
|
2174
2215
|
}
|
2175
2216
|
|
2176
2217
|
void noinline
|
@@ -2185,7 +2226,7 @@ ev_timer_stop (EV_P_ ev_timer *w)
|
|
2185
2226
|
{
|
2186
2227
|
int active = ev_active (w);
|
2187
2228
|
|
2188
|
-
assert (("internal timer heap corruption", ANHE_w (timers [active]) == (WT)w));
|
2229
|
+
assert (("libev: internal timer heap corruption", ANHE_w (timers [active]) == (WT)w));
|
2189
2230
|
|
2190
2231
|
--timercnt;
|
2191
2232
|
|
@@ -2239,7 +2280,7 @@ ev_periodic_start (EV_P_ ev_periodic *w)
|
|
2239
2280
|
ev_at (w) = w->reschedule_cb (w, ev_rt_now);
|
2240
2281
|
else if (w->interval)
|
2241
2282
|
{
|
2242
|
-
assert (("ev_periodic_start called with negative interval value", w->interval >= 0.));
|
2283
|
+
assert (("libev: ev_periodic_start called with negative interval value", w->interval >= 0.));
|
2243
2284
|
/* this formula differs from the one in periodic_reify because we do not always round up */
|
2244
2285
|
ev_at (w) = w->offset + ceil ((ev_rt_now - w->offset) / w->interval) * w->interval;
|
2245
2286
|
}
|
@@ -2257,7 +2298,7 @@ ev_periodic_start (EV_P_ ev_periodic *w)
|
|
2257
2298
|
|
2258
2299
|
EV_FREQUENT_CHECK;
|
2259
2300
|
|
2260
|
-
/*assert (("internal periodic heap corruption", ANHE_w (periodics [ev_active (w)]) == (WT)w));*/
|
2301
|
+
/*assert (("libev: internal periodic heap corruption", ANHE_w (periodics [ev_active (w)]) == (WT)w));*/
|
2261
2302
|
}
|
2262
2303
|
|
2263
2304
|
void noinline
|
@@ -2272,7 +2313,7 @@ ev_periodic_stop (EV_P_ ev_periodic *w)
|
|
2272
2313
|
{
|
2273
2314
|
int active = ev_active (w);
|
2274
2315
|
|
2275
|
-
assert (("internal periodic heap corruption", ANHE_w (periodics [active]) == (WT)w));
|
2316
|
+
assert (("libev: internal periodic heap corruption", ANHE_w (periodics [active]) == (WT)w));
|
2276
2317
|
|
2277
2318
|
--periodiccnt;
|
2278
2319
|
|
@@ -2305,12 +2346,12 @@ void noinline
|
|
2305
2346
|
ev_signal_start (EV_P_ ev_signal *w)
|
2306
2347
|
{
|
2307
2348
|
#if EV_MULTIPLICITY
|
2308
|
-
assert (("signal watchers are only supported in the default loop", loop == ev_default_loop_ptr));
|
2349
|
+
assert (("libev: signal watchers are only supported in the default loop", loop == ev_default_loop_ptr));
|
2309
2350
|
#endif
|
2310
2351
|
if (expect_false (ev_is_active (w)))
|
2311
2352
|
return;
|
2312
2353
|
|
2313
|
-
assert (("ev_signal_start called with illegal signal number", w->signum > 0));
|
2354
|
+
assert (("libev: ev_signal_start called with illegal signal number", w->signum > 0));
|
2314
2355
|
|
2315
2356
|
evpipe_init (EV_A);
|
2316
2357
|
|
@@ -2323,7 +2364,7 @@ ev_signal_start (EV_P_ ev_signal *w)
|
|
2323
2364
|
sigprocmask (SIG_SETMASK, &full, &prev);
|
2324
2365
|
#endif
|
2325
2366
|
|
2326
|
-
array_needsize (ANSIG, signals, signalmax, w->signum,
|
2367
|
+
array_needsize (ANSIG, signals, signalmax, w->signum, array_init_zero);
|
2327
2368
|
|
2328
2369
|
#ifndef _WIN32
|
2329
2370
|
sigprocmask (SIG_SETMASK, &prev, 0);
|
@@ -2371,7 +2412,7 @@ void
|
|
2371
2412
|
ev_child_start (EV_P_ ev_child *w)
|
2372
2413
|
{
|
2373
2414
|
#if EV_MULTIPLICITY
|
2374
|
-
assert (("child watchers are only supported in the default loop", loop == ev_default_loop_ptr));
|
2415
|
+
assert (("libev: child watchers are only supported in the default loop", loop == ev_default_loop_ptr));
|
2375
2416
|
#endif
|
2376
2417
|
if (expect_false (ev_is_active (w)))
|
2377
2418
|
return;
|
@@ -2406,8 +2447,9 @@ ev_child_stop (EV_P_ ev_child *w)
|
|
2406
2447
|
# define lstat(a,b) _stati64 (a,b)
|
2407
2448
|
# endif
|
2408
2449
|
|
2409
|
-
#define DEF_STAT_INTERVAL
|
2410
|
-
#define
|
2450
|
+
#define DEF_STAT_INTERVAL 5.0074891
|
2451
|
+
#define NFS_STAT_INTERVAL 30.1074891 /* for filesystems potentially failing inotify */
|
2452
|
+
#define MIN_STAT_INTERVAL 0.1074891
|
2411
2453
|
|
2412
2454
|
static void noinline stat_timer_cb (EV_P_ ev_timer *w_, int revents);
|
2413
2455
|
|
@@ -2421,10 +2463,11 @@ infy_add (EV_P_ ev_stat *w)
|
|
2421
2463
|
|
2422
2464
|
if (w->wd < 0)
|
2423
2465
|
{
|
2424
|
-
|
2466
|
+
w->timer.repeat = w->interval ? w->interval : DEF_STAT_INTERVAL;
|
2467
|
+
ev_timer_again (EV_A_ &w->timer); /* this is not race-free, so we still need to recheck periodically */
|
2425
2468
|
|
2426
2469
|
/* monitor some parent directory for speedup hints */
|
2427
|
-
/* note that exceeding the hardcoded limit is not a correctness issue, */
|
2470
|
+
/* note that exceeding the hardcoded path limit is not a correctness issue, */
|
2428
2471
|
/* but an efficiency issue only */
|
2429
2472
|
if ((errno == ENOENT || errno == EACCES) && strlen (w->path) < 4096)
|
2430
2473
|
{
|
@@ -2438,8 +2481,8 @@ infy_add (EV_P_ ev_stat *w)
|
|
2438
2481
|
|
2439
2482
|
char *pend = strrchr (path, '/');
|
2440
2483
|
|
2441
|
-
if (!pend)
|
2442
|
-
break;
|
2484
|
+
if (!pend || pend == path)
|
2485
|
+
break;
|
2443
2486
|
|
2444
2487
|
*pend = 0;
|
2445
2488
|
w->wd = inotify_add_watch (fs_fd, path, mask);
|
@@ -2447,11 +2490,28 @@ infy_add (EV_P_ ev_stat *w)
|
|
2447
2490
|
while (w->wd < 0 && (errno == ENOENT || errno == EACCES));
|
2448
2491
|
}
|
2449
2492
|
}
|
2450
|
-
else
|
2451
|
-
ev_timer_stop (EV_A_ &w->timer); /* we can watch this in a race-free way */
|
2452
2493
|
|
2453
2494
|
if (w->wd >= 0)
|
2454
|
-
|
2495
|
+
{
|
2496
|
+
wlist_add (&fs_hash [w->wd & (EV_INOTIFY_HASHSIZE - 1)].head, (WL)w);
|
2497
|
+
|
2498
|
+
/* now local changes will be tracked by inotify, but remote changes won't */
|
2499
|
+
/* unless the filesystem it known to be local, we therefore still poll */
|
2500
|
+
/* also do poll on <2.6.25, but with normal frequency */
|
2501
|
+
struct statfs sfs;
|
2502
|
+
|
2503
|
+
if (fs_2625 && !statfs (w->path, &sfs))
|
2504
|
+
if (sfs.f_type == 0x1373 /* devfs */
|
2505
|
+
|| sfs.f_type == 0xEF53 /* ext2/3 */
|
2506
|
+
|| sfs.f_type == 0x3153464a /* jfs */
|
2507
|
+
|| sfs.f_type == 0x52654973 /* reiser3 */
|
2508
|
+
|| sfs.f_type == 0x01021994 /* tempfs */
|
2509
|
+
|| sfs.f_type == 0x58465342 /* xfs */)
|
2510
|
+
return;
|
2511
|
+
|
2512
|
+
w->timer.repeat = w->interval ? w->interval : fs_2625 ? NFS_STAT_INTERVAL : DEF_STAT_INTERVAL;
|
2513
|
+
ev_timer_again (EV_A_ &w->timer);
|
2514
|
+
}
|
2455
2515
|
}
|
2456
2516
|
|
2457
2517
|
static void noinline
|
@@ -2475,7 +2535,7 @@ static void noinline
|
|
2475
2535
|
infy_wd (EV_P_ int slot, int wd, struct inotify_event *ev)
|
2476
2536
|
{
|
2477
2537
|
if (slot < 0)
|
2478
|
-
/* overflow, need to check for all
|
2538
|
+
/* overflow, need to check for all hash slots */
|
2479
2539
|
for (slot = 0; slot < EV_INOTIFY_HASHSIZE; ++slot)
|
2480
2540
|
infy_wd (EV_A_ slot, wd, ev);
|
2481
2541
|
else
|
@@ -2491,6 +2551,7 @@ infy_wd (EV_P_ int slot, int wd, struct inotify_event *ev)
|
|
2491
2551
|
{
|
2492
2552
|
if (ev->mask & (IN_IGNORED | IN_UNMOUNT | IN_DELETE_SELF))
|
2493
2553
|
{
|
2554
|
+
wlist_del (&fs_hash [slot & (EV_INOTIFY_HASHSIZE - 1)].head, (WL)w);
|
2494
2555
|
w->wd = -1;
|
2495
2556
|
infy_add (EV_A_ w); /* re-add, no matter what */
|
2496
2557
|
}
|
@@ -2513,12 +2574,39 @@ infy_cb (EV_P_ ev_io *w, int revents)
|
|
2513
2574
|
infy_wd (EV_A_ ev->wd, ev->wd, ev);
|
2514
2575
|
}
|
2515
2576
|
|
2577
|
+
void inline_size
|
2578
|
+
check_2625 (EV_P)
|
2579
|
+
{
|
2580
|
+
/* kernels < 2.6.25 are borked
|
2581
|
+
* http://www.ussg.indiana.edu/hypermail/linux/kernel/0711.3/1208.html
|
2582
|
+
*/
|
2583
|
+
struct utsname buf;
|
2584
|
+
int major, minor, micro;
|
2585
|
+
|
2586
|
+
if (uname (&buf))
|
2587
|
+
return;
|
2588
|
+
|
2589
|
+
if (sscanf (buf.release, "%d.%d.%d", &major, &minor, µ) != 3)
|
2590
|
+
return;
|
2591
|
+
|
2592
|
+
if (major < 2
|
2593
|
+
|| (major == 2 && minor < 6)
|
2594
|
+
|| (major == 2 && minor == 6 && micro < 25))
|
2595
|
+
return;
|
2596
|
+
|
2597
|
+
fs_2625 = 1;
|
2598
|
+
}
|
2599
|
+
|
2516
2600
|
void inline_size
|
2517
2601
|
infy_init (EV_P)
|
2518
2602
|
{
|
2519
2603
|
if (fs_fd != -2)
|
2520
2604
|
return;
|
2521
2605
|
|
2606
|
+
fs_fd = -1;
|
2607
|
+
|
2608
|
+
check_2625 (EV_A);
|
2609
|
+
|
2522
2610
|
fs_fd = inotify_init ();
|
2523
2611
|
|
2524
2612
|
if (fs_fd >= 0)
|
@@ -2555,14 +2643,19 @@ infy_fork (EV_P)
|
|
2555
2643
|
if (fs_fd >= 0)
|
2556
2644
|
infy_add (EV_A_ w); /* re-add, no matter what */
|
2557
2645
|
else
|
2558
|
-
|
2646
|
+
ev_timer_again (EV_A_ &w->timer);
|
2559
2647
|
}
|
2560
|
-
|
2561
2648
|
}
|
2562
2649
|
}
|
2563
2650
|
|
2564
2651
|
#endif
|
2565
2652
|
|
2653
|
+
#ifdef _WIN32
|
2654
|
+
# define EV_LSTAT(p,b) _stati64 (p, b)
|
2655
|
+
#else
|
2656
|
+
# define EV_LSTAT(p,b) lstat (p, b)
|
2657
|
+
#endif
|
2658
|
+
|
2566
2659
|
void
|
2567
2660
|
ev_stat_stat (EV_P_ ev_stat *w)
|
2568
2661
|
{
|
@@ -2597,9 +2690,12 @@ stat_timer_cb (EV_P_ ev_timer *w_, int revents)
|
|
2597
2690
|
|| w->prev.st_ctime != w->attr.st_ctime
|
2598
2691
|
) {
|
2599
2692
|
#if EV_USE_INOTIFY
|
2600
|
-
|
2601
|
-
|
2602
|
-
|
2693
|
+
if (fs_fd >= 0)
|
2694
|
+
{
|
2695
|
+
infy_del (EV_A_ w);
|
2696
|
+
infy_add (EV_A_ w);
|
2697
|
+
ev_stat_stat (EV_A_ w); /* avoid race... */
|
2698
|
+
}
|
2603
2699
|
#endif
|
2604
2700
|
|
2605
2701
|
ev_feed_event (EV_A_ w, EV_STAT);
|
@@ -2612,16 +2708,12 @@ ev_stat_start (EV_P_ ev_stat *w)
|
|
2612
2708
|
if (expect_false (ev_is_active (w)))
|
2613
2709
|
return;
|
2614
2710
|
|
2615
|
-
/* since we use memcmp, we need to clear any padding data etc. */
|
2616
|
-
memset (&w->prev, 0, sizeof (ev_statdata));
|
2617
|
-
memset (&w->attr, 0, sizeof (ev_statdata));
|
2618
|
-
|
2619
2711
|
ev_stat_stat (EV_A_ w);
|
2620
2712
|
|
2621
|
-
if (w->interval < MIN_STAT_INTERVAL)
|
2622
|
-
w->interval =
|
2713
|
+
if (w->interval < MIN_STAT_INTERVAL && w->interval)
|
2714
|
+
w->interval = MIN_STAT_INTERVAL;
|
2623
2715
|
|
2624
|
-
ev_timer_init (&w->timer, stat_timer_cb, w->interval
|
2716
|
+
ev_timer_init (&w->timer, stat_timer_cb, 0., w->interval ? w->interval : DEF_STAT_INTERVAL);
|
2625
2717
|
ev_set_priority (&w->timer, ev_priority (w));
|
2626
2718
|
|
2627
2719
|
#if EV_USE_INOTIFY
|
@@ -2631,7 +2723,7 @@ ev_stat_start (EV_P_ ev_stat *w)
|
|
2631
2723
|
infy_add (EV_A_ w);
|
2632
2724
|
else
|
2633
2725
|
#endif
|
2634
|
-
|
2726
|
+
ev_timer_again (EV_A_ &w->timer);
|
2635
2727
|
|
2636
2728
|
ev_start (EV_A_ (W)w, 1);
|
2637
2729
|
|
@@ -2811,6 +2903,23 @@ embed_prepare_cb (EV_P_ ev_prepare *prepare, int revents)
|
|
2811
2903
|
}
|
2812
2904
|
}
|
2813
2905
|
|
2906
|
+
static void
|
2907
|
+
embed_fork_cb (EV_P_ ev_fork *fork_w, int revents)
|
2908
|
+
{
|
2909
|
+
ev_embed *w = (ev_embed *)(((char *)fork_w) - offsetof (ev_embed, fork));
|
2910
|
+
|
2911
|
+
ev_embed_stop (EV_A_ w);
|
2912
|
+
|
2913
|
+
{
|
2914
|
+
struct ev_loop *loop = w->other;
|
2915
|
+
|
2916
|
+
ev_loop_fork (EV_A);
|
2917
|
+
ev_loop (EV_A_ EVLOOP_NONBLOCK);
|
2918
|
+
}
|
2919
|
+
|
2920
|
+
ev_embed_start (EV_A_ w);
|
2921
|
+
}
|
2922
|
+
|
2814
2923
|
#if 0
|
2815
2924
|
static void
|
2816
2925
|
embed_idle_cb (EV_P_ ev_idle *idle, int revents)
|
@@ -2827,7 +2936,7 @@ ev_embed_start (EV_P_ ev_embed *w)
|
|
2827
2936
|
|
2828
2937
|
{
|
2829
2938
|
struct ev_loop *loop = w->other;
|
2830
|
-
assert (("loop to be embedded is not embeddable", backend & ev_embeddable_backends ()));
|
2939
|
+
assert (("libev: loop to be embedded is not embeddable", backend & ev_embeddable_backends ()));
|
2831
2940
|
ev_io_init (&w->io, embed_io_cb, backend_fd, EV_READ);
|
2832
2941
|
}
|
2833
2942
|
|
@@ -2840,6 +2949,9 @@ ev_embed_start (EV_P_ ev_embed *w)
|
|
2840
2949
|
ev_set_priority (&w->prepare, EV_MINPRI);
|
2841
2950
|
ev_prepare_start (EV_A_ &w->prepare);
|
2842
2951
|
|
2952
|
+
ev_fork_init (&w->fork, embed_fork_cb);
|
2953
|
+
ev_fork_start (EV_A_ &w->fork);
|
2954
|
+
|
2843
2955
|
/*ev_idle_init (&w->idle, e,bed_idle_cb);*/
|
2844
2956
|
|
2845
2957
|
ev_start (EV_A_ (W)w, 1);
|
@@ -2856,10 +2968,9 @@ ev_embed_stop (EV_P_ ev_embed *w)
|
|
2856
2968
|
|
2857
2969
|
EV_FREQUENT_CHECK;
|
2858
2970
|
|
2859
|
-
ev_io_stop
|
2971
|
+
ev_io_stop (EV_A_ &w->io);
|
2860
2972
|
ev_prepare_stop (EV_A_ &w->prepare);
|
2861
|
-
|
2862
|
-
ev_stop (EV_A_ (W)w);
|
2973
|
+
ev_fork_stop (EV_A_ &w->fork);
|
2863
2974
|
|
2864
2975
|
EV_FREQUENT_CHECK;
|
2865
2976
|
}
|
@@ -2966,7 +3077,7 @@ once_cb (EV_P_ struct ev_once *once, int revents)
|
|
2966
3077
|
void (*cb)(int revents, void *arg) = once->cb;
|
2967
3078
|
void *arg = once->arg;
|
2968
3079
|
|
2969
|
-
ev_io_stop
|
3080
|
+
ev_io_stop (EV_A_ &once->io);
|
2970
3081
|
ev_timer_stop (EV_A_ &once->to);
|
2971
3082
|
ev_free (once);
|
2972
3083
|
|
@@ -2976,13 +3087,17 @@ once_cb (EV_P_ struct ev_once *once, int revents)
|
|
2976
3087
|
static void
|
2977
3088
|
once_cb_io (EV_P_ ev_io *w, int revents)
|
2978
3089
|
{
|
2979
|
-
|
3090
|
+
struct ev_once *once = (struct ev_once *)(((char *)w) - offsetof (struct ev_once, io));
|
3091
|
+
|
3092
|
+
once_cb (EV_A_ once, revents | ev_clear_pending (EV_A_ &once->to));
|
2980
3093
|
}
|
2981
3094
|
|
2982
3095
|
static void
|
2983
3096
|
once_cb_to (EV_P_ ev_timer *w, int revents)
|
2984
3097
|
{
|
2985
|
-
|
3098
|
+
struct ev_once *once = (struct ev_once *)(((char *)w) - offsetof (struct ev_once, to));
|
3099
|
+
|
3100
|
+
once_cb (EV_A_ once, revents | ev_clear_pending (EV_A_ &once->io));
|
2986
3101
|
}
|
2987
3102
|
|
2988
3103
|
void
|