cool.io 1.0.0 → 1.9.0

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.
Files changed (83) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/test.yaml +54 -0
  3. data/.gitignore +30 -0
  4. data/.rspec +3 -0
  5. data/{CHANGES → CHANGES.md} +175 -79
  6. data/{README.markdown → README.md} +43 -49
  7. data/Rakefile +44 -69
  8. data/appveyor.yml +18 -0
  9. data/cool.io.gemspec +18 -131
  10. data/examples/callbacked_echo_server.rb +24 -0
  11. data/ext/cool.io/buffer.c +781 -0
  12. data/ext/cool.io/cool.io.h +13 -0
  13. data/ext/cool.io/cool.io_ext.c +1 -0
  14. data/ext/cool.io/ev_wrap.h +4 -2
  15. data/ext/cool.io/extconf.rb +27 -16
  16. data/ext/cool.io/iowatcher.c +17 -8
  17. data/ext/cool.io/loop.c +36 -84
  18. data/ext/cool.io/stat_watcher.c +103 -25
  19. data/ext/cool.io/timer_watcher.c +3 -3
  20. data/ext/cool.io/utils.c +5 -0
  21. data/ext/cool.io/watcher.h +1 -1
  22. data/ext/libev/Changes +152 -3
  23. data/ext/libev/LICENSE +2 -1
  24. data/ext/libev/README +8 -8
  25. data/ext/libev/ev.c +1719 -348
  26. data/ext/libev/ev.h +146 -118
  27. data/ext/libev/ev_epoll.c +71 -20
  28. data/ext/libev/ev_kqueue.c +36 -16
  29. data/ext/libev/ev_poll.c +14 -11
  30. data/ext/libev/ev_port.c +43 -18
  31. data/ext/libev/ev_select.c +82 -25
  32. data/ext/libev/ev_vars.h +28 -21
  33. data/ext/libev/ev_win32.c +19 -10
  34. data/ext/libev/ev_wrap.h +166 -152
  35. data/ext/libev/test_libev_win32.c +1 -1
  36. data/gems.rb +9 -0
  37. data/lib/cool.io/async_watcher.rb +1 -1
  38. data/lib/cool.io/custom_require.rb +9 -0
  39. data/lib/cool.io/dns_resolver.rb +30 -22
  40. data/lib/cool.io/dsl.rb +32 -28
  41. data/lib/cool.io/io.rb +55 -35
  42. data/lib/cool.io/iowatcher.rb +1 -1
  43. data/lib/cool.io/listener.rb +35 -17
  44. data/lib/cool.io/loop.rb +17 -25
  45. data/lib/cool.io/meta.rb +6 -5
  46. data/lib/cool.io/server.rb +5 -4
  47. data/lib/cool.io/socket.rb +41 -30
  48. data/lib/cool.io/timer_watcher.rb +1 -1
  49. data/lib/cool.io/version.rb +7 -0
  50. data/lib/cool.io.rb +11 -10
  51. data/lib/coolio.rb +1 -1
  52. data/libev_ruby_gil.diff +175 -0
  53. data/libev_win_select.diff +130 -0
  54. data/spec/async_watcher_spec.rb +5 -5
  55. data/spec/dns_spec.rb +27 -8
  56. data/spec/iobuffer_spec.rb +147 -0
  57. data/spec/spec_helper.rb +15 -1
  58. data/spec/stat_watcher_spec.rb +81 -0
  59. data/spec/tcp_server_spec.rb +225 -0
  60. data/spec/tcp_socket_spec.rb +185 -0
  61. data/spec/timer_watcher_spec.rb +23 -19
  62. data/spec/udp_socket_spec.rb +58 -0
  63. data/spec/unix_listener_spec.rb +8 -8
  64. data/spec/unix_server_spec.rb +10 -8
  65. metadata +109 -112
  66. data/VERSION +0 -1
  67. data/examples/httpclient.rb +0 -38
  68. data/ext/http11_client/.gitignore +0 -5
  69. data/ext/http11_client/LICENSE +0 -31
  70. data/ext/http11_client/ext_help.h +0 -14
  71. data/ext/http11_client/extconf.rb +0 -6
  72. data/ext/http11_client/http11_client.c +0 -300
  73. data/ext/http11_client/http11_parser.c +0 -403
  74. data/ext/http11_client/http11_parser.h +0 -48
  75. data/ext/http11_client/http11_parser.rl +0 -173
  76. data/lib/cool.io/eventmachine.rb +0 -234
  77. data/lib/cool.io/http_client.rb +0 -419
  78. data/lib/rev.rb +0 -4
  79. data/spec/possible_tests/schedules_other_threads.rb +0 -48
  80. data/spec/possible_tests/test_on_resolve_failed.rb +0 -9
  81. data/spec/possible_tests/test_resolves.rb +0 -27
  82. data/spec/possible_tests/test_write_during_resolve.rb +0 -27
  83. data/spec/possible_tests/works_straight.rb +0 -71
