-
-
Notifications
You must be signed in to change notification settings - Fork 49
Expand file tree
/
Copy pathlibev_win_select.diff
More file actions
146 lines (137 loc) · 4.98 KB
/
Copy pathlibev_win_select.diff
File metadata and controls
146 lines (137 loc) · 4.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
diff --git a/ext/libev/ev.c b/ext/libev/ev.c
index a59efb2..5c18fd6 100644
--- a/ext/libev/ev.c
+++ b/ext/libev/ev.c
@@ -210,6 +210,13 @@
#else
# include <io.h>
# define WIN32_LEAN_AND_MEAN
+/* ruby.h above already pulled in winsock2.h, so fd_set may be dimensioned
+ * already. Defining FD_SETSIZE unconditionally here would only move the bound
+ * used by EV_WIN_FD_SET, not the array it indexes. Take whatever is in effect
+ * and only supply a default when nothing has been decided yet. */
+# ifndef FD_SETSIZE
+# define FD_SETSIZE 1024
+# endif
# include <winsock2.h>
# include <windows.h>
# ifndef EV_SELECT_IS_WINSOCKET
diff --git a/ext/libev/ev_select.c b/ext/libev/ev_select.c
index ed1fc7a..eccff2b 100644
--- a/ext/libev/ev_select.c
+++ b/ext/libev/ev_select.c
@@ -67,6 +67,64 @@
#include <string.h>
+#ifdef _WIN32
+/*
+########## COOLIO PATCHERY HO! ##########
+
+Ruby undefs FD_* utilities for own implementation.
+It converts fd argument into socket handle internally on Windows,
+so libev should not use Ruby's FD_* utilities.
+
+Following FD_* utilities come from MinGW.
+RubyInstaller is built by MinGW so this should work.
+*/
+int PASCAL __WSAFDIsSet(SOCKET,fd_set*);
+#define EV_WIN_FD_CLR(fd,set) do { u_int __i;\
+for (__i = 0; __i < ((fd_set *)(set))->fd_count ; __i++) {\
+ if (((fd_set *)(set))->fd_array[__i] == (fd)) {\
+ while (__i < ((fd_set *)(set))->fd_count-1) {\
+ ((fd_set*)(set))->fd_array[__i] = ((fd_set*)(set))->fd_array[__i+1];\
+ __i++;\
+ }\
+ ((fd_set*)(set))->fd_count--;\
+ break;\
+ }\
+}\
+} while (0)
+#define EV_WIN_FD_SET(fd, set) do { u_int __i;\
+for (__i = 0; __i < ((fd_set *)(set))->fd_count ; __i++) {\
+ if (((fd_set *)(set))->fd_array[__i] == (fd)) {\
+ break;\
+ }\
+}\
+if (__i == ((fd_set *)(set))->fd_count) {\
+ if (((fd_set *)(set))->fd_count < FD_SETSIZE) {\
+ ((fd_set *)(set))->fd_array[__i] = (fd);\
+ ((fd_set *)(set))->fd_count++;\
+ }\
+}\
+} while(0)
+#define EV_WIN_FD_ZERO(set) (((fd_set *)(set))->fd_count=0)
+#define EV_WIN_FD_ISSET(fd, set) __WSAFDIsSet((SOCKET)(fd), (fd_set *)(set))
+#define EV_WIN_FD_COUNT(set) (((fd_set *)(set))->fd_count)
+
+/*
+fd_set is dimensioned by whatever FD_SETSIZE was in effect when winsock2.h was
+first pulled in, but EV_WIN_FD_SET and select_modify bound-check against the
+FD_SETSIZE visible here. The two are decided by separate paths, so if the bound
+ever exceeds the declared array we would write past the end of the allocation in
+select_init. Catch that at build time instead.
+*/
+typedef char coolio_fd_setsize_matches_fd_set[
+ (sizeof (((fd_set *)0)->fd_array) / sizeof (SOCKET) >= (size_t)FD_SETSIZE) ? 1 : -1];
+/* ######################################## */
+#else
+#define EV_WIN_FD_CLR FD_CLR
+#define EV_WIN_FD_SET FD_SET
+#define EV_WIN_FD_ZERO FD_ZERO
+#define EV_WIN_FD_ISSET FD_ISSET
+#endif
+
static void
select_modify (EV_P_ int fd, int oev, int nev)
{
@@ -91,17 +149,17 @@ select_modify (EV_P_ int fd, int oev, int nev)
if ((oev ^ nev) & EV_READ)
#endif
if (nev & EV_READ)
- FD_SET (handle, (fd_set *)vec_ri);
+ EV_WIN_FD_SET (handle, (fd_set *)vec_ri);
else
- FD_CLR (handle, (fd_set *)vec_ri);
+ EV_WIN_FD_CLR (handle, (fd_set *)vec_ri);
#if EV_SELECT_IS_WINSOCKET
if ((oev ^ nev) & EV_WRITE)
#endif
if (nev & EV_WRITE)
- FD_SET (handle, (fd_set *)vec_wi);
+ EV_WIN_FD_SET (handle, (fd_set *)vec_wi);
else
- FD_CLR (handle, (fd_set *)vec_wi);
+ EV_WIN_FD_CLR (handle, (fd_set *)vec_wi);
#else
@@ -197,8 +255,8 @@ select_poll (EV_P_ ev_tstamp timeout)
{
if (timeout)
{
- unsigned long ms = timeout * 1e3;
- Sleep (ms ? ms : 1);
+ unsigned long ms = (unsigned long)(timeout * 1e3);
+ SleepEx (ms ? ms : 1, TRUE);
}
return;
@@ -230,10 +288,10 @@ select_poll (EV_P_ ev_tstamp timeout)
int handle = fd;
#endif
- if (FD_ISSET (handle, (fd_set *)vec_ro)) events |= EV_READ;
- if (FD_ISSET (handle, (fd_set *)vec_wo)) events |= EV_WRITE;
+ if (EV_WIN_FD_ISSET (handle, (fd_set *)vec_ro)) events |= EV_READ;
+ if (EV_WIN_FD_ISSET (handle, (fd_set *)vec_wo)) events |= EV_WRITE;
#ifdef _WIN32
- if (FD_ISSET (handle, (fd_set *)vec_eo)) events |= EV_WRITE;
+ if (EV_WIN_FD_ISSET (handle, (fd_set *)vec_eo)) events |= EV_WRITE;
#endif
if (expect_true (events))
@@ -280,9 +338,9 @@ select_init (EV_P_ int flags)
backend_poll = select_poll;
#if EV_SELECT_USE_FD_SET
- vec_ri = ev_malloc (sizeof (fd_set)); FD_ZERO ((fd_set *)vec_ri);
+ vec_ri = ev_malloc (sizeof (fd_set)); EV_WIN_FD_ZERO ((fd_set *)vec_ri);
vec_ro = ev_malloc (sizeof (fd_set));
- vec_wi = ev_malloc (sizeof (fd_set)); FD_ZERO ((fd_set *)vec_wi);
+ vec_wi = ev_malloc (sizeof (fd_set)); EV_WIN_FD_ZERO ((fd_set *)vec_wi);
vec_wo = ev_malloc (sizeof (fd_set));
#ifdef _WIN32
vec_eo = ev_malloc (sizeof (fd_set));