rev 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- 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.h
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
/*
|
2
2
|
* libev native API header
|
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-
|
@@ -90,6 +90,10 @@ typedef double ev_tstamp;
|
|
90
90
|
/*****************************************************************************/
|
91
91
|
|
92
92
|
#if EV_STAT_ENABLE
|
93
|
+
# ifdef _WIN32
|
94
|
+
# include <time.h>
|
95
|
+
# include <sys/types.h>
|
96
|
+
# endif
|
93
97
|
# include <sys/stat.h>
|
94
98
|
#endif
|
95
99
|
|
@@ -163,9 +167,10 @@ struct ev_loop;
|
|
163
167
|
|
164
168
|
/*
|
165
169
|
* struct member types:
|
166
|
-
* private: you
|
167
|
-
*
|
168
|
-
*
|
170
|
+
* private: you may look at them, but not change them,
|
171
|
+
* and they might not mean anything to you.
|
172
|
+
* ro: can be read anytime, but only changed when the watcher isn't active.
|
173
|
+
* rw: can be read and modified anytime, even when the watcher is active.
|
169
174
|
*
|
170
175
|
* some internal details that might be helpful for debugging:
|
171
176
|
*
|
@@ -174,7 +179,7 @@ struct ev_loop;
|
|
174
179
|
* or the array index + 1 (most other watchers)
|
175
180
|
* or simply 1 for watchers that aren't in some array.
|
176
181
|
* pending is either 0, in which case the watcher isn't,
|
177
|
-
*
|
182
|
+
* or the array index + 1 in the pendings array.
|
178
183
|
*/
|
179
184
|
|
180
185
|
/* shared by all watchers */
|
@@ -333,7 +338,7 @@ typedef struct ev_embed
|
|
333
338
|
ev_timer timer; /* unused */
|
334
339
|
ev_periodic periodic; /* unused */
|
335
340
|
ev_idle idle; /* unused */
|
336
|
-
ev_fork fork; /*
|
341
|
+
ev_fork fork; /* private */
|
337
342
|
} ev_embed;
|
338
343
|
#endif
|
339
344
|
|
@@ -452,6 +457,7 @@ void ev_loop_fork (EV_P);
|
|
452
457
|
void ev_loop_verify (EV_P);
|
453
458
|
|
454
459
|
ev_tstamp ev_now (EV_P); /* time w.r.t. timers and the eventloop, updated after each poll */
|
460
|
+
void ev_now_update (EV_P);
|
455
461
|
|
456
462
|
#else
|
457
463
|
|
@@ -510,7 +516,7 @@ void ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval); /* sleep at lea
|
|
510
516
|
void ev_ref (EV_P);
|
511
517
|
void ev_unref (EV_P);
|
512
518
|
|
513
|
-
/*
|
519
|
+
/* convenience function, wait for a single event, without registering an event watcher */
|
514
520
|
/* if timeout is < 0, do wait indefinitely */
|
515
521
|
void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg);
|
516
522
|
#endif
|
data/ext/libev/ev_epoll.c
CHANGED
@@ -52,7 +52,9 @@
|
|
52
52
|
*
|
53
53
|
* lots of "weird code" and complication handling in this file is due
|
54
54
|
* to these design problems with epoll, as we try very hard to avoid
|
55
|
-
* epoll_ctl syscalls for common usage patterns
|
55
|
+
* epoll_ctl syscalls for common usage patterns and handle the breakage
|
56
|
+
* ensuing from receiving events for closed and otherwise long gone
|
57
|
+
* file descriptors.
|
56
58
|
*/
|
57
59
|
|
58
60
|
#include <sys/epoll.h>
|
@@ -61,17 +63,25 @@ static void
|
|
61
63
|
epoll_modify (EV_P_ int fd, int oev, int nev)
|
62
64
|
{
|
63
65
|
struct epoll_event ev;
|
66
|
+
unsigned char oldmask;
|
64
67
|
|
65
68
|
/*
|
66
69
|
* we handle EPOLL_CTL_DEL by ignoring it here
|
67
70
|
* on the assumption that the fd is gone anyways
|
68
71
|
* if that is wrong, we have to handle the spurious
|
69
72
|
* event in epoll_poll.
|
73
|
+
* if the fd is added again, we try to ADD it, and, if that
|
74
|
+
* fails, we assume it still has the same eventmask.
|
70
75
|
*/
|
71
76
|
if (!nev)
|
72
77
|
return;
|
73
78
|
|
74
|
-
|
79
|
+
oldmask = anfds [fd].emask;
|
80
|
+
anfds [fd].emask = nev;
|
81
|
+
|
82
|
+
/* store the generation counter in the upper 32 bits, the fd in the lower 32 bits */
|
83
|
+
ev.data.u64 = (uint64_t)(uint32_t)fd
|
84
|
+
| ((uint64_t)(uint32_t)++anfds [fd].egen << 32);
|
75
85
|
ev.events = (nev & EV_READ ? EPOLLIN : 0)
|
76
86
|
| (nev & EV_WRITE ? EPOLLOUT : 0);
|
77
87
|
|
@@ -80,21 +90,29 @@ epoll_modify (EV_P_ int fd, int oev, int nev)
|
|
80
90
|
|
81
91
|
if (expect_true (errno == ENOENT))
|
82
92
|
{
|
83
|
-
/*
|
93
|
+
/* if ENOENT then the fd went away, so try to do the right thing */
|
84
94
|
if (!nev)
|
85
|
-
|
95
|
+
goto dec_egen;
|
86
96
|
|
87
97
|
if (!epoll_ctl (backend_fd, EPOLL_CTL_ADD, fd, &ev))
|
88
98
|
return;
|
89
99
|
}
|
90
100
|
else if (expect_true (errno == EEXIST))
|
91
101
|
{
|
92
|
-
/*
|
102
|
+
/* EEXIST means we ignored a previous DEL, but the fd is still active */
|
103
|
+
/* if the kernel mask is the same as the new mask, we assume it hasn't changed */
|
104
|
+
if (oldmask == nev)
|
105
|
+
goto dec_egen;
|
106
|
+
|
93
107
|
if (!epoll_ctl (backend_fd, EPOLL_CTL_MOD, fd, &ev))
|
94
108
|
return;
|
95
109
|
}
|
96
110
|
|
97
111
|
fd_kill (EV_A_ fd);
|
112
|
+
|
113
|
+
dec_egen:
|
114
|
+
/* we didn't successfully call epoll_ctl, so decrement the generation counter again */
|
115
|
+
--anfds [fd].egen;
|
98
116
|
}
|
99
117
|
|
100
118
|
static void
|
@@ -106,7 +124,7 @@ epoll_poll (EV_P_ ev_tstamp timeout)
|
|
106
124
|
if (expect_false (eventcnt < 0))
|
107
125
|
{
|
108
126
|
if (errno != EINTR)
|
109
|
-
|
127
|
+
ev_syserr ("(libev) epoll_wait");
|
110
128
|
|
111
129
|
return;
|
112
130
|
}
|
@@ -115,18 +133,33 @@ epoll_poll (EV_P_ ev_tstamp timeout)
|
|
115
133
|
{
|
116
134
|
struct epoll_event *ev = epoll_events + i;
|
117
135
|
|
118
|
-
int fd
|
136
|
+
int fd = (uint32_t)ev->data.u64; /* mask out the lower 32 bits */
|
137
|
+
int want = anfds [fd].events;
|
119
138
|
int got = (ev->events & (EPOLLOUT | EPOLLERR | EPOLLHUP) ? EV_WRITE : 0)
|
120
139
|
| (ev->events & (EPOLLIN | EPOLLERR | EPOLLHUP) ? EV_READ : 0);
|
121
|
-
|
140
|
+
|
141
|
+
/* check for spurious notification */
|
142
|
+
if (expect_false ((uint32_t)anfds [fd].egen != (uint32_t)(ev->data.u64 >> 32)))
|
143
|
+
{
|
144
|
+
/* recreate kernel state */
|
145
|
+
postfork = 1;
|
146
|
+
continue;
|
147
|
+
}
|
122
148
|
|
123
149
|
if (expect_false (got & ~want))
|
124
150
|
{
|
151
|
+
anfds [fd].emask = want;
|
152
|
+
|
125
153
|
/* we received an event but are not interested in it, try mod or del */
|
154
|
+
/* I don't think we ever need MOD, but let's handle it anyways */
|
126
155
|
ev->events = (want & EV_READ ? EPOLLIN : 0)
|
127
156
|
| (want & EV_WRITE ? EPOLLOUT : 0);
|
128
157
|
|
129
|
-
epoll_ctl (backend_fd, want ? EPOLL_CTL_MOD : EPOLL_CTL_DEL, fd, ev)
|
158
|
+
if (epoll_ctl (backend_fd, want ? EPOLL_CTL_MOD : EPOLL_CTL_DEL, fd, ev))
|
159
|
+
{
|
160
|
+
postfork = 1; /* an error occured, recreate kernel state */
|
161
|
+
continue;
|
162
|
+
}
|
130
163
|
}
|
131
164
|
|
132
165
|
fd_event (EV_A_ fd, got);
|
@@ -155,7 +188,7 @@ epoll_init (EV_P_ int flags)
|
|
155
188
|
backend_modify = epoll_modify;
|
156
189
|
backend_poll = epoll_poll;
|
157
190
|
|
158
|
-
epoll_eventmax = 64; /*
|
191
|
+
epoll_eventmax = 64; /* initial number of events receivable per poll */
|
159
192
|
epoll_events = (struct epoll_event *)ev_malloc (sizeof (struct epoll_event) * epoll_eventmax);
|
160
193
|
|
161
194
|
return EVBACKEND_EPOLL;
|
@@ -173,7 +206,7 @@ epoll_fork (EV_P)
|
|
173
206
|
close (backend_fd);
|
174
207
|
|
175
208
|
while ((backend_fd = epoll_create (256)) < 0)
|
176
|
-
|
209
|
+
ev_syserr ("(libev) epoll_create");
|
177
210
|
|
178
211
|
fcntl (backend_fd, F_SETFD, FD_CLOEXEC);
|
179
212
|
|
data/ext/libev/ev_kqueue.c
CHANGED
@@ -101,7 +101,7 @@ kqueue_poll (EV_P_ ev_tstamp timeout)
|
|
101
101
|
if (expect_false (res < 0))
|
102
102
|
{
|
103
103
|
if (errno != EINTR)
|
104
|
-
|
104
|
+
ev_syserr ("(libev) kevent");
|
105
105
|
|
106
106
|
return;
|
107
107
|
}
|
@@ -184,7 +184,7 @@ kqueue_fork (EV_P)
|
|
184
184
|
close (backend_fd);
|
185
185
|
|
186
186
|
while ((backend_fd = kqueue ()) < 0)
|
187
|
-
|
187
|
+
ev_syserr ("(libev) kqueue");
|
188
188
|
|
189
189
|
fcntl (backend_fd, F_SETFD, FD_CLOEXEC);
|
190
190
|
|
data/ext/libev/ev_poll.c
CHANGED
@@ -42,6 +42,8 @@
|
|
42
42
|
void inline_size
|
43
43
|
pollidx_init (int *base, int count)
|
44
44
|
{
|
45
|
+
/* consider using memset (.., -1, ...), which is pratically guarenteed
|
46
|
+
* to work on all systems implementing poll */
|
45
47
|
while (count--)
|
46
48
|
*base++ = -1;
|
47
49
|
}
|
@@ -96,7 +98,7 @@ poll_poll (EV_P_ ev_tstamp timeout)
|
|
96
98
|
else if (errno == ENOMEM && !syserr_cb)
|
97
99
|
fd_enomem (EV_A);
|
98
100
|
else if (errno != EINTR)
|
99
|
-
|
101
|
+
ev_syserr ("(libev) poll");
|
100
102
|
}
|
101
103
|
else
|
102
104
|
for (p = polls; res; ++p)
|
data/ext/libev/ev_port.c
CHANGED
@@ -59,7 +59,7 @@ port_associate_and_check (EV_P_ int fd, int ev)
|
|
59
59
|
if (errno == EBADFD)
|
60
60
|
fd_kill (EV_A_ fd);
|
61
61
|
else
|
62
|
-
|
62
|
+
ev_syserr ("(libev) port_associate");
|
63
63
|
}
|
64
64
|
}
|
65
65
|
|
@@ -89,10 +89,10 @@ port_poll (EV_P_ ev_tstamp timeout)
|
|
89
89
|
ts.tv_nsec = (long)(timeout - (ev_tstamp)ts.tv_sec) * 1e9;
|
90
90
|
res = port_getn (backend_fd, port_events, port_eventmax, &nget, &ts);
|
91
91
|
|
92
|
-
if (res
|
92
|
+
if (res == -1)
|
93
93
|
{
|
94
94
|
if (errno != EINTR && errno != ETIME)
|
95
|
-
|
95
|
+
ev_syserr ("(libev) port_getn");
|
96
96
|
|
97
97
|
return;
|
98
98
|
}
|
@@ -153,7 +153,7 @@ port_fork (EV_P)
|
|
153
153
|
close (backend_fd);
|
154
154
|
|
155
155
|
while ((backend_fd = port_create ()) < 0)
|
156
|
-
|
156
|
+
ev_syserr ("(libev) port");
|
157
157
|
|
158
158
|
fcntl (backend_fd, F_SETFD, FD_CLOEXEC);
|
159
159
|
|
data/ext/libev/ev_select.c
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
/*
|
2
2
|
* libev select fd activity backend
|
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-
|
@@ -54,6 +54,8 @@
|
|
54
54
|
#if EV_SELECT_IS_WINSOCKET
|
55
55
|
# undef EV_SELECT_USE_FD_SET
|
56
56
|
# define EV_SELECT_USE_FD_SET 1
|
57
|
+
# undef NFDBITS
|
58
|
+
# define NFDBITS 0
|
57
59
|
#endif
|
58
60
|
|
59
61
|
#if !EV_SELECT_USE_FD_SET
|
@@ -77,15 +79,26 @@ select_modify (EV_P_ int fd, int oev, int nev)
|
|
77
79
|
int handle = fd;
|
78
80
|
#endif
|
79
81
|
|
80
|
-
|
81
|
-
FD_SET (handle, (fd_set *)vec_ri);
|
82
|
-
else
|
83
|
-
FD_CLR (handle, (fd_set *)vec_ri);
|
82
|
+
assert (("libev: fd >= FD_SETSIZE passed to fd_set-based select backend", fd < FD_SETSIZE));
|
84
83
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
84
|
+
/* FD_SET is broken on windows (it adds the fd to a set twice or more,
|
85
|
+
* which eventually leads to overflows). Need to call it only on changes.
|
86
|
+
*/
|
87
|
+
#if EV_SELECT_IS_WINSOCKET
|
88
|
+
if ((oev ^ nev) & EV_READ)
|
89
|
+
#endif
|
90
|
+
if (nev & EV_READ)
|
91
|
+
FD_SET (handle, (fd_set *)vec_ri);
|
92
|
+
else
|
93
|
+
FD_CLR (handle, (fd_set *)vec_ri);
|
94
|
+
|
95
|
+
#if EV_SELECT_IS_WINSOCKET
|
96
|
+
if ((oev ^ nev) & EV_WRITE)
|
97
|
+
#endif
|
98
|
+
if (nev & EV_WRITE)
|
99
|
+
FD_SET (handle, (fd_set *)vec_wi);
|
100
|
+
else
|
101
|
+
FD_CLR (handle, (fd_set *)vec_wi);
|
89
102
|
|
90
103
|
#else
|
91
104
|
|
@@ -100,6 +113,9 @@ select_modify (EV_P_ int fd, int oev, int nev)
|
|
100
113
|
vec_ro = ev_realloc (vec_ro, new_max * NFDBYTES); /* could free/malloc */
|
101
114
|
vec_wi = ev_realloc (vec_wi, new_max * NFDBYTES);
|
102
115
|
vec_wo = ev_realloc (vec_wo, new_max * NFDBYTES); /* could free/malloc */
|
116
|
+
#ifdef _WIN32
|
117
|
+
vec_eo = ev_realloc (vec_eo, new_max * NFDBYTES); /* could free/malloc */
|
118
|
+
#endif
|
103
119
|
|
104
120
|
for (; vec_max < new_max; ++vec_max)
|
105
121
|
((fd_mask *)vec_ri) [vec_max] =
|
@@ -122,19 +138,34 @@ select_poll (EV_P_ ev_tstamp timeout)
|
|
122
138
|
{
|
123
139
|
struct timeval tv;
|
124
140
|
int res;
|
141
|
+
int fd_setsize;
|
142
|
+
|
143
|
+
tv.tv_sec = (long)timeout;
|
144
|
+
tv.tv_usec = (long)((timeout - (ev_tstamp)tv.tv_sec) * 1e6);
|
125
145
|
|
126
146
|
#if EV_SELECT_USE_FD_SET
|
127
|
-
|
128
|
-
memcpy (vec_wo, vec_wi, sizeof (fd_set));
|
147
|
+
fd_setsize = sizeof (fd_set);
|
129
148
|
#else
|
130
|
-
|
131
|
-
memcpy (vec_wo, vec_wi, vec_max * NFDBYTES);
|
149
|
+
fd_setsize = vec_max * NFDBYTES;
|
132
150
|
#endif
|
133
151
|
|
134
|
-
|
135
|
-
|
136
|
-
|
152
|
+
memcpy (vec_ro, vec_ri, fd_setsize);
|
153
|
+
memcpy (vec_wo, vec_wi, fd_setsize);
|
154
|
+
|
155
|
+
#ifdef _WIN32
|
156
|
+
/* pass in the write set as except set.
|
157
|
+
* the idea behind this is to work around a windows bug that causes
|
158
|
+
* errors to be reported as an exception and not by setting
|
159
|
+
* the writable bit. this is so uncontrollably lame.
|
160
|
+
*/
|
161
|
+
memcpy (vec_eo, vec_wi, fd_setsize);
|
162
|
+
res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, (fd_set *)vec_eo, &tv);
|
163
|
+
#elif EV_SELECT_USE_FD_SET
|
164
|
+
fd_setsize = anfdmax < FD_SETSIZE ? anfdmax : FD_SETSIZE;
|
165
|
+
res = select (fd_setsize, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv);
|
166
|
+
#else
|
137
167
|
res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv);
|
168
|
+
#endif
|
138
169
|
|
139
170
|
if (expect_false (res < 0))
|
140
171
|
{
|
@@ -153,7 +184,7 @@ select_poll (EV_P_ ev_tstamp timeout)
|
|
153
184
|
#ifdef _WIN32
|
154
185
|
/* select on windows errornously returns EINVAL when no fd sets have been
|
155
186
|
* provided (this is documented). what microsoft doesn't tell you that this bug
|
156
|
-
* exists even when the fd sets
|
187
|
+
* exists even when the fd sets _are_ provided, so we have to check for this bug
|
157
188
|
* here and emulate by sleeping manually.
|
158
189
|
* we also get EINVAL when the timeout is invalid, but we ignore this case here
|
159
190
|
* and assume that EINVAL always means: you have to wait manually.
|
@@ -170,7 +201,7 @@ select_poll (EV_P_ ev_tstamp timeout)
|
|
170
201
|
else if (errno == ENOMEM && !syserr_cb)
|
171
202
|
fd_enomem (EV_A);
|
172
203
|
else if (errno != EINTR)
|
173
|
-
|
204
|
+
ev_syserr ("(libev) select");
|
174
205
|
|
175
206
|
return;
|
176
207
|
}
|
@@ -192,6 +223,9 @@ select_poll (EV_P_ ev_tstamp timeout)
|
|
192
223
|
|
193
224
|
if (FD_ISSET (handle, (fd_set *)vec_ro)) events |= EV_READ;
|
194
225
|
if (FD_ISSET (handle, (fd_set *)vec_wo)) events |= EV_WRITE;
|
226
|
+
#ifdef _WIN32
|
227
|
+
if (FD_ISSET (handle, (fd_set *)vec_eo)) events |= EV_WRITE;
|
228
|
+
#endif
|
195
229
|
|
196
230
|
if (expect_true (events))
|
197
231
|
fd_event (EV_A_ fd, events);
|
@@ -206,6 +240,9 @@ select_poll (EV_P_ ev_tstamp timeout)
|
|
206
240
|
{
|
207
241
|
fd_mask word_r = ((fd_mask *)vec_ro) [word];
|
208
242
|
fd_mask word_w = ((fd_mask *)vec_wo) [word];
|
243
|
+
#ifdef _WIN32
|
244
|
+
word_w |= ((fd_mask *)vec_eo) [word];
|
245
|
+
#endif
|
209
246
|
|
210
247
|
if (word_r || word_w)
|
211
248
|
for (bit = NFDBITS; bit--; )
|
@@ -233,11 +270,13 @@ select_init (EV_P_ int flags)
|
|
233
270
|
backend_poll = select_poll;
|
234
271
|
|
235
272
|
#if EV_SELECT_USE_FD_SET
|
236
|
-
vec_max = FD_SETSIZE / 32;
|
237
273
|
vec_ri = ev_malloc (sizeof (fd_set)); FD_ZERO ((fd_set *)vec_ri);
|
238
274
|
vec_ro = ev_malloc (sizeof (fd_set));
|
239
275
|
vec_wi = ev_malloc (sizeof (fd_set)); FD_ZERO ((fd_set *)vec_wi);
|
240
276
|
vec_wo = ev_malloc (sizeof (fd_set));
|
277
|
+
#ifdef _WIN32
|
278
|
+
vec_eo = ev_malloc (sizeof (fd_set));
|
279
|
+
#endif
|
241
280
|
#else
|
242
281
|
vec_max = 0;
|
243
282
|
vec_ri = 0;
|
data/ext/libev/ev_vars.h
CHANGED
@@ -65,13 +65,16 @@ VARx(ev_io, pipeev)
|
|
65
65
|
VARx(pid_t, curpid)
|
66
66
|
#endif
|
67
67
|
|
68
|
-
VARx(
|
68
|
+
VARx(char, postfork) /* true if we need to recreate kernel state after fork */
|
69
69
|
|
70
70
|
#if EV_USE_SELECT || EV_GENWRAP
|
71
71
|
VARx(void *, vec_ri)
|
72
72
|
VARx(void *, vec_ro)
|
73
73
|
VARx(void *, vec_wi)
|
74
74
|
VARx(void *, vec_wo)
|
75
|
+
#if defined(_WIN32) || EV_GENWRAP
|
76
|
+
VARx(void *, vec_eo)
|
77
|
+
#endif
|
75
78
|
VARx(int, vec_max)
|
76
79
|
#endif
|
77
80
|
|
@@ -153,6 +156,7 @@ VARx(int, asynccnt)
|
|
153
156
|
#if EV_USE_INOTIFY || EV_GENWRAP
|
154
157
|
VARx(int, fs_fd)
|
155
158
|
VARx(ev_io, fs_w)
|
159
|
+
VARx(char, fs_2625) /* whether we are running in linux 2.6.25 or newer */
|
156
160
|
VAR (fs_hash, ANFS fs_hash [EV_INOTIFY_HASHSIZE])
|
157
161
|
#endif
|
158
162
|
|
data/ext/libev/ev_win32.c
CHANGED
@@ -39,10 +39,13 @@
|
|
39
39
|
|
40
40
|
#ifdef _WIN32
|
41
41
|
|
42
|
+
/* timeb.h is actually xsi legacy functionality */
|
42
43
|
#include <sys/timeb.h>
|
43
44
|
|
44
45
|
/* note: the comment below could not be substantiated, but what would I care */
|
45
46
|
/* MSDN says this is required to handle SIGFPE */
|
47
|
+
/* my wild guess would be that using something floating-pointy is required */
|
48
|
+
/* for the crt to do something about it */
|
46
49
|
volatile double SIGFPE_REQ = 0.0f;
|
47
50
|
|
48
51
|
/* oh, the humanity! */
|
@@ -51,6 +54,8 @@ ev_pipe (int filedes [2])
|
|
51
54
|
{
|
52
55
|
struct sockaddr_in addr = { 0 };
|
53
56
|
int addr_size = sizeof (addr);
|
57
|
+
struct sockaddr_in adr2;
|
58
|
+
int adr2_size;
|
54
59
|
SOCKET listener;
|
55
60
|
SOCKET sock [2] = { -1, -1 };
|
56
61
|
|
@@ -64,7 +69,7 @@ ev_pipe (int filedes [2])
|
|
64
69
|
if (bind (listener, (struct sockaddr *)&addr, addr_size))
|
65
70
|
goto fail;
|
66
71
|
|
67
|
-
if (getsockname(listener, (struct sockaddr *)&addr, &addr_size))
|
72
|
+
if (getsockname (listener, (struct sockaddr *)&addr, &addr_size))
|
68
73
|
goto fail;
|
69
74
|
|
70
75
|
if (listen (listener, 1))
|
@@ -73,10 +78,34 @@ ev_pipe (int filedes [2])
|
|
73
78
|
if ((sock [0] = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
|
74
79
|
goto fail;
|
75
80
|
|
76
|
-
if (connect (sock[0], (struct sockaddr *)&addr, addr_size))
|
81
|
+
if (connect (sock [0], (struct sockaddr *)&addr, addr_size))
|
77
82
|
goto fail;
|
78
83
|
|
79
|
-
if ((sock[1] = accept (listener, 0, 0)) < 0)
|
84
|
+
if ((sock [1] = accept (listener, 0, 0)) < 0)
|
85
|
+
goto fail;
|
86
|
+
|
87
|
+
/* windows vista returns fantasy port numbers for sockets:
|
88
|
+
* example for two interconnected tcp sockets:
|
89
|
+
*
|
90
|
+
* (Socket::unpack_sockaddr_in getsockname $sock0)[0] == 53364
|
91
|
+
* (Socket::unpack_sockaddr_in getpeername $sock0)[0] == 53363
|
92
|
+
* (Socket::unpack_sockaddr_in getsockname $sock1)[0] == 53363
|
93
|
+
* (Socket::unpack_sockaddr_in getpeername $sock1)[0] == 53365
|
94
|
+
*
|
95
|
+
* wow! tridirectional sockets!
|
96
|
+
*
|
97
|
+
* this way of checking ports seems to work:
|
98
|
+
*/
|
99
|
+
if (getpeername (sock [0], (struct sockaddr *)&addr, &addr_size))
|
100
|
+
goto fail;
|
101
|
+
|
102
|
+
if (getsockname (sock [1], (struct sockaddr *)&adr2, &adr2_size))
|
103
|
+
goto fail;
|
104
|
+
|
105
|
+
errno = WSAEINVAL;
|
106
|
+
if (addr_size != adr2_size
|
107
|
+
|| addr.sin_addr.s_addr != adr2.sin_addr.s_addr /* just to be sure, I mean, it's windows */
|
108
|
+
|| addr.sin_port != adr2.sin_port)
|
80
109
|
goto fail;
|
81
110
|
|
82
111
|
closesocket (listener);
|