data/ext/libev/ev_epoll.c CHANGED
@@ -1,19 +1,19 @@
1
1
  /*
2
2
  * libev epoll fd activity backend
3
3
  *
4
- * Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann <libev@schmorp.de>
4
+ * Copyright (c) 2007,2008,2009,2010,2011 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-
8
8
  * tion, are permitted provided that the following conditions are met:
9
- *
9
+ *
10
10
  * 1. Redistributions of source code must retain the above copyright notice,
11
11
  * this list of conditions and the following disclaimer.
12
- *
12
+ *
13
13
  * 2. Redistributions in binary form must reproduce the above copyright
14
14
  * notice, this list of conditions and the following disclaimer in the
15
15
  * documentation and/or other materials provided with the distribution.
16
- *
16
+ *
17
17
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18
18
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
19
19
  * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
@@ -53,7 +53,8 @@
53
53
  * (such as files). while not critical, no other advanced interface
54
54
  * seems to share this (rather non-unixy) limitation.
55
55
  * e) epoll claims to be embeddable, but in practise you never get
56
- * a ready event for the epoll fd.
56
+ * a ready event for the epoll fd (broken: <=2.6.26, working: >=2.6.32).
57
+ * f) epoll_ctl returning EPERM means the fd is always ready.
57
58
  *
58
59
  * lots of "weird code" and complication handling in this file is due
59
60
  * to these design problems with epoll, as we try very hard to avoid
@@ -64,6 +65,8 @@
64
65
 
65
66
  #include <sys/epoll.h>
66
67
 
68
+ #define EV_EMASK_EPERM 0x80
69
+
67
70
  static void
68
71
  epoll_modify (EV_P_ int fd, int oev, int nev)
69
72
  {
@@ -112,6 +115,21 @@ epoll_modify (EV_P_ int fd, int oev, int nev)
112
115
  if (!epoll_ctl (backend_fd, EPOLL_CTL_MOD, fd, &ev))
113
116
  return;
114
117
  }
118
+ else if (expect_true (errno == EPERM))
119
+ {
120
+ /* EPERM means the fd is always ready, but epoll is too snobbish */
121
+ /* to handle it, unlike select or poll. */
122
+ anfds [fd].emask = EV_EMASK_EPERM;
123
+
124
+ /* add fd to epoll_eperms, if not already inside */
125
+ if (!(oldmask & EV_EMASK_EPERM))
126
+ {
127
+ array_needsize (int, epoll_eperms, epoll_epermmax, epoll_epermcnt + 1, EMPTY2);
128
+ epoll_eperms [epoll_epermcnt++] = fd;
129
+ }
130
+
131
+ return;
132
+ }
115
133
 
116
134
  fd_kill (EV_A_ fd);
117
135
 
@@ -125,11 +143,14 @@ epoll_poll (EV_P_ ev_tstamp timeout)
125
143
  {
126
144
  int i;
127
145
  int eventcnt;
128
-
146
+
147
+ if (expect_false (epoll_epermcnt))
148
+ timeout = 0.;
149
+
129
150
  /* epoll wait times cannot be larger than (LONG_MAX - 999UL) / HZ msecs, which is below */
130
151
  /* the default libev max wait time, however. */
131
152
  EV_RELEASE_CB;
132
- eventcnt = epoll_wait (backend_fd, epoll_events, epoll_eventmax, (int)ceil (timeout * 1000.));
153
+ eventcnt = epoll_wait (backend_fd, epoll_events, epoll_eventmax, timeout * 1e3);
133
154
  EV_ACQUIRE_CB;
134
155
 
135
156
  if (expect_false (eventcnt < 0))
@@ -149,12 +170,16 @@ epoll_poll (EV_P_ ev_tstamp timeout)
149
170
  int got = (ev->events & (EPOLLOUT | EPOLLERR | EPOLLHUP) ? EV_WRITE : 0)
150
171
  | (ev->events & (EPOLLIN | EPOLLERR | EPOLLHUP) ? EV_READ : 0);
151
172
 
152
- /* check for spurious notification */
153
- /* we assume that fd is always in range, as we never shrink the anfds array */
173
+ /*
174
+ * check for spurious notification.
175
+ * this only finds spurious notifications on egen updates
176
+ * other spurious notifications will be found by epoll_ctl, below
177
+ * we assume that fd is always in range, as we never shrink the anfds array
178
+ */
154
179
  if (expect_false ((uint32_t)anfds [fd].egen != (uint32_t)(ev->data.u64 >> 32)))
155
180
  {
156
181
  /* recreate kernel state */
157
- postfork = 1;
182
+ postfork |= 2;
158
183
  continue;
159
184
  }
160
185
 
@@ -162,8 +187,15 @@ epoll_poll (EV_P_ ev_tstamp timeout)
162
187
  {
163
188
  anfds [fd].emask = want;
164
189
 
165
- /* we received an event but are not interested in it, try mod or del */
166
- /* I don't think we ever need MOD, but let's handle it anyways */
190
+ /*
191
+ * we received an event but are not interested in it, try mod or del
192
+ * this often happens because we optimistically do not unregister fds
193
+ * when we are no longer interested in them, but also when we get spurious
194
+ * notifications for fds from another process. this is partially handled
195
+ * above with the gencounter check (== our fd is not the event fd), and
196
+ * partially here, when epoll_ctl returns an error (== a child has the fd
197
+ * but we closed it).
198
+ */
167
199
  ev->events = (want & EV_READ ? EPOLLIN : 0)
168
200
  | (want & EV_WRITE ? EPOLLOUT : 0);
169
201
 
@@ -171,7 +203,7 @@ epoll_poll (EV_P_ ev_tstamp timeout)
171
203
  /* which is fortunately easy to do for us. */
172
204
  if (epoll_ctl (backend_fd, want ? EPOLL_CTL_MOD : EPOLL_CTL_DEL, fd, ev))
173
205
  {
174
- postfork = 1; /* an error occurred, recreate kernel state */
206
+ postfork |= 2; /* an error occurred, recreate kernel state */
175
207
  continue;
176
208
  }
177
209
  }
@@ -186,15 +218,31 @@ epoll_poll (EV_P_ ev_tstamp timeout)
186
218
  epoll_eventmax = array_nextsize (sizeof (struct epoll_event), epoll_eventmax, epoll_eventmax + 1);
187
219
  epoll_events = (struct epoll_event *)ev_malloc (sizeof (struct epoll_event) * epoll_eventmax);
188
220
  }
221
+
222
+ /* now synthesize events for all fds where epoll fails, while select works... */
223
+ for (i = epoll_epermcnt; i--; )
224
+ {
225
+ int fd = epoll_eperms [i];
226
+ unsigned char events = anfds [fd].events & (EV_READ | EV_WRITE);
227
+
228
+ if (anfds [fd].emask & EV_EMASK_EPERM && events)
229
+ fd_event (EV_A_ fd, events);
230
+ else
231
+ {
232
+ epoll_eperms [i] = epoll_eperms [--epoll_epermcnt];
233
+ anfds [fd].emask = 0;
234
+ }
235
+ }
189
236
  }
190
237
 
191
- int inline_size
238
+ inline_size
239
+ int
192
240
  epoll_init (EV_P_ int flags)
193
241
  {
194
242
  #ifdef EPOLL_CLOEXEC
195
243
  backend_fd = epoll_create1 (EPOLL_CLOEXEC);
196
244
 
197
- if (backend_fd <= 0)
245
+ if (backend_fd < 0 && (errno == EINVAL || errno == ENOSYS))
198
246
  #endif
199
247
  backend_fd = epoll_create (256);
200
248
 
@@ -203,9 +251,9 @@ epoll_init (EV_P_ int flags)
203
251
 
204
252
  fcntl (backend_fd, F_SETFD, FD_CLOEXEC);
205
253
 
206
- backend_fudge = 0.; /* kernel sources seem to indicate this to be zero */
207
- backend_modify = epoll_modify;
208
- backend_poll = epoll_poll;
254
+ backend_mintime = 1e-3; /* epoll does sometimes return early, this is just to avoid the worst */
255
+ backend_modify = epoll_modify;
256
+ backend_poll = epoll_poll;
209
257
 
210
258
  epoll_eventmax = 64; /* initial number of events receivable per poll */
211
259
  epoll_events = (struct epoll_event *)ev_malloc (sizeof (struct epoll_event) * epoll_eventmax);
@@ -213,13 +261,16 @@ epoll_init (EV_P_ int flags)
213
261
  return EVBACKEND_EPOLL;
214
262
  }
215
263
 
216
- void inline_size
264
+ inline_size
265
+ void
217
266
  epoll_destroy (EV_P)
218
267
  {
219
268
  ev_free (epoll_events);
269
+ array_free (epoll_eperm, EMPTY);
220
270
  }
221
271
 
222
- void inline_size
272
+ inline_size
273
+ void
223
274
  epoll_fork (EV_P)
224
275
  {
225
276
  close (backend_fd);
@@ -1,19 +1,19 @@
1
1
  /*
2
2
  * libev kqueue backend
3
3
  *
4
- * Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann <libev@schmorp.de>
4
+ * Copyright (c) 2007,2008,2009,2010,2011,2012,2013 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-
8
8
  * tion, are permitted provided that the following conditions are met:
9
- *
9
+ *
10
10
  * 1. Redistributions of source code must retain the above copyright notice,
11
11
  * this list of conditions and the following disclaimer.
12
- *
12
+ *
13
13
  * 2. Redistributions in binary form must reproduce the above copyright
14
14
  * notice, this list of conditions and the following disclaimer in the
15
15
  * documentation and/or other materials provided with the distribution.
16
- *
16
+ *
17
17
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18
18
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
19
19
  * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
@@ -43,7 +43,8 @@
43
43
  #include <string.h>
44
44
  #include <errno.h>
45
45
 
46
- void inline_speed
46
+ inline_speed
47
+ void
47
48
  kqueue_change (EV_P_ int fd, int filter, int flags, int fflags)
48
49
  {
49
50
  ++kqueue_changecnt;
@@ -103,12 +104,12 @@ kqueue_poll (EV_P_ ev_tstamp timeout)
103
104
  kqueue_changecnt = 0;
104
105
 
105
106
  if (expect_false (res < 0))
106
- {
107
+ {
107
108
  if (errno != EINTR)
108
109
  ev_syserr ("(libev) kevent");
109
110
 
110
111
  return;
111
- }
112
+ }
112
113
 
113
114
  for (i = 0; i < res; ++i)
114
115
  {
@@ -152,18 +153,20 @@ kqueue_poll (EV_P_ ev_tstamp timeout)
152
153
  }
153
154
  }
154
155
 
155
- int inline_size
156
+ inline_size
157
+ int
156
158
  kqueue_init (EV_P_ int flags)
157
159
  {
158
- /* Initialize the kernel queue */
160
+ /* initialize the kernel queue */
161
+ kqueue_fd_pid = getpid ();
159
162
  if ((backend_fd = kqueue ()) < 0)
160
163
  return 0;
161
164
 
162
165
  fcntl (backend_fd, F_SETFD, FD_CLOEXEC); /* not sure if necessary, hopefully doesn't hurt */
163
166
 
164
- backend_fudge = 0.;
165
- backend_modify = kqueue_modify;
166
- backend_poll = kqueue_poll;
167
+ backend_mintime = 1e-9; /* apparently, they did the right thing in freebsd */
168
+ backend_modify = kqueue_modify;
169
+ backend_poll = kqueue_poll;
167
170
 
168
171
  kqueue_eventmax = 64; /* initial number of events receivable per poll */
169
172
  kqueue_events = (struct kevent *)ev_malloc (sizeof (struct kevent) * kqueue_eventmax);
@@ -175,18 +178,32 @@ kqueue_init (EV_P_ int flags)
175
178
  return EVBACKEND_KQUEUE;
176
179
  }
177
180
 
178
- void inline_size
181
+ inline_size
182
+ void
179
183
  kqueue_destroy (EV_P)
180
184
  {
181
185
  ev_free (kqueue_events);
182
186
  ev_free (kqueue_changes);
183
187
  }
184
188
 
185
- void inline_size
189
+ inline_size
190
+ void
186
191
  kqueue_fork (EV_P)
187
192
  {
188
- close (backend_fd);
189
-
193
+ /* some BSD kernels don't just destroy the kqueue itself,
194
+ * but also close the fd, which isn't documented, and
195
+ * impossible to support properly.
196
+ * we remember the pid of the kqueue call and only close
197
+ * the fd if the pid is still the same.
198
+ * this leaks fds on sane kernels, but BSD interfaces are
199
+ * notoriously buggy and rarely get fixed.
200
+ */
201
+ pid_t newpid = getpid ();
202
+
203
+ if (newpid == kqueue_fd_pid)
204
+ close (backend_fd);
205
+
206
+ kqueue_fd_pid = newpid;
190
207
  while ((backend_fd = kqueue ()) < 0)
191
208
  ev_syserr ("(libev) kqueue");
192
209
 
@@ -196,3 +213,6 @@ kqueue_fork (EV_P)
196
213
  fd_rearm_all (EV_A);
197
214
  }
198
215
 
216
+ /* sys/event.h defines EV_ERROR */
217
+ #undef EV_ERROR
218
+
data/ext/libev/ev_poll.c CHANGED
@@ -1,19 +1,19 @@
1
1
  /*
2
2
  * libev poll fd activity backend
3
3
  *
4
- * Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann <libev@schmorp.de>
4
+ * Copyright (c) 2007,2008,2009,2010,2011 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-
8
8
  * tion, are permitted provided that the following conditions are met:
9
- *
9
+ *
10
10
  * 1. Redistributions of source code must retain the above copyright notice,
11
11
  * this list of conditions and the following disclaimer.
12
- *
12
+ *
13
13
  * 2. Redistributions in binary form must reproduce the above copyright
14
14
  * notice, this list of conditions and the following disclaimer in the
15
15
  * documentation and/or other materials provided with the distribution.
16
- *
16
+ *
17
17
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18
18
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
19
19
  * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
@@ -39,7 +39,8 @@
39
39
 
40
40
  #include <poll.h>
41
41
 
42
- void inline_size
42
+ inline_size
43
+ void
43
44
  pollidx_init (int *base, int count)
44
45
  {
45
46
  /* consider using memset (.., -1, ...), which is practically guaranteed
@@ -92,7 +93,7 @@ poll_poll (EV_P_ ev_tstamp timeout)
92
93
  int res;
93
94
 
94
95
  EV_RELEASE_CB;
95
- res = poll (polls, pollcnt, (int)ceil (timeout * 1000.));
96
+ res = poll (polls, pollcnt, timeout * 1e3);
96
97
  EV_ACQUIRE_CB;
97
98
 
98
99
  if (expect_false (res < 0))
@@ -126,12 +127,13 @@ poll_poll (EV_P_ ev_tstamp timeout)
126
127
  }
127
128
  }
128
129
 
129
- int inline_size
130
+ inline_size
131
+ int
130
132
  poll_init (EV_P_ int flags)
131
133
  {
132
- backend_fudge = 0.; /* posix says this is zero */
133
- backend_modify = poll_modify;
134
- backend_poll = poll_poll;
134
+ backend_mintime = 1e-3;
135
+ backend_modify = poll_modify;
136
+ backend_poll = poll_poll;
135
137
 
136
138
  pollidxs = 0; pollidxmax = 0;
137
139
  polls = 0; pollmax = 0; pollcnt = 0;
@@ -139,7 +141,8 @@ poll_init (EV_P_ int flags)
139
141
  return EVBACKEND_POLL;
140
142
  }
141
143
 
142
- void inline_size
144
+ inline_size
145
+ void
143
146
  poll_destroy (EV_P)
144
147
  {
145
148
  ev_free (pollidxs);
data/ext/libev/ev_port.c CHANGED
@@ -1,19 +1,19 @@
1
1
  /*
2
2
  * libev solaris event port backend
3
3
  *
4
- * Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann <libev@schmorp.de>
4
+ * Copyright (c) 2007,2008,2009,2010,2011 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-
8
8
  * tion, are permitted provided that the following conditions are met:
9
- *
9
+ *
10
10
  * 1. Redistributions of source code must retain the above copyright notice,
11
11
  * this list of conditions and the following disclaimer.
12
- *
12
+ *
13
13
  * 2. Redistributions in binary form must reproduce the above copyright
14
14
  * notice, this list of conditions and the following disclaimer in the
15
15
  * documentation and/or other materials provided with the distribution.
16
- *
16
+ *
17
17
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18
18
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
19
19
  * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
@@ -37,6 +37,17 @@
37
37
  * either the BSD or the GPL.
38
38
  */
39
39
 
40
+ /* useful reading:
41
+ *
42
+ * http://bugs.opensolaris.org/view_bug.do?bug_id=6268715 (random results)
43
+ * http://bugs.opensolaris.org/view_bug.do?bug_id=6455223 (just totally broken)
44
+ * http://bugs.opensolaris.org/view_bug.do?bug_id=6873782 (manpage ETIME)
45
+ * http://bugs.opensolaris.org/view_bug.do?bug_id=6874410 (implementation ETIME)
46
+ * http://www.mail-archive.com/networking-discuss@opensolaris.org/msg11898.html ETIME vs. nget
47
+ * http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libc/port/gen/event_port.c (libc)
48
+ * http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/common/fs/portfs/port.c#1325 (kernel)
49
+ */
50
+
40
51
  #include <sys/types.h>
41
52
  #include <sys/time.h>
42
53
  #include <poll.h>
@@ -44,7 +55,8 @@
44
55
  #include <string.h>
45
56
  #include <errno.h>
46
57
 
47
- void inline_speed
58
+ inline_speed
59
+ void
48
60
  port_associate_and_check (EV_P_ int fd, int ev)
49
61
  {
50
62
  if (0 >
@@ -85,18 +97,20 @@ port_poll (EV_P_ ev_tstamp timeout)
85
97
  struct timespec ts;
86
98
  uint_t nget = 1;
87
99
 
100
+ /* we initialise this to something we will skip in the loop, as */
101
+ /* port_getn can return with nget unchanged, but no indication */
102
+ /* whether it was the original value or has been updated :/ */
103
+ port_events [0].portev_source = 0;
104
+
88
105
  EV_RELEASE_CB;
89
106
  EV_TS_SET (ts, timeout);
90
107
  res = port_getn (backend_fd, port_events, port_eventmax, &nget, &ts);
91
108
  EV_ACQUIRE_CB;
92
109
 
93
- if (res == -1)
94
- {
95
- if (errno != EINTR && errno != ETIME)
96
- ev_syserr ("(libev) port_getn (see http://bugs.opensolaris.org/view_bug.do?bug_id=6268715, try LIBEV_FLAGS=3 env variable)");
97
-
98
- return;
99
- }
110
+ /* port_getn may or may not set nget on error */
111
+ /* so we rely on port_events [0].portev_source not being updated */
112
+ if (res == -1 && errno != ETIME && errno != EINTR)
113
+ ev_syserr ("(libev) port_getn (see http://bugs.opensolaris.org/view_bug.do?bug_id=6268715, try LIBEV_FLAGS=3 env variable)");
100
114
 
101
115
  for (i = 0; i < nget; ++i)
102
116
  {
@@ -123,18 +137,27 @@ port_poll (EV_P_ ev_tstamp timeout)
123
137
  }
124
138
  }
125
139
 
126
- int inline_size
140
+ inline_size
141
+ int
127
142
  port_init (EV_P_ int flags)
128
143
  {
129
144
  /* Initialize the kernel queue */
130
145
  if ((backend_fd = port_create ()) < 0)
131
146
  return 0;
132
147
 
148
+ assert (("libev: PORT_SOURCE_FD must not be zero", PORT_SOURCE_FD));
149
+
133
150
  fcntl (backend_fd, F_SETFD, FD_CLOEXEC); /* not sure if necessary, hopefully doesn't hurt */
134
151
 
135
- backend_fudge = 1e-3; /* needed to compensate for port_getn returning early */
136
- backend_modify = port_modify;
137
- backend_poll = port_poll;
152
+ /* if my reading of the opensolaris kernel sources are correct, then
153
+ * opensolaris does something very stupid: it checks if the time has already
154
+ * elapsed and doesn't round up if that is the case,m otherwise it DOES round
155
+ * up. Since we can't know what the case is, we need to guess by using a
156
+ * "large enough" timeout. Normally, 1e-9 would be correct.
157
+ */
158
+ backend_mintime = 1e-3; /* needed to compensate for port_getn returning early */
159
+ backend_modify = port_modify;
160
+ backend_poll = port_poll;
138
161
 
139
162
  port_eventmax = 64; /* initial number of events receivable per poll */
140
163
  port_events = (port_event_t *)ev_malloc (sizeof (port_event_t) * port_eventmax);
@@ -142,13 +165,15 @@ port_init (EV_P_ int flags)
142
165
  return EVBACKEND_PORT;
143
166
  }
144
167
 
145
- void inline_size
168
+ inline_size
169
+ void
146
170
  port_destroy (EV_P)
147
171
  {
148
172
  ev_free (port_events);
149
173
  }
150
174
 
151
- void inline_size
175
+ inline_size
176
+ void
152
177
  port_fork (EV_P)
153
178
  {
154
179
  close (backend_fd);