wj_eventmachine 1.3.0.dev.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (180) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +179 -0
  3. data/GNU +281 -0
  4. data/LICENSE +60 -0
  5. data/README.md +110 -0
  6. data/docs/DocumentationGuidesIndex.md +27 -0
  7. data/docs/GettingStarted.md +520 -0
  8. data/docs/old/ChangeLog +211 -0
  9. data/docs/old/DEFERRABLES +246 -0
  10. data/docs/old/EPOLL +141 -0
  11. data/docs/old/INSTALL +13 -0
  12. data/docs/old/KEYBOARD +42 -0
  13. data/docs/old/LEGAL +25 -0
  14. data/docs/old/LIGHTWEIGHT_CONCURRENCY +130 -0
  15. data/docs/old/PURE_RUBY +75 -0
  16. data/docs/old/RELEASE_NOTES +94 -0
  17. data/docs/old/SMTP +4 -0
  18. data/docs/old/SPAWNED_PROCESSES +148 -0
  19. data/docs/old/TODO +8 -0
  20. data/examples/guides/getting_started/01_eventmachine_echo_server.rb +18 -0
  21. data/examples/guides/getting_started/02_eventmachine_echo_server_that_recognizes_exit_command.rb +22 -0
  22. data/examples/guides/getting_started/03_simple_chat_server.rb +149 -0
  23. data/examples/guides/getting_started/04_simple_chat_server_step_one.rb +27 -0
  24. data/examples/guides/getting_started/05_simple_chat_server_step_two.rb +43 -0
  25. data/examples/guides/getting_started/06_simple_chat_server_step_three.rb +98 -0
  26. data/examples/guides/getting_started/07_simple_chat_server_step_four.rb +121 -0
  27. data/examples/guides/getting_started/08_simple_chat_server_step_five.rb +141 -0
  28. data/examples/old/ex_channel.rb +43 -0
  29. data/examples/old/ex_queue.rb +2 -0
  30. data/examples/old/ex_tick_loop_array.rb +15 -0
  31. data/examples/old/ex_tick_loop_counter.rb +32 -0
  32. data/examples/old/helper.rb +2 -0
  33. data/ext/binder.cpp +124 -0
  34. data/ext/binder.h +52 -0
  35. data/ext/cmain.cpp +1046 -0
  36. data/ext/ed.cpp +2238 -0
  37. data/ext/ed.h +460 -0
  38. data/ext/em.cpp +2378 -0
  39. data/ext/em.h +266 -0
  40. data/ext/eventmachine.h +152 -0
  41. data/ext/extconf.rb +285 -0
  42. data/ext/fastfilereader/extconf.rb +120 -0
  43. data/ext/fastfilereader/mapper.cpp +214 -0
  44. data/ext/fastfilereader/mapper.h +59 -0
  45. data/ext/fastfilereader/rubymain.cpp +126 -0
  46. data/ext/kb.cpp +79 -0
  47. data/ext/page.cpp +107 -0
  48. data/ext/page.h +51 -0
  49. data/ext/pipe.cpp +354 -0
  50. data/ext/project.h +174 -0
  51. data/ext/rubymain.cpp +1610 -0
  52. data/ext/ssl.cpp +627 -0
  53. data/ext/ssl.h +103 -0
  54. data/ext/wait_for_single_fd.h +36 -0
  55. data/java/.classpath +8 -0
  56. data/java/.project +17 -0
  57. data/java/src/com/rubyeventmachine/EmReactor.java +625 -0
  58. data/java/src/com/rubyeventmachine/EmReactorException.java +40 -0
  59. data/java/src/com/rubyeventmachine/EmReactorInterface.java +70 -0
  60. data/java/src/com/rubyeventmachine/EventableChannel.java +72 -0
  61. data/java/src/com/rubyeventmachine/EventableDatagramChannel.java +201 -0
  62. data/java/src/com/rubyeventmachine/EventableSocketChannel.java +415 -0
  63. data/java/src/com/rubyeventmachine/NullEmReactor.java +157 -0
  64. data/java/src/com/rubyeventmachine/NullEventableChannel.java +81 -0
  65. data/lib/em/buftok.rb +59 -0
  66. data/lib/em/callback.rb +58 -0
  67. data/lib/em/channel.rb +69 -0
  68. data/lib/em/completion.rb +307 -0
  69. data/lib/em/connection.rb +776 -0
  70. data/lib/em/deferrable.rb +210 -0
  71. data/lib/em/deferrable/pool.rb +2 -0
  72. data/lib/em/file_watch.rb +73 -0
  73. data/lib/em/future.rb +61 -0
  74. data/lib/em/io_streamer.rb +68 -0
  75. data/lib/em/iterator.rb +252 -0
  76. data/lib/em/messages.rb +66 -0
  77. data/lib/em/pool.rb +151 -0
  78. data/lib/em/process_watch.rb +45 -0
  79. data/lib/em/processes.rb +123 -0
  80. data/lib/em/protocols.rb +37 -0
  81. data/lib/em/protocols/header_and_content.rb +138 -0
  82. data/lib/em/protocols/httpclient.rb +303 -0
  83. data/lib/em/protocols/httpclient2.rb +602 -0
  84. data/lib/em/protocols/line_and_text.rb +125 -0
  85. data/lib/em/protocols/line_protocol.rb +33 -0
  86. data/lib/em/protocols/linetext2.rb +179 -0
  87. data/lib/em/protocols/memcache.rb +331 -0
  88. data/lib/em/protocols/object_protocol.rb +46 -0
  89. data/lib/em/protocols/postgres3.rb +246 -0
  90. data/lib/em/protocols/saslauth.rb +175 -0
  91. data/lib/em/protocols/smtpclient.rb +394 -0
  92. data/lib/em/protocols/smtpserver.rb +666 -0
  93. data/lib/em/protocols/socks4.rb +66 -0
  94. data/lib/em/protocols/stomp.rb +205 -0
  95. data/lib/em/protocols/tcptest.rb +54 -0
  96. data/lib/em/pure_ruby.rb +1299 -0
  97. data/lib/em/queue.rb +80 -0
  98. data/lib/em/resolver.rb +232 -0
  99. data/lib/em/spawnable.rb +84 -0
  100. data/lib/em/streamer.rb +118 -0
  101. data/lib/em/threaded_resource.rb +90 -0
  102. data/lib/em/tick_loop.rb +85 -0
  103. data/lib/em/timers.rb +61 -0
  104. data/lib/em/version.rb +3 -0
  105. data/lib/eventmachine.rb +1602 -0
  106. data/lib/jeventmachine.rb +318 -0
  107. data/rakelib/package.rake +120 -0
  108. data/rakelib/test.rake +6 -0
  109. data/rakelib/test_pure.rake +11 -0
  110. data/tests/client.crt +31 -0
  111. data/tests/client.key +51 -0
  112. data/tests/dhparam.pem +13 -0
  113. data/tests/em_ssl_handlers.rb +153 -0
  114. data/tests/em_test_helper.rb +198 -0
  115. data/tests/jruby/test_jeventmachine.rb +38 -0
  116. data/tests/test_attach.rb +199 -0
  117. data/tests/test_basic.rb +321 -0
  118. data/tests/test_channel.rb +75 -0
  119. data/tests/test_completion.rb +178 -0
  120. data/tests/test_connection_count.rb +83 -0
  121. data/tests/test_connection_write.rb +35 -0
  122. data/tests/test_defer.rb +35 -0
  123. data/tests/test_deferrable.rb +35 -0
  124. data/tests/test_epoll.rb +141 -0
  125. data/tests/test_error_handler.rb +38 -0
  126. data/tests/test_exc.rb +37 -0
  127. data/tests/test_file_watch.rb +86 -0
  128. data/tests/test_fork.rb +75 -0
  129. data/tests/test_futures.rb +170 -0
  130. data/tests/test_handler_check.rb +35 -0
  131. data/tests/test_hc.rb +155 -0
  132. data/tests/test_httpclient.rb +238 -0
  133. data/tests/test_httpclient2.rb +132 -0
  134. data/tests/test_idle_connection.rb +31 -0
  135. data/tests/test_inactivity_timeout.rb +102 -0
  136. data/tests/test_io_streamer.rb +47 -0
  137. data/tests/test_ipv4.rb +96 -0
  138. data/tests/test_ipv6.rb +107 -0
  139. data/tests/test_iterator.rb +122 -0
  140. data/tests/test_kb.rb +28 -0
  141. data/tests/test_keepalive.rb +113 -0
  142. data/tests/test_line_protocol.rb +33 -0
  143. data/tests/test_ltp.rb +155 -0
  144. data/tests/test_ltp2.rb +332 -0
  145. data/tests/test_many_fds.rb +21 -0
  146. data/tests/test_next_tick.rb +104 -0
  147. data/tests/test_object_protocol.rb +36 -0
  148. data/tests/test_pause.rb +109 -0
  149. data/tests/test_pending_connect_timeout.rb +52 -0
  150. data/tests/test_pool.rb +196 -0
  151. data/tests/test_process_watch.rb +50 -0
  152. data/tests/test_processes.rb +128 -0
  153. data/tests/test_proxy_connection.rb +180 -0
  154. data/tests/test_pure.rb +156 -0
  155. data/tests/test_queue.rb +64 -0
  156. data/tests/test_resolver.rb +129 -0
  157. data/tests/test_running.rb +14 -0
  158. data/tests/test_sasl.rb +46 -0
  159. data/tests/test_send_file.rb +217 -0
  160. data/tests/test_servers.rb +32 -0
  161. data/tests/test_shutdown_hooks.rb +23 -0
  162. data/tests/test_smtpclient.rb +75 -0
  163. data/tests/test_smtpserver.rb +90 -0
  164. data/tests/test_sock_opt.rb +53 -0
  165. data/tests/test_spawn.rb +290 -0
  166. data/tests/test_ssl_args.rb +41 -0
  167. data/tests/test_ssl_dhparam.rb +57 -0
  168. data/tests/test_ssl_ecdh_curve.rb +57 -0
  169. data/tests/test_ssl_extensions.rb +24 -0
  170. data/tests/test_ssl_methods.rb +31 -0
  171. data/tests/test_ssl_protocols.rb +190 -0
  172. data/tests/test_ssl_verify.rb +52 -0
  173. data/tests/test_stomp.rb +38 -0
  174. data/tests/test_system.rb +46 -0
  175. data/tests/test_threaded_resource.rb +68 -0
  176. data/tests/test_tick_loop.rb +58 -0
  177. data/tests/test_timers.rb +150 -0
  178. data/tests/test_ud.rb +8 -0
  179. data/tests/test_unbind_reason.rb +40 -0
  180. metadata +384 -0
@@ -0,0 +1,2378 @@
1
+ /*****************************************************************************
2
+
3
+ $Id$
4
+
5
+ File: em.cpp
6
+ Date: 06Apr06
7
+
8
+ Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
9
+ Gmail: blackhedd
10
+
11
+ This program is free software; you can redistribute it and/or modify
12
+ it under the terms of either: 1) the GNU General Public License
13
+ as published by the Free Software Foundation; either version 2 of the
14
+ License, or (at your option) any later version; or 2) Ruby's License.
15
+
16
+ See the file COPYING for complete licensing information.
17
+
18
+ *****************************************************************************/
19
+
20
+ // THIS ENTIRE FILE WILL EVENTUALLY BE FOR UNIX BUILDS ONLY.
21
+ //#ifdef OS_UNIX
22
+
23
+ #include "project.h"
24
+
25
+ /* The numer of max outstanding timers was once a const enum defined in em.h.
26
+ * Now we define it here so that users can change its value if necessary.
27
+ */
28
+ static unsigned int MaxOutstandingTimers = 100000;
29
+
30
+ /* The number of accept() done at once in a single tick when the acceptor
31
+ * socket becomes readable.
32
+ */
33
+ static unsigned int SimultaneousAcceptCount = 10;
34
+
35
+ /* Internal helper to create a socket with SOCK_CLOEXEC set, and fall
36
+ * back to fcntl'ing it if the headers/runtime don't support it.
37
+ */
38
+ SOCKET EmSocket (int domain, int type, int protocol)
39
+ {
40
+ SOCKET sd;
41
+ #ifdef HAVE_SOCKET_CLOEXEC
42
+ sd = socket (domain, type | SOCK_CLOEXEC, protocol);
43
+ if (sd == INVALID_SOCKET) {
44
+ sd = socket (domain, type, protocol);
45
+ if (sd < 0) {
46
+ return sd;
47
+ }
48
+ SetFdCloexec(sd);
49
+ }
50
+ #else
51
+ sd = socket (domain, type, protocol);
52
+ if (sd == INVALID_SOCKET) {
53
+ return sd;
54
+ }
55
+ SetFdCloexec(sd);
56
+ #endif
57
+ return sd;
58
+ }
59
+
60
+
61
+ /***************************************
62
+ STATIC EventMachine_t::GetMaxTimerCount
63
+ ***************************************/
64
+
65
+ int EventMachine_t::GetMaxTimerCount()
66
+ {
67
+ return MaxOutstandingTimers;
68
+ }
69
+
70
+
71
+ /***************************************
72
+ STATIC EventMachine_t::SetMaxTimerCount
73
+ ***************************************/
74
+
75
+ void EventMachine_t::SetMaxTimerCount (int count)
76
+ {
77
+ /* Allow a user to increase the maximum number of outstanding timers.
78
+ * If this gets "too high" (a metric that is of course platform dependent),
79
+ * bad things will happen like performance problems and possible overuse
80
+ * of memory.
81
+ * The actual timer mechanism is very efficient so it's hard to know what
82
+ * the practical max, but 100,000 shouldn't be too problematical.
83
+ */
84
+ if (count < 100)
85
+ count = 100;
86
+ MaxOutstandingTimers = count;
87
+ }
88
+
89
+ int EventMachine_t::GetSimultaneousAcceptCount()
90
+ {
91
+ return SimultaneousAcceptCount;
92
+ }
93
+
94
+ void EventMachine_t::SetSimultaneousAcceptCount (int count)
95
+ {
96
+ if (count < 1)
97
+ count = 1;
98
+ SimultaneousAcceptCount = count;
99
+ }
100
+
101
+
102
+ /******************************
103
+ EventMachine_t::EventMachine_t
104
+ ******************************/
105
+
106
+ EventMachine_t::EventMachine_t (EMCallback event_callback, Poller_t poller):
107
+ NumCloseScheduled (0),
108
+ HeartbeatInterval(2000000),
109
+ EventCallback (event_callback),
110
+ LoopBreakerReader (INVALID_SOCKET),
111
+ LoopBreakerWriter (INVALID_SOCKET),
112
+ bTerminateSignalReceived (false),
113
+ Poller (poller),
114
+ epfd (-1),
115
+ kqfd (-1)
116
+ #ifdef HAVE_INOTIFY
117
+ , inotify (NULL)
118
+ #endif
119
+ {
120
+ // Default time-slice is just smaller than one hundred mills.
121
+ Quantum.tv_sec = 0;
122
+ Quantum.tv_usec = 90000;
123
+
124
+ // Override the requested poller back to default if needed.
125
+ #if !defined(HAVE_EPOLL) && !defined(HAVE_KQUEUE)
126
+ Poller = Poller_Default;
127
+ #endif
128
+
129
+ /* Initialize monotonic timekeeping on OS X before the first call to GetRealTime */
130
+ #ifdef OS_DARWIN
131
+ (void) mach_timebase_info(&mach_timebase);
132
+ #endif
133
+
134
+ #ifdef OS_WIN32
135
+ TickCountTickover = 0;
136
+ LastTickCount = 0;
137
+ #endif
138
+
139
+ // Make sure the current loop time is sane, in case we do any initializations of
140
+ // objects before we start running.
141
+ _UpdateTime();
142
+
143
+ /* We initialize the network library here (only on Windows of course)
144
+ * and initialize "loop breakers." Our destructor also does some network-level
145
+ * cleanup. There's thus an implicit assumption that any given instance of EventMachine_t
146
+ * will only call ::Run once. Is that a good assumption? Should we move some of these
147
+ * inits and de-inits into ::Run?
148
+ */
149
+ #ifdef OS_WIN32
150
+ WSADATA w;
151
+ WSAStartup (MAKEWORD (1, 1), &w);
152
+ #endif
153
+
154
+ _InitializeLoopBreaker();
155
+ SelectData = new SelectData_t();
156
+ }
157
+
158
+
159
+ /*******************************
160
+ EventMachine_t::~EventMachine_t
161
+ *******************************/
162
+
163
+ EventMachine_t::~EventMachine_t()
164
+ {
165
+ // Run down descriptors
166
+ size_t i;
167
+ for (i = 0; i < NewDescriptors.size(); i++)
168
+ delete NewDescriptors[i];
169
+ for (i = 0; i < Descriptors.size(); i++)
170
+ delete Descriptors[i];
171
+
172
+ close (LoopBreakerReader);
173
+ close (LoopBreakerWriter);
174
+
175
+ // Remove any file watch descriptors
176
+ while(!Files.empty()) {
177
+ std::map<int, Bindable_t*>::iterator f = Files.begin();
178
+ UnwatchFile (f->first);
179
+ }
180
+
181
+ if (epfd != -1)
182
+ close (epfd);
183
+ if (kqfd != -1)
184
+ close (kqfd);
185
+
186
+ delete SelectData;
187
+ }
188
+
189
+
190
+ /****************************
191
+ EventMachine_t::ScheduleHalt
192
+ ****************************/
193
+
194
+ void EventMachine_t::ScheduleHalt()
195
+ {
196
+ /* This is how we stop the machine.
197
+ * This can be called by clients. Signal handlers will probably
198
+ * set the global flag.
199
+ * For now this means there can only be one EventMachine ever running at a time.
200
+ *
201
+ * IMPORTANT: keep this light, fast, and async-safe. Don't do anything frisky in here,
202
+ * because it may be called from signal handlers invoked from code that we don't
203
+ * control. At this writing (20Sep06), EM does NOT install any signal handlers of
204
+ * its own.
205
+ *
206
+ * We need a FAQ. And one of the questions is: how do I stop EM when Ctrl-C happens?
207
+ * The answer is to call evma_stop_machine, which calls here, from a SIGINT handler.
208
+ */
209
+ bTerminateSignalReceived = true;
210
+
211
+ /* Signal the loopbreaker so we break out of long-running select/epoll/kqueue and
212
+ * notice the halt boolean is set. Signalling the loopbreaker also uses a single
213
+ * signal-safe syscall.
214
+ */
215
+ SignalLoopBreaker();
216
+ }
217
+
218
+ bool EventMachine_t::Stopping()
219
+ {
220
+ return bTerminateSignalReceived;
221
+ }
222
+
223
+ /*******************************
224
+ EventMachine_t::GetTimerQuantum
225
+ *******************************/
226
+
227
+ uint64_t EventMachine_t::GetTimerQuantum()
228
+ {
229
+ /* Convert timer-quantum to microseconds */
230
+ return (Quantum.tv_sec * 1000 + (Quantum.tv_usec + 500) / 1000) * 1000;
231
+ }
232
+
233
+ /*******************************
234
+ EventMachine_t::SetTimerQuantum
235
+ *******************************/
236
+
237
+ void EventMachine_t::SetTimerQuantum (int interval)
238
+ {
239
+ /* We get a timer-quantum expressed in milliseconds.
240
+ */
241
+
242
+ if ((interval < 5) || (interval > 5*60*1000))
243
+ throw std::runtime_error ("invalid timer-quantum");
244
+
245
+ Quantum.tv_sec = interval / 1000;
246
+ Quantum.tv_usec = (interval % 1000) * 1000;
247
+ }
248
+
249
+
250
+ /*************************************
251
+ (STATIC) EventMachine_t::SetuidString
252
+ *************************************/
253
+
254
+ #ifdef OS_UNIX
255
+ void EventMachine_t::SetuidString (const char *username)
256
+ {
257
+ /* This method takes a caller-supplied username and tries to setuid
258
+ * to that user. There is no meaningful implementation (and no error)
259
+ * on Windows. On Unix, a failure to setuid the caller-supplied string
260
+ * causes a fatal abort, because presumably the program is calling here
261
+ * in order to fulfill a security requirement. If we fail silently,
262
+ * the user may continue to run with too much privilege.
263
+ *
264
+ * TODO, we need to decide on and document a way of generating C++ level errors
265
+ * that can be wrapped in documented Ruby exceptions, so users can catch
266
+ * and handle them. And distinguish it from errors that we WON'T let the Ruby
267
+ * user catch (like security-violations and resource-overallocation).
268
+ * A setuid failure here would be in the latter category.
269
+ */
270
+
271
+ if (!username || !*username)
272
+ throw std::runtime_error ("setuid_string failed: no username specified");
273
+
274
+ errno = 0;
275
+ struct passwd *p = getpwnam (username);
276
+ if (!p) {
277
+ if (errno) {
278
+ char buf[200];
279
+ snprintf (buf, sizeof(buf)-1, "setuid_string failed: %s", strerror(errno));
280
+ throw std::runtime_error (buf);
281
+ } else {
282
+ throw std::runtime_error ("setuid_string failed: unknown username");
283
+ }
284
+ }
285
+
286
+ if (setuid (p->pw_uid) != 0)
287
+ throw std::runtime_error ("setuid_string failed: no setuid");
288
+
289
+ // Success.
290
+ }
291
+ #else
292
+ void EventMachine_t::SetuidString (const char *username UNUSED) { }
293
+ #endif
294
+
295
+ /****************************************
296
+ (STATIC) EventMachine_t::SetRlimitNofile
297
+ ****************************************/
298
+
299
+ #ifdef OS_UNIX
300
+ int EventMachine_t::SetRlimitNofile (int nofiles)
301
+ {
302
+ struct rlimit rlim;
303
+ getrlimit (RLIMIT_NOFILE, &rlim);
304
+ if (nofiles >= 0) {
305
+ rlim.rlim_cur = nofiles;
306
+ if ((unsigned int)nofiles > rlim.rlim_max)
307
+ rlim.rlim_max = nofiles;
308
+ setrlimit (RLIMIT_NOFILE, &rlim);
309
+ // ignore the error return, for now at least.
310
+ // TODO, emit an error message someday when we have proper debug levels.
311
+ }
312
+ getrlimit (RLIMIT_NOFILE, &rlim);
313
+ return rlim.rlim_cur;
314
+ }
315
+ #else
316
+ int EventMachine_t::SetRlimitNofile (int nofiles UNUSED) { return 0; }
317
+ #endif
318
+
319
+ /*********************************
320
+ EventMachine_t::SignalLoopBreaker
321
+ *********************************/
322
+
323
+ void EventMachine_t::SignalLoopBreaker()
324
+ {
325
+ #ifdef OS_UNIX
326
+ (void)write (LoopBreakerWriter, "", 1);
327
+ #endif
328
+ #ifdef OS_WIN32
329
+ sendto (LoopBreakerReader, "", 0, 0, (struct sockaddr*)&(LoopBreakerTarget), sizeof(LoopBreakerTarget));
330
+ #endif
331
+ }
332
+
333
+
334
+ /**************************************
335
+ EventMachine_t::_InitializeLoopBreaker
336
+ **************************************/
337
+
338
+ void EventMachine_t::_InitializeLoopBreaker()
339
+ {
340
+ /* A "loop-breaker" is a socket-descriptor that we can write to in order
341
+ * to break the main select loop. Primarily useful for things running on
342
+ * threads other than the main EM thread, so they can trigger processing
343
+ * of events that arise exogenously to the EM.
344
+ * Keep the loop-breaker pipe out of the main descriptor set, otherwise
345
+ * its events will get passed on to user code.
346
+ */
347
+
348
+ #ifdef OS_UNIX
349
+ int fd[2];
350
+ #if defined (HAVE_CLOEXEC) && defined (HAVE_PIPE2)
351
+ int pipestatus = pipe2(fd, O_CLOEXEC);
352
+ if (pipestatus < 0) {
353
+ if (pipe(fd))
354
+ throw std::runtime_error (strerror(errno));
355
+ }
356
+ #else
357
+ if (pipe (fd))
358
+ throw std::runtime_error (strerror(errno));
359
+ #endif
360
+ if (!SetFdCloexec(fd[0]) || !SetFdCloexec(fd[1]))
361
+ throw std::runtime_error (strerror(errno));
362
+
363
+ LoopBreakerWriter = fd[1];
364
+ LoopBreakerReader = fd[0];
365
+
366
+ /* 16Jan11: Make sure the pipe is non-blocking, so more than 65k loopbreaks
367
+ * in one tick do not fill up the pipe and block the process on write() */
368
+ SetSocketNonblocking (LoopBreakerWriter);
369
+ #endif
370
+
371
+ #ifdef OS_WIN32
372
+ SOCKET sd = EmSocket (AF_INET, SOCK_DGRAM, 0);
373
+ if (sd == INVALID_SOCKET)
374
+ throw std::runtime_error ("no loop breaker socket");
375
+ SetSocketNonblocking (sd);
376
+
377
+ memset (&LoopBreakerTarget, 0, sizeof(LoopBreakerTarget));
378
+ LoopBreakerTarget.sin_family = AF_INET;
379
+ LoopBreakerTarget.sin_addr.s_addr = inet_addr ("127.0.0.1");
380
+
381
+ srand ((int)time(NULL));
382
+ int i;
383
+ for (i=0; i < 100; i++) {
384
+ int r = (rand() % 10000) + 20000;
385
+ LoopBreakerTarget.sin_port = htons (r);
386
+ if (bind (sd, (struct sockaddr*)&LoopBreakerTarget, sizeof(LoopBreakerTarget)) == 0)
387
+ break;
388
+ }
389
+
390
+ if (i == 100)
391
+ throw std::runtime_error ("no loop breaker");
392
+ LoopBreakerReader = sd;
393
+ #endif
394
+
395
+ #ifdef HAVE_EPOLL
396
+ if (Poller == Poller_Epoll) {
397
+ epfd = epoll_create1(EPOLL_CLOEXEC);
398
+ if (epfd == -1) {
399
+ char buf[200];
400
+ snprintf (buf, sizeof(buf)-1, "unable to create epoll descriptor: %s", strerror(errno));
401
+ throw std::runtime_error (buf);
402
+ }
403
+
404
+ assert (LoopBreakerReader >= 0);
405
+ LoopbreakDescriptor *ld = new LoopbreakDescriptor (LoopBreakerReader, this);
406
+ assert (ld);
407
+ Add (ld);
408
+ }
409
+ #endif
410
+
411
+ #ifdef HAVE_KQUEUE
412
+ if (Poller == Poller_Kqueue) {
413
+ kqfd = kqueue();
414
+ if (kqfd == -1) {
415
+ char buf[200];
416
+ snprintf (buf, sizeof(buf)-1, "unable to create kqueue descriptor: %s", strerror(errno));
417
+ throw std::runtime_error (buf);
418
+ }
419
+ // cloexec not needed. By definition, kqueues are not carried across forks.
420
+
421
+ assert (LoopBreakerReader >= 0);
422
+ LoopbreakDescriptor *ld = new LoopbreakDescriptor (LoopBreakerReader, this);
423
+ assert (ld);
424
+ Add (ld);
425
+ }
426
+ #endif
427
+ }
428
+
429
+ /***************************
430
+ EventMachine_t::_UpdateTime
431
+ ***************************/
432
+
433
+ void EventMachine_t::_UpdateTime()
434
+ {
435
+ MyCurrentLoopTime = GetRealTime();
436
+ }
437
+
438
+ /***************************
439
+ EventMachine_t::GetRealTime
440
+ ***************************/
441
+
442
+ // Two great writeups of cross-platform monotonic time are at:
443
+ // http://www.python.org/dev/peps/pep-0418
444
+ // http://nadeausoftware.com/articles/2012/04/c_c_tip_how_measure_elapsed_real_time_benchmarking
445
+ // Uncomment the #pragma messages to confirm which compile-time option was used
446
+ uint64_t EventMachine_t::GetRealTime()
447
+ {
448
+ uint64_t current_time;
449
+
450
+ #if defined(HAVE_CONST_CLOCK_MONOTONIC_RAW)
451
+ // #pragma message "GetRealTime: clock_gettime CLOCK_MONOTONIC_RAW"
452
+ // Linux 2.6.28 and above
453
+ struct timespec tv;
454
+ clock_gettime (CLOCK_MONOTONIC_RAW, &tv);
455
+ current_time = (((uint64_t)(tv.tv_sec)) * 1000000LL) + ((uint64_t)((tv.tv_nsec)/1000));
456
+
457
+ #elif defined(HAVE_CONST_CLOCK_MONOTONIC)
458
+ // #pragma message "GetRealTime: clock_gettime CLOCK_MONOTONIC"
459
+ // Linux, FreeBSD 5.0 and above, Solaris 8 and above, OpenBSD, NetBSD, DragonflyBSD
460
+ struct timespec tv;
461
+ clock_gettime (CLOCK_MONOTONIC, &tv);
462
+ current_time = (((uint64_t)(tv.tv_sec)) * 1000000LL) + ((uint64_t)((tv.tv_nsec)/1000));
463
+
464
+ #elif defined(HAVE_GETHRTIME)
465
+ // #pragma message "GetRealTime: gethrtime"
466
+ // Solaris and HP-UX
467
+ current_time = (uint64_t)gethrtime() / 1000;
468
+
469
+ #elif defined(OS_DARWIN)
470
+ // #pragma message "GetRealTime: mach_absolute_time"
471
+ // Mac OS X
472
+ // https://developer.apple.com/library/mac/qa/qa1398/_index.html
473
+ current_time = mach_absolute_time() * mach_timebase.numer / mach_timebase.denom / 1000;
474
+
475
+ #elif defined(OS_UNIX)
476
+ // #pragma message "GetRealTime: gettimeofday"
477
+ // Unix fallback
478
+ struct timeval tv;
479
+ gettimeofday (&tv, NULL);
480
+ current_time = (((uint64_t)(tv.tv_sec)) * 1000000LL) + ((uint64_t)(tv.tv_usec));
481
+
482
+ #elif defined(OS_WIN32)
483
+ // #pragma message "GetRealTime: GetTickCount"
484
+ // Future improvement: use GetTickCount64 in Windows Vista / Server 2008
485
+ unsigned tick = GetTickCount();
486
+ if (tick < LastTickCount)
487
+ TickCountTickover += 1;
488
+ LastTickCount = tick;
489
+ current_time = ((uint64_t)TickCountTickover << 32) + (uint64_t)tick;
490
+ current_time *= 1000; // convert to microseconds
491
+
492
+ #else
493
+ // #pragma message "GetRealTime: time"
494
+ // Universal fallback
495
+ current_time = (uint64_t)time(NULL) * 1000000LL;
496
+ #endif
497
+
498
+ return current_time;
499
+ }
500
+
501
+ /***********************************
502
+ EventMachine_t::_DispatchHeartbeats
503
+ ***********************************/
504
+
505
+ void EventMachine_t::_DispatchHeartbeats()
506
+ {
507
+ // Store the first processed heartbeat descriptor and bail out if
508
+ // we see it again. This fixes an infinite loop in case the system time
509
+ // is changed out from underneath MyCurrentLoopTime.
510
+ const EventableDescriptor *head = NULL;
511
+
512
+ while (true) {
513
+ std::multimap<uint64_t,EventableDescriptor*>::iterator i = Heartbeats.begin();
514
+ if (i == Heartbeats.end())
515
+ break;
516
+ if (i->first > MyCurrentLoopTime)
517
+ break;
518
+
519
+ EventableDescriptor *ed = i->second;
520
+ if (ed == head)
521
+ break;
522
+
523
+ ed->Heartbeat();
524
+ QueueHeartbeat(ed);
525
+
526
+ if (head == NULL)
527
+ head = ed;
528
+ }
529
+ }
530
+
531
+ /******************************
532
+ EventMachine_t::QueueHeartbeat
533
+ ******************************/
534
+
535
+ void EventMachine_t::QueueHeartbeat(EventableDescriptor *ed)
536
+ {
537
+ uint64_t heartbeat = ed->GetNextHeartbeat();
538
+
539
+ if (heartbeat) {
540
+ #ifndef HAVE_MAKE_PAIR
541
+ Heartbeats.insert (std::multimap<uint64_t,EventableDescriptor*>::value_type (heartbeat, ed));
542
+ #else
543
+ Heartbeats.insert (std::make_pair (heartbeat, ed));
544
+ #endif
545
+ }
546
+ }
547
+
548
+ /******************************
549
+ EventMachine_t::ClearHeartbeat
550
+ ******************************/
551
+
552
+ void EventMachine_t::ClearHeartbeat(uint64_t key, EventableDescriptor* ed)
553
+ {
554
+ std::multimap<uint64_t,EventableDescriptor*>::iterator it;
555
+ std::pair<std::multimap<uint64_t,EventableDescriptor*>::iterator,std::multimap<uint64_t,EventableDescriptor*>::iterator> ret;
556
+ ret = Heartbeats.equal_range (key);
557
+ for (it = ret.first; it != ret.second; ++it) {
558
+ if (it->second == ed) {
559
+ Heartbeats.erase (it);
560
+ break;
561
+ }
562
+ }
563
+ }
564
+
565
+ /*******************
566
+ EventMachine_t::Run
567
+ *******************/
568
+
569
+ void EventMachine_t::Run()
570
+ {
571
+ while (RunOnce()) ;
572
+ }
573
+
574
+ /***********************
575
+ EventMachine_t::RunOnce
576
+ ***********************/
577
+
578
+ bool EventMachine_t::RunOnce()
579
+ {
580
+ _UpdateTime();
581
+ _RunTimers();
582
+
583
+ /* _Add must precede _Modify because the same descriptor might
584
+ * be on both lists during the same pass through the machine,
585
+ * and to modify a descriptor before adding it would fail.
586
+ */
587
+ _AddNewDescriptors();
588
+ _ModifyDescriptors();
589
+
590
+ switch (Poller) {
591
+ case Poller_Epoll:
592
+ _RunEpollOnce();
593
+ break;
594
+ case Poller_Kqueue:
595
+ _RunKqueueOnce();
596
+ break;
597
+ case Poller_Default:
598
+ _RunSelectOnce();
599
+ break;
600
+ }
601
+
602
+ _DispatchHeartbeats();
603
+ _CleanupSockets();
604
+
605
+ if (bTerminateSignalReceived)
606
+ return false;
607
+
608
+ return true;
609
+ }
610
+
611
+
612
+ #ifdef HAVE_EPOLL
613
+ typedef struct {
614
+ int epfd;
615
+ struct epoll_event *events;
616
+ int maxevents;
617
+ int timeout;
618
+ } epoll_args_t;
619
+
620
+ static void *nogvl_epoll_wait(void *args)
621
+ {
622
+ epoll_args_t *a = (epoll_args_t *)args;
623
+ return (void *) (uintptr_t) epoll_wait (a->epfd, a->events, a->maxevents, a->timeout);
624
+ }
625
+ #endif
626
+
627
+ /*****************************
628
+ EventMachine_t::_RunEpollOnce
629
+ *****************************/
630
+
631
+ void EventMachine_t::_RunEpollOnce()
632
+ {
633
+ #ifdef HAVE_EPOLL
634
+ assert (epfd != -1);
635
+ int s;
636
+
637
+ timeval tv = _TimeTilNextEvent();
638
+
639
+ #ifdef BUILD_FOR_RUBY
640
+ int ret = 0;
641
+
642
+ if ((ret = rb_wait_for_single_fd(epfd, RB_WAITFD_IN|RB_WAITFD_PRI, &tv)) < 1) {
643
+ if (ret == -1) {
644
+ assert(errno != EINVAL);
645
+ assert(errno != EBADF);
646
+ }
647
+ return;
648
+ }
649
+
650
+ epoll_args_t epoll_args = { epfd, epoll_events, MaxEvents, 0 };
651
+ s = (uintptr_t) rb_thread_call_without_gvl (nogvl_epoll_wait, &epoll_args, RUBY_UBF_IO, 0);
652
+ #else
653
+ int duration = 0;
654
+ duration = duration + (tv.tv_sec * 1000);
655
+ duration = duration + (tv.tv_usec / 1000);
656
+ s = epoll_wait (epfd, epoll_events, MaxEvents, duration);
657
+ #endif
658
+
659
+ if (s > 0) {
660
+ for (int i=0; i < s; i++) {
661
+ EventableDescriptor *ed = (EventableDescriptor*) epoll_events[i].data.ptr;
662
+
663
+ if (ed->IsWatchOnly() && ed->GetSocket() == INVALID_SOCKET)
664
+ continue;
665
+
666
+ assert(ed->GetSocket() != INVALID_SOCKET);
667
+
668
+ if (epoll_events[i].events & EPOLLIN)
669
+ ed->Read();
670
+ if (epoll_events[i].events & EPOLLOUT)
671
+ ed->Write();
672
+ if (epoll_events[i].events & (EPOLLERR | EPOLLHUP))
673
+ ed->HandleError();
674
+ }
675
+ }
676
+ else if (s < 0) {
677
+ // epoll_wait can fail on error in a handful of ways.
678
+ // If this happens, then wait for a little while to avoid busy-looping.
679
+ // If the error was EINTR, we probably caught SIGCHLD or something,
680
+ // so keep the wait short.
681
+ timeval tv = {0, ((errno == EINTR) ? 5 : 50) * 1000};
682
+ EmSelect (0, NULL, NULL, NULL, &tv);
683
+ }
684
+ #else
685
+ throw std::runtime_error ("epoll is not implemented on this platform");
686
+ #endif
687
+ }
688
+
689
+
690
+ #ifdef HAVE_KQUEUE
691
+ typedef struct {
692
+ int kqfd;
693
+ const struct kevent *changelist;
694
+ int nchanges;
695
+ struct kevent *eventlist;
696
+ int nevents;
697
+ const struct timespec *timeout;
698
+ } kevent_args_t;
699
+
700
+ static void *nogvl_kevent(void *args)
701
+ {
702
+ kevent_args_t *a = (kevent_args_t *)args;
703
+ return (void *) (uintptr_t) kevent (a->kqfd, a->changelist, a->nchanges, a->eventlist, a->nevents, a->timeout);
704
+ }
705
+ #endif
706
+
707
+ /******************************
708
+ EventMachine_t::_RunKqueueOnce
709
+ ******************************/
710
+
711
+ #ifdef HAVE_KQUEUE
712
+ void EventMachine_t::_RunKqueueOnce()
713
+ {
714
+ assert (kqfd != -1);
715
+ int k;
716
+
717
+ timeval tv = _TimeTilNextEvent();
718
+
719
+ struct timespec ts;
720
+ ts.tv_sec = tv.tv_sec;
721
+ ts.tv_nsec = tv.tv_usec * 1000;
722
+
723
+ #ifdef BUILD_FOR_RUBY
724
+ int ret = 0;
725
+
726
+ if ((ret = rb_wait_for_single_fd(kqfd, RB_WAITFD_IN|RB_WAITFD_PRI, &tv)) < 1) {
727
+ if (ret == -1) {
728
+ assert(errno != EINVAL);
729
+ assert(errno != EBADF);
730
+ }
731
+ return;
732
+ }
733
+
734
+ ts.tv_sec = ts.tv_nsec = 0;
735
+ kevent_args_t kevent_args = { kqfd, NULL, 0, Karray, MaxEvents, &ts };
736
+ k = (uintptr_t) rb_thread_call_without_gvl (nogvl_kevent, &kevent_args, RUBY_UBF_IO, 0);
737
+ #else
738
+ k = kevent (kqfd, NULL, 0, Karray, MaxEvents, &ts);
739
+ #endif
740
+
741
+ struct kevent *ke = Karray;
742
+ while (k > 0) {
743
+ switch (ke->filter)
744
+ {
745
+ case EVFILT_VNODE:
746
+ _HandleKqueueFileEvent (ke);
747
+ break;
748
+
749
+ case EVFILT_PROC:
750
+ _HandleKqueuePidEvent (ke);
751
+ break;
752
+
753
+ case EVFILT_READ:
754
+ case EVFILT_WRITE:
755
+ EventableDescriptor *ed = (EventableDescriptor*) (ke->udata);
756
+ assert (ed);
757
+
758
+ if (ed->IsWatchOnly() && ed->GetSocket() == INVALID_SOCKET)
759
+ break;
760
+
761
+ if (ke->filter == EVFILT_READ)
762
+ ed->Read();
763
+ else if (ke->filter == EVFILT_WRITE)
764
+ ed->Write();
765
+ else
766
+ std::cerr << "Discarding unknown kqueue event " << ke->filter << std::endl;
767
+
768
+ break;
769
+ }
770
+
771
+ --k;
772
+ ++ke;
773
+ }
774
+
775
+ #ifdef BUILD_FOR_RUBY
776
+ if (!rb_thread_alone()) {
777
+ rb_thread_schedule();
778
+ }
779
+ #endif
780
+ }
781
+ #else
782
+ void EventMachine_t::_RunKqueueOnce()
783
+ {
784
+ throw std::runtime_error ("kqueue is not implemented on this platform");
785
+ }
786
+ #endif
787
+
788
+
789
+ /*********************************
790
+ EventMachine_t::_TimeTilNextEvent
791
+ *********************************/
792
+
793
+ timeval EventMachine_t::_TimeTilNextEvent()
794
+ {
795
+ // 29jul11: Changed calculation base from MyCurrentLoopTime to the
796
+ // real time. As MyCurrentLoopTime is set at the beginning of an
797
+ // iteration and this calculation is done at the end, evenmachine
798
+ // will potentially oversleep by the amount of time the iteration
799
+ // took to execute.
800
+ uint64_t next_event = 0;
801
+ uint64_t current_time = GetRealTime();
802
+
803
+ if (!Heartbeats.empty()) {
804
+ std::multimap<uint64_t,EventableDescriptor*>::iterator heartbeats = Heartbeats.begin();
805
+ next_event = heartbeats->first;
806
+ }
807
+
808
+ if (!Timers.empty()) {
809
+ std::multimap<uint64_t,Timer_t>::iterator timers = Timers.begin();
810
+ if (next_event == 0 || timers->first < next_event)
811
+ next_event = timers->first;
812
+ }
813
+
814
+ if (!NewDescriptors.empty() || !ModifiedDescriptors.empty()) {
815
+ next_event = current_time;
816
+ }
817
+
818
+ timeval tv;
819
+
820
+ if (NumCloseScheduled > 0 || bTerminateSignalReceived) {
821
+ tv.tv_sec = tv.tv_usec = 0;
822
+ } else if (next_event == 0) {
823
+ tv = Quantum;
824
+ } else {
825
+ if (next_event > current_time) {
826
+ uint64_t duration = next_event - current_time;
827
+ tv.tv_sec = duration / 1000000;
828
+ tv.tv_usec = duration % 1000000;
829
+ } else {
830
+ tv.tv_sec = tv.tv_usec = 0;
831
+ }
832
+ }
833
+
834
+ return tv;
835
+ }
836
+
837
+ /*******************************
838
+ EventMachine_t::_CleanupSockets
839
+ *******************************/
840
+
841
+ void EventMachine_t::_CleanupSockets()
842
+ {
843
+ // TODO, rip this out and only delete the descriptors we know have died,
844
+ // rather than traversing the whole list.
845
+ // Modified 05Jan08 per suggestions by Chris Heath. It's possible that
846
+ // an EventableDescriptor will have a descriptor value of -1. That will
847
+ // happen if EventableDescriptor::Close was called on it. In that case,
848
+ // don't call epoll_ctl to remove the socket's filters from the epoll set.
849
+ // According to the epoll docs, this happens automatically when the
850
+ // descriptor is closed anyway. This is different from the case where
851
+ // the socket has already been closed but the descriptor in the ED object
852
+ // hasn't yet been set to INVALID_SOCKET.
853
+ // In kqueue, closing a descriptor automatically removes its event filters.
854
+ int i, j;
855
+ int nSockets = Descriptors.size();
856
+ for (i=0, j=0; i < nSockets; i++) {
857
+ EventableDescriptor *ed = Descriptors[i];
858
+ assert (ed);
859
+ if (ed->ShouldDelete()) {
860
+ #ifdef HAVE_EPOLL
861
+ if (Poller == Poller_Epoll) {
862
+ assert (epfd != -1);
863
+ if (ed->GetSocket() != INVALID_SOCKET) {
864
+ int e = epoll_ctl (epfd, EPOLL_CTL_DEL, ed->GetSocket(), ed->GetEpollEvent());
865
+ // ENOENT or EBADF are not errors because the socket may be already closed when we get here.
866
+ if (e && (errno != ENOENT) && (errno != EBADF) && (errno != EPERM)) {
867
+ char buf [200];
868
+ snprintf (buf, sizeof(buf)-1, "unable to delete epoll event: %s", strerror(errno));
869
+ throw std::runtime_error (buf);
870
+ }
871
+ }
872
+ ModifiedDescriptors.erase(ed);
873
+ }
874
+ #endif
875
+ delete ed;
876
+ }
877
+ else
878
+ Descriptors [j++] = ed;
879
+ }
880
+ while ((size_t)j < Descriptors.size())
881
+ Descriptors.pop_back();
882
+ }
883
+
884
+ /*********************************
885
+ EventMachine_t::_ModifyEpollEvent
886
+ *********************************/
887
+
888
+ #ifdef HAVE_EPOLL
889
+ void EventMachine_t::_ModifyEpollEvent (EventableDescriptor *ed)
890
+ {
891
+ if (Poller == Poller_Epoll) {
892
+ assert (epfd != -1);
893
+ assert (ed);
894
+ assert (ed->GetSocket() != INVALID_SOCKET);
895
+ int e = epoll_ctl (epfd, EPOLL_CTL_MOD, ed->GetSocket(), ed->GetEpollEvent());
896
+ if (e) {
897
+ char buf [200];
898
+ snprintf (buf, sizeof(buf)-1, "unable to modify epoll event: %s", strerror(errno));
899
+ throw std::runtime_error (buf);
900
+ }
901
+ }
902
+ }
903
+ #else
904
+ void EventMachine_t::_ModifyEpollEvent (EventableDescriptor *ed UNUSED) { }
905
+ #endif
906
+
907
+
908
+ /**************************
909
+ SelectData_t::SelectData_t
910
+ **************************/
911
+
912
+ SelectData_t::SelectData_t()
913
+ {
914
+ maxsocket = 0;
915
+ rb_fd_init (&fdreads);
916
+ rb_fd_init (&fdwrites);
917
+ rb_fd_init (&fderrors);
918
+ }
919
+
920
+ SelectData_t::~SelectData_t()
921
+ {
922
+ rb_fd_term (&fdreads);
923
+ rb_fd_term (&fdwrites);
924
+ rb_fd_term (&fderrors);
925
+ }
926
+
927
+ /*********************
928
+ SelectData_t::_Select
929
+ *********************/
930
+
931
+ int SelectData_t::_Select()
932
+ {
933
+ return EmSelect (maxsocket + 1, &fdreads, &fdwrites, &fderrors, &tv);
934
+ }
935
+
936
+ void SelectData_t::_Clear()
937
+ {
938
+ maxsocket = 0;
939
+ rb_fd_zero (&fdreads);
940
+ rb_fd_zero (&fdwrites);
941
+ rb_fd_zero (&fderrors);
942
+ }
943
+
944
+ /******************************
945
+ EventMachine_t::_RunSelectOnce
946
+ ******************************/
947
+
948
+ void EventMachine_t::_RunSelectOnce()
949
+ {
950
+ // Crank the event machine once.
951
+ // If there are no descriptors to process, then sleep
952
+ // for a few hundred mills to avoid busy-looping.
953
+ // This is based on a select loop. Alternately provide epoll
954
+ // if we know we're running on a 2.6 kernel.
955
+ // epoll will be effective if we provide it as an alternative,
956
+ // however it has the same problem interoperating with Ruby
957
+ // threads that select does.
958
+
959
+ // Get ready for select()
960
+ SelectData->_Clear();
961
+
962
+ // Always read the loop-breaker reader.
963
+ // Changed 23Aug06, provisionally implemented for Windows with a UDP socket
964
+ // running on localhost with a randomly-chosen port. (*Puke*)
965
+ // Windows has a version of the Unix pipe() library function, but it doesn't
966
+ // give you back descriptors that are selectable.
967
+ rb_fd_set (LoopBreakerReader, &(SelectData->fdreads));
968
+ if (SelectData->maxsocket < LoopBreakerReader)
969
+ SelectData->maxsocket = LoopBreakerReader;
970
+
971
+ // prepare the sockets for reading and writing
972
+ size_t i;
973
+ for (i = 0; i < Descriptors.size(); i++) {
974
+ EventableDescriptor *ed = Descriptors[i];
975
+ assert (ed);
976
+ SOCKET sd = ed->GetSocket();
977
+ if (ed->IsWatchOnly() && sd == INVALID_SOCKET)
978
+ continue;
979
+ assert (sd != INVALID_SOCKET);
980
+
981
+ if (ed->SelectForRead())
982
+ rb_fd_set (sd, &(SelectData->fdreads));
983
+ if (ed->SelectForWrite())
984
+ rb_fd_set (sd, &(SelectData->fdwrites));
985
+
986
+ #ifdef OS_WIN32
987
+ /* 21Sep09: on windows, a non-blocking connect() that fails does not come up as writable.
988
+ Instead, it is added to the error set. See http://www.mail-archive.com/openssl-users@openssl.org/msg58500.html
989
+ */
990
+ if (ed->IsConnectPending())
991
+ rb_fd_set (sd, &(SelectData->fderrors));
992
+ #endif
993
+
994
+ if (SelectData->maxsocket < sd)
995
+ SelectData->maxsocket = sd;
996
+ }
997
+
998
+
999
+ { // read and write the sockets
1000
+ SelectData->tv = _TimeTilNextEvent();
1001
+ int s = SelectData->_Select();
1002
+ if (s > 0) {
1003
+ /* Changed 01Jun07. We used to handle the Loop-breaker right here.
1004
+ * Now we do it AFTER all the regular descriptors. There's an
1005
+ * incredibly important and subtle reason for this. Code on
1006
+ * loop breakers is sometimes used to cause the reactor core to
1007
+ * cycle (for example, to allow outbound network buffers to drain).
1008
+ * If a loop-breaker handler reschedules itself (say, after determining
1009
+ * that the write buffers are still too full), then it will execute
1010
+ * IMMEDIATELY if _ReadLoopBreaker is done here instead of after
1011
+ * the other descriptors are processed. That defeats the whole purpose.
1012
+ */
1013
+ for (i=0; i < Descriptors.size(); i++) {
1014
+ EventableDescriptor *ed = Descriptors[i];
1015
+ assert (ed);
1016
+ SOCKET sd = ed->GetSocket();
1017
+ if (ed->IsWatchOnly() && sd == INVALID_SOCKET)
1018
+ continue;
1019
+ assert (sd != INVALID_SOCKET);
1020
+
1021
+ if (rb_fd_isset (sd, &(SelectData->fdwrites))) {
1022
+ // Double-check SelectForWrite() still returns true. If not, one of the callbacks must have
1023
+ // modified some value since we checked SelectForWrite() earlier in this method.
1024
+ if (ed->SelectForWrite())
1025
+ ed->Write();
1026
+ }
1027
+ if (rb_fd_isset (sd, &(SelectData->fdreads)))
1028
+ ed->Read();
1029
+ if (rb_fd_isset (sd, &(SelectData->fderrors)))
1030
+ ed->HandleError();
1031
+ }
1032
+
1033
+ if (rb_fd_isset (LoopBreakerReader, &(SelectData->fdreads)))
1034
+ _ReadLoopBreaker();
1035
+ }
1036
+ else if (s < 0) {
1037
+ switch (errno) {
1038
+ case EBADF:
1039
+ _CleanBadDescriptors();
1040
+ break;
1041
+ case EINVAL:
1042
+ throw std::runtime_error ("Somehow EM passed an invalid nfds or invalid timeout to select(2), please report this!");
1043
+ break;
1044
+ default:
1045
+ // select can fail on error in a handful of ways.
1046
+ // If this happens, then wait for a little while to avoid busy-looping.
1047
+ // If the error was EINTR, we probably caught SIGCHLD or something,
1048
+ // so keep the wait short.
1049
+ timeval tv = {0, ((errno == EINTR) ? 5 : 50) * 1000};
1050
+ EmSelect (0, NULL, NULL, NULL, &tv);
1051
+ }
1052
+ }
1053
+ }
1054
+ }
1055
+
1056
+ void EventMachine_t::_CleanBadDescriptors()
1057
+ {
1058
+ size_t i;
1059
+
1060
+ for (i = 0; i < Descriptors.size(); i++) {
1061
+ EventableDescriptor *ed = Descriptors[i];
1062
+ if (ed->ShouldDelete())
1063
+ continue;
1064
+
1065
+ if (rb_wait_for_single_fd(ed->GetSocket(), RB_WAITFD_PRI, NULL) < 0) {
1066
+ if (errno == EBADF)
1067
+ ed->ScheduleClose(false);
1068
+ }
1069
+ }
1070
+ }
1071
+
1072
+ /********************************
1073
+ EventMachine_t::_ReadLoopBreaker
1074
+ ********************************/
1075
+
1076
+ void EventMachine_t::_ReadLoopBreaker()
1077
+ {
1078
+ /* The loop breaker has selected readable.
1079
+ * Read it ONCE (it may block if we try to read it twice)
1080
+ * and send a loop-break event back to user code.
1081
+ */
1082
+ char buffer [1024];
1083
+ (void)read (LoopBreakerReader, buffer, sizeof(buffer));
1084
+ if (EventCallback)
1085
+ (*EventCallback)(0, EM_LOOPBREAK_SIGNAL, "", 0);
1086
+ }
1087
+
1088
+
1089
+ /**************************
1090
+ EventMachine_t::_RunTimers
1091
+ **************************/
1092
+
1093
+ void EventMachine_t::_RunTimers()
1094
+ {
1095
+ // These are caller-defined timer handlers.
1096
+ // We rely on the fact that multimaps sort by their keys to avoid
1097
+ // inspecting the whole list every time we come here.
1098
+ // Just keep inspecting and processing the list head until we hit
1099
+ // one that hasn't expired yet.
1100
+
1101
+ while (true) {
1102
+ std::multimap<uint64_t,Timer_t>::iterator i = Timers.begin();
1103
+ if (i == Timers.end())
1104
+ break;
1105
+ if (i->first > MyCurrentLoopTime)
1106
+ break;
1107
+ if (EventCallback)
1108
+ (*EventCallback) (0, EM_TIMER_FIRED, NULL, i->second.GetBinding());
1109
+ Timers.erase (i);
1110
+ }
1111
+ }
1112
+
1113
+ /*********************************************
1114
+ EventMachine_t::_GetNumberOfOutstandingTimers
1115
+ *********************************************/
1116
+
1117
+ size_t EventMachine_t::GetTimerCount()
1118
+ {
1119
+ return Timers.size();
1120
+ }
1121
+
1122
+
1123
+ /***********************************
1124
+ EventMachine_t::InstallOneshotTimer
1125
+ ***********************************/
1126
+
1127
+ const uintptr_t EventMachine_t::InstallOneshotTimer (uint64_t milliseconds)
1128
+ {
1129
+ if (Timers.size() > MaxOutstandingTimers)
1130
+ return false;
1131
+
1132
+ uint64_t fire_at = GetRealTime();
1133
+ fire_at += ((uint64_t)milliseconds) * 1000LL;
1134
+
1135
+ Timer_t t;
1136
+ #ifndef HAVE_MAKE_PAIR
1137
+ std::multimap<uint64_t,Timer_t>::iterator i = Timers.insert (std::multimap<uint64_t,Timer_t>::value_type (fire_at, t));
1138
+ #else
1139
+ std::multimap<uint64_t,Timer_t>::iterator i = Timers.insert (std::make_pair (fire_at, t));
1140
+ #endif
1141
+ return i->second.GetBinding();
1142
+ }
1143
+
1144
+
1145
+ /*******************************
1146
+ EventMachine_t::ConnectToServer
1147
+ *******************************/
1148
+
1149
+ const uintptr_t EventMachine_t::ConnectToServer (const char *bind_addr, int bind_port, const char *server, int port)
1150
+ {
1151
+ /* We want to spend no more than a few seconds waiting for a connection
1152
+ * to a remote host. So we use a nonblocking connect.
1153
+ * Linux disobeys the usual rules for nonblocking connects.
1154
+ * Per Stevens (UNP p.410), you expect a nonblocking connect to select
1155
+ * both readable and writable on error, and not to return EINPROGRESS
1156
+ * if the connect can be fulfilled immediately. Linux violates both
1157
+ * of these expectations.
1158
+ * Any kind of nonblocking connect on Linux returns EINPROGRESS.
1159
+ * The socket will then return writable when the disposition of the
1160
+ * connect is known, but it will not also be readable in case of
1161
+ * error! Weirdly, it will be readable in case there is data to read!!!
1162
+ * (Which can happen with protocols like SSH and SMTP.)
1163
+ * I suppose if you were so inclined you could consider this logical,
1164
+ * but it's not the way Unix has historically done it.
1165
+ * So we ignore the readable flag and read getsockopt to see if there
1166
+ * was an error connecting. A select timeout works as expected.
1167
+ * In regard to getsockopt: Linux does the Berkeley-style thing,
1168
+ * not the Solaris-style, and returns zero with the error code in
1169
+ * the error parameter.
1170
+ * Return the binding-text of the newly-created pending connection,
1171
+ * or NULL if there was a problem.
1172
+ */
1173
+
1174
+ if (!server || !*server || !port)
1175
+ throw std::runtime_error ("invalid server or port");
1176
+
1177
+ struct sockaddr_storage bind_as;
1178
+ size_t bind_as_len = sizeof bind_as;
1179
+ int gai = name2address (server, port, SOCK_STREAM, (struct sockaddr *)&bind_as, &bind_as_len);
1180
+ if (gai != 0) {
1181
+ char buf [200];
1182
+ snprintf (buf, sizeof(buf)-1, "unable to resolve address: %s", gai_strerror(gai));
1183
+ throw std::runtime_error (buf);
1184
+ }
1185
+
1186
+ SOCKET sd = EmSocket (bind_as.ss_family, SOCK_STREAM, 0);
1187
+ if (sd == INVALID_SOCKET) {
1188
+ char buf [200];
1189
+ snprintf (buf, sizeof(buf)-1, "unable to create new socket: %s", strerror(errno));
1190
+ throw std::runtime_error (buf);
1191
+ }
1192
+
1193
+ // From here on, ALL error returns must close the socket.
1194
+ // Set the new socket nonblocking.
1195
+ if (!SetSocketNonblocking (sd)) {
1196
+ close (sd);
1197
+ throw std::runtime_error ("unable to set socket as non-blocking");
1198
+ }
1199
+ // Disable slow-start (Nagle algorithm).
1200
+ int one = 1;
1201
+ setsockopt (sd, IPPROTO_TCP, TCP_NODELAY, (char*) &one, sizeof(one));
1202
+ // Set reuseaddr to improve performance on restarts
1203
+ setsockopt (sd, SOL_SOCKET, SO_REUSEADDR, (char*) &one, sizeof(one));
1204
+
1205
+ if (bind_addr) {
1206
+ struct sockaddr_storage bind_to;
1207
+ size_t bind_to_len = sizeof bind_to;
1208
+ gai = name2address (bind_addr, bind_port, SOCK_STREAM, (struct sockaddr *)&bind_to, &bind_to_len);
1209
+ if (gai != 0) {
1210
+ close (sd);
1211
+ char buf [200];
1212
+ snprintf (buf, sizeof(buf)-1, "invalid bind address: %s", gai_strerror(gai));
1213
+ throw std::runtime_error (buf);
1214
+ }
1215
+ if (bind (sd, (struct sockaddr *)&bind_to, bind_to_len) < 0) {
1216
+ close (sd);
1217
+ throw std::runtime_error ("couldn't bind to address");
1218
+ }
1219
+ }
1220
+
1221
+ uintptr_t out = 0;
1222
+
1223
+ #ifdef OS_UNIX
1224
+ int e_reason = 0;
1225
+ if (connect (sd, (struct sockaddr *)&bind_as, bind_as_len) == 0) {
1226
+ // This is a connect success, which Linux appears
1227
+ // never to give when the socket is nonblocking,
1228
+ // even if the connection is intramachine or to
1229
+ // localhost.
1230
+
1231
+ /* Changed this branch 08Aug06. Evidently some kernels
1232
+ * (FreeBSD for example) will actually return success from
1233
+ * a nonblocking connect. This is a pretty simple case,
1234
+ * just set up the new connection and clear the pending flag.
1235
+ * Thanks to Chris Ochs for helping track this down.
1236
+ * This branch never gets taken on Linux or (oddly) OSX.
1237
+ * The original behavior was to throw an unimplemented,
1238
+ * which the user saw as a fatal exception. Very unfriendly.
1239
+ *
1240
+ * Tweaked 10Aug06. Even though the connect disposition is
1241
+ * known, we still set the connect-pending flag. That way
1242
+ * some needed initialization will happen in the ConnectionDescriptor.
1243
+ * (To wit, the ConnectionCompleted event gets sent to the client.)
1244
+ */
1245
+ ConnectionDescriptor *cd = new ConnectionDescriptor (sd, this);
1246
+ if (!cd)
1247
+ throw std::runtime_error ("no connection allocated");
1248
+ cd->SetConnectPending (true);
1249
+ Add (cd);
1250
+ out = cd->GetBinding();
1251
+ }
1252
+ else if (errno == EINPROGRESS) {
1253
+ // Errno will generally always be EINPROGRESS, but on Linux
1254
+ // we have to look at getsockopt to be sure what really happened.
1255
+ int error = 0;
1256
+ socklen_t len;
1257
+ len = sizeof(error);
1258
+ int o = getsockopt (sd, SOL_SOCKET, SO_ERROR, &error, &len);
1259
+ if ((o == 0) && (error == 0)) {
1260
+ // Here, there's no disposition.
1261
+ // Put the connection on the stack and wait for it to complete
1262
+ // or time out.
1263
+ ConnectionDescriptor *cd = new ConnectionDescriptor (sd, this);
1264
+ if (!cd)
1265
+ throw std::runtime_error ("no connection allocated");
1266
+ cd->SetConnectPending (true);
1267
+ Add (cd);
1268
+ out = cd->GetBinding();
1269
+ } else {
1270
+ // Fall through to the !out case below.
1271
+ e_reason = error;
1272
+ }
1273
+ }
1274
+ else {
1275
+ // The error from connect was something other then EINPROGRESS (EHOSTDOWN, etc).
1276
+ // Fall through to the !out case below
1277
+ e_reason = errno;
1278
+ }
1279
+
1280
+ if (!out) {
1281
+ /* This could be connection refused or some such thing.
1282
+ * We will come here on Linux if a localhost connection fails.
1283
+ * Changed 16Jul06: Originally this branch was a no-op, and
1284
+ * we'd drop down to the end of the method, close the socket,
1285
+ * and return NULL, which would cause the caller to GET A
1286
+ * FATAL EXCEPTION. Now we keep the socket around but schedule an
1287
+ * immediate close on it, so the caller will get a close-event
1288
+ * scheduled on it. This was only an issue for localhost connections
1289
+ * to non-listening ports. We may eventually need to revise this
1290
+ * revised behavior, in case it causes problems like making it hard
1291
+ * for people to know that a failure occurred.
1292
+ */
1293
+ ConnectionDescriptor *cd = new ConnectionDescriptor (sd, this);
1294
+ if (!cd)
1295
+ throw std::runtime_error ("no connection allocated");
1296
+ cd->SetUnbindReasonCode (e_reason);
1297
+ cd->ScheduleClose (false);
1298
+ Add (cd);
1299
+ out = cd->GetBinding();
1300
+ }
1301
+ #endif
1302
+
1303
+ #ifdef OS_WIN32
1304
+ if (connect (sd, (struct sockaddr *)&bind_as, bind_as_len) == 0) {
1305
+ // This is a connect success, which Windows appears
1306
+ // never to give when the socket is nonblocking,
1307
+ // even if the connection is intramachine or to
1308
+ // localhost.
1309
+ throw std::runtime_error ("unimplemented");
1310
+ }
1311
+ else if (WSAGetLastError() == WSAEWOULDBLOCK) {
1312
+ // Here, there's no disposition.
1313
+ // Windows appears not to surface refused connections or
1314
+ // such stuff at this point.
1315
+ // Put the connection on the stack and wait for it to complete
1316
+ // or time out.
1317
+ ConnectionDescriptor *cd = new ConnectionDescriptor (sd, this);
1318
+ if (!cd)
1319
+ throw std::runtime_error ("no connection allocated");
1320
+ cd->SetConnectPending (true);
1321
+ Add (cd);
1322
+ out = cd->GetBinding();
1323
+ }
1324
+ else {
1325
+ // The error from connect was something other then WSAEWOULDBLOCK.
1326
+ }
1327
+
1328
+ #endif
1329
+
1330
+ if (!out)
1331
+ close (sd);
1332
+ return out;
1333
+ }
1334
+
1335
+ /***********************************
1336
+ EventMachine_t::ConnectToUnixServer
1337
+ ***********************************/
1338
+
1339
+ #ifdef OS_UNIX
1340
+ const uintptr_t EventMachine_t::ConnectToUnixServer (const char *server)
1341
+ {
1342
+ /* Connect to a Unix-domain server, which by definition is running
1343
+ * on the same host.
1344
+ * There is no meaningful implementation on Windows.
1345
+ * There's no need to do a nonblocking connect, since the connection
1346
+ * is always local and can always be fulfilled immediately.
1347
+ */
1348
+
1349
+ uintptr_t out = 0;
1350
+
1351
+ if (!server || !*server)
1352
+ return 0;
1353
+
1354
+ sockaddr_un pun;
1355
+ memset (&pun, 0, sizeof(pun));
1356
+ pun.sun_family = AF_LOCAL;
1357
+
1358
+ // You ordinarily expect the server name field to be at least 1024 bytes long,
1359
+ // but on Linux it can be MUCH shorter.
1360
+ if (strlen(server) >= sizeof(pun.sun_path))
1361
+ throw std::runtime_error ("unix-domain server name is too long");
1362
+
1363
+
1364
+ strcpy (pun.sun_path, server);
1365
+
1366
+ SOCKET fd = EmSocket (AF_LOCAL, SOCK_STREAM, 0);
1367
+ if (fd == INVALID_SOCKET)
1368
+ return 0;
1369
+
1370
+ // From here on, ALL error returns must close the socket.
1371
+ // NOTE: At this point, the socket is still a blocking socket.
1372
+ if (connect (fd, (struct sockaddr*)&pun, sizeof(pun)) != 0) {
1373
+ close (fd);
1374
+ return 0;
1375
+ }
1376
+
1377
+ // Set the newly-connected socket nonblocking.
1378
+ if (!SetSocketNonblocking (fd)) {
1379
+ close (fd);
1380
+ return 0;
1381
+ }
1382
+
1383
+ // Set up a connection descriptor and add it to the event-machine.
1384
+ // Observe, even though we know the connection status is connect-success,
1385
+ // we still set the "pending" flag, so some needed initializations take
1386
+ // place.
1387
+ ConnectionDescriptor *cd = new ConnectionDescriptor (fd, this);
1388
+ if (!cd)
1389
+ throw std::runtime_error ("no connection allocated");
1390
+ cd->SetConnectPending (true);
1391
+ Add (cd);
1392
+ out = cd->GetBinding();
1393
+
1394
+ if (!out)
1395
+ close (fd);
1396
+
1397
+ return out;
1398
+ }
1399
+ #else
1400
+ const uintptr_t EventMachine_t::ConnectToUnixServer (const char *server UNUSED)
1401
+ {
1402
+ throw std::runtime_error ("unix-domain connection unavailable on this platform");
1403
+ }
1404
+ #endif
1405
+
1406
+ /************************
1407
+ EventMachine_t::AttachFD
1408
+ ************************/
1409
+
1410
+ const uintptr_t EventMachine_t::AttachFD (SOCKET fd, bool watch_mode)
1411
+ {
1412
+ #ifdef OS_UNIX
1413
+ if (fcntl(fd, F_GETFL, 0) < 0) {
1414
+ if (errno) {
1415
+ throw std::runtime_error (strerror(errno));
1416
+ } else {
1417
+ throw std::runtime_error ("invalid file descriptor");
1418
+ }
1419
+ }
1420
+ #endif
1421
+
1422
+ #ifdef OS_WIN32
1423
+ // TODO: add better check for invalid file descriptors (see ioctlsocket or getsockopt)
1424
+ if (fd == INVALID_SOCKET)
1425
+ throw std::runtime_error ("invalid file descriptor");
1426
+ #endif
1427
+
1428
+ {// Check for duplicate descriptors
1429
+ size_t i;
1430
+ for (i = 0; i < Descriptors.size(); i++) {
1431
+ EventableDescriptor *ed = Descriptors[i];
1432
+ assert (ed);
1433
+ if (ed->GetSocket() == fd)
1434
+ throw std::runtime_error ("adding existing descriptor");
1435
+ }
1436
+
1437
+ for (i = 0; i < NewDescriptors.size(); i++) {
1438
+ EventableDescriptor *ed = NewDescriptors[i];
1439
+ assert (ed);
1440
+ if (ed->GetSocket() == fd)
1441
+ throw std::runtime_error ("adding existing new descriptor");
1442
+ }
1443
+ }
1444
+
1445
+ if (!watch_mode)
1446
+ SetSocketNonblocking(fd);
1447
+
1448
+ ConnectionDescriptor *cd = new ConnectionDescriptor (fd, this);
1449
+ if (!cd)
1450
+ throw std::runtime_error ("no connection allocated");
1451
+
1452
+ cd->SetAttached(true);
1453
+ cd->SetWatchOnly(watch_mode);
1454
+ cd->SetConnectPending (false);
1455
+
1456
+ Add (cd);
1457
+
1458
+ const uintptr_t out = cd->GetBinding();
1459
+ return out;
1460
+ }
1461
+
1462
+ /************************
1463
+ EventMachine_t::DetachFD
1464
+ ************************/
1465
+
1466
+ int EventMachine_t::DetachFD (EventableDescriptor *ed)
1467
+ {
1468
+ if (!ed)
1469
+ throw std::runtime_error ("detaching bad descriptor");
1470
+
1471
+ SOCKET fd = ed->GetSocket();
1472
+
1473
+ #ifdef HAVE_EPOLL
1474
+ if (Poller == Poller_Epoll) {
1475
+ if (ed->GetSocket() != INVALID_SOCKET) {
1476
+ assert (epfd != -1);
1477
+ int e = epoll_ctl (epfd, EPOLL_CTL_DEL, ed->GetSocket(), ed->GetEpollEvent());
1478
+ // ENOENT or EBADF are not errors because the socket may be already closed when we get here.
1479
+ if (e && (errno != ENOENT) && (errno != EBADF)) {
1480
+ char buf [200];
1481
+ snprintf (buf, sizeof(buf)-1, "unable to delete epoll event: %s", strerror(errno));
1482
+ throw std::runtime_error (buf);
1483
+ }
1484
+ }
1485
+ }
1486
+ #endif
1487
+
1488
+ #ifdef HAVE_KQUEUE
1489
+ if (Poller == Poller_Kqueue) {
1490
+ // remove any read/write events for this fd
1491
+ struct kevent k;
1492
+ #ifdef __NetBSD__
1493
+ EV_SET (&k, ed->GetSocket(), EVFILT_READ | EVFILT_WRITE, EV_DELETE, 0, 0, (intptr_t)ed);
1494
+ #else
1495
+ EV_SET (&k, ed->GetSocket(), EVFILT_READ | EVFILT_WRITE, EV_DELETE, 0, 0, ed);
1496
+ #endif
1497
+ int t = kevent (kqfd, &k, 1, NULL, 0, NULL);
1498
+ if (t < 0 && (errno != ENOENT) && (errno != EBADF)) {
1499
+ char buf [200];
1500
+ snprintf (buf, sizeof(buf)-1, "unable to delete kqueue event: %s", strerror(errno));
1501
+ throw std::runtime_error (buf);
1502
+ }
1503
+ }
1504
+ #endif
1505
+
1506
+ // Prevent the descriptor from being modified, in case DetachFD was called from a timer or next_tick
1507
+ ModifiedDescriptors.erase (ed);
1508
+
1509
+ // Prevent the descriptor from being added, in case DetachFD was called in the same tick as AttachFD
1510
+ for (size_t i = 0; i < NewDescriptors.size(); i++) {
1511
+ if (ed == NewDescriptors[i]) {
1512
+ NewDescriptors.erase(NewDescriptors.begin() + i);
1513
+ break;
1514
+ }
1515
+ }
1516
+
1517
+ // Set MySocket = INVALID_SOCKET so ShouldDelete() is true (and the descriptor gets deleted and removed),
1518
+ // and also to prevent anyone from calling close() on the detached fd
1519
+ ed->SetSocketInvalid();
1520
+
1521
+ return fd;
1522
+ }
1523
+
1524
+ /************
1525
+ name2address
1526
+ ************/
1527
+
1528
+ int EventMachine_t::name2address (const char *server, int port, int socktype, struct sockaddr *addr, size_t *addr_len)
1529
+ {
1530
+ if (!server || !*server)
1531
+ server = "0.0.0.0";
1532
+
1533
+ struct addrinfo *ai;
1534
+ struct addrinfo hints;
1535
+ memset (&hints, 0, sizeof(hints));
1536
+ hints.ai_socktype = socktype;
1537
+ hints.ai_family = AF_UNSPEC;
1538
+ hints.ai_flags = AI_NUMERICSERV | AI_ADDRCONFIG;
1539
+
1540
+ char portstr[12];
1541
+ snprintf(portstr, sizeof(portstr), "%u", port);
1542
+
1543
+ int gai = getaddrinfo (server, portstr, &hints, &ai);
1544
+ if (gai == 0) {
1545
+ assert (ai->ai_addrlen <= *addr_len);
1546
+ memcpy (addr, ai->ai_addr, ai->ai_addrlen);
1547
+ *addr_len = ai->ai_addrlen;
1548
+ freeaddrinfo(ai);
1549
+ }
1550
+
1551
+ return gai;
1552
+ }
1553
+
1554
+
1555
+ /*******************************
1556
+ EventMachine_t::CreateTcpServer
1557
+ *******************************/
1558
+
1559
+ const uintptr_t EventMachine_t::CreateTcpServer (const char *server, int port)
1560
+ {
1561
+ /* Create a TCP-acceptor (server) socket and add it to the event machine.
1562
+ * Return the binding of the new acceptor to the caller.
1563
+ * This binding will be referenced when the new acceptor sends events
1564
+ * to indicate accepted connections.
1565
+ */
1566
+
1567
+
1568
+ struct sockaddr_storage bind_here;
1569
+ size_t bind_here_len = sizeof bind_here;
1570
+ if (0 != name2address (server, port, SOCK_STREAM, (struct sockaddr *)&bind_here, &bind_here_len))
1571
+ return 0;
1572
+
1573
+ SOCKET sd_accept = EmSocket (bind_here.ss_family, SOCK_STREAM, 0);
1574
+ if (sd_accept == INVALID_SOCKET) {
1575
+ goto fail;
1576
+ }
1577
+
1578
+ { // set reuseaddr to improve performance on restarts.
1579
+ int oval = 1;
1580
+ if (setsockopt (sd_accept, SOL_SOCKET, SO_REUSEADDR, (char*)&oval, sizeof(oval)) < 0) {
1581
+ //__warning ("setsockopt failed while creating listener","");
1582
+ goto fail;
1583
+ }
1584
+ }
1585
+
1586
+ { // set CLOEXEC. Only makes sense on Unix
1587
+ #ifdef OS_UNIX
1588
+ int cloexec = fcntl (sd_accept, F_GETFD, 0);
1589
+ assert (cloexec >= 0);
1590
+ cloexec |= FD_CLOEXEC;
1591
+ fcntl (sd_accept, F_SETFD, cloexec);
1592
+ #endif
1593
+ }
1594
+
1595
+
1596
+ if (bind (sd_accept, (struct sockaddr *)&bind_here, bind_here_len)) {
1597
+ //__warning ("binding failed");
1598
+ goto fail;
1599
+ }
1600
+
1601
+ if (listen (sd_accept, 100)) {
1602
+ //__warning ("listen failed");
1603
+ goto fail;
1604
+ }
1605
+
1606
+ return AttachSD(sd_accept);
1607
+
1608
+ fail:
1609
+ if (sd_accept != INVALID_SOCKET)
1610
+ close (sd_accept);
1611
+ return 0;
1612
+ }
1613
+
1614
+
1615
+ /**********************************
1616
+ EventMachine_t::OpenDatagramSocket
1617
+ **********************************/
1618
+
1619
+ const uintptr_t EventMachine_t::OpenDatagramSocket (const char *address, int port)
1620
+ {
1621
+ uintptr_t output_binding = 0;
1622
+
1623
+ struct sockaddr_storage bind_here;
1624
+ size_t bind_here_len = sizeof bind_here;
1625
+ if (0 != name2address (address, port, SOCK_DGRAM, (struct sockaddr *)&bind_here, &bind_here_len))
1626
+ return 0;
1627
+
1628
+ // from here on, early returns must close the socket!
1629
+ SOCKET sd = EmSocket (bind_here.ss_family, SOCK_DGRAM, 0);
1630
+ if (sd == INVALID_SOCKET)
1631
+ goto fail;
1632
+
1633
+ { // set the SO_REUSEADDR on the socket before we bind, otherwise it won't work for a second one
1634
+ int oval = 1;
1635
+ if (setsockopt (sd, SOL_SOCKET, SO_REUSEADDR, (char*)&oval, sizeof(oval)) < 0)
1636
+ goto fail;
1637
+ }
1638
+
1639
+ // Set the new socket nonblocking.
1640
+ if (!SetSocketNonblocking (sd))
1641
+ goto fail;
1642
+
1643
+ if (bind (sd, (struct sockaddr *)&bind_here, bind_here_len) != 0)
1644
+ goto fail;
1645
+
1646
+ { // Looking good.
1647
+ DatagramDescriptor *ds = new DatagramDescriptor (sd, this);
1648
+ if (!ds)
1649
+ throw std::runtime_error ("unable to allocate datagram-socket");
1650
+ Add (ds);
1651
+ output_binding = ds->GetBinding();
1652
+ }
1653
+
1654
+ return output_binding;
1655
+
1656
+ fail:
1657
+ if (sd != INVALID_SOCKET)
1658
+ close (sd);
1659
+ return 0;
1660
+ }
1661
+
1662
+
1663
+
1664
+ /*******************
1665
+ EventMachine_t::Add
1666
+ *******************/
1667
+
1668
+ void EventMachine_t::Add (EventableDescriptor *ed)
1669
+ {
1670
+ if (!ed)
1671
+ throw std::runtime_error ("added bad descriptor");
1672
+ ed->SetEventCallback (EventCallback);
1673
+ NewDescriptors.push_back (ed);
1674
+ }
1675
+
1676
+
1677
+ /*******************************
1678
+ EventMachine_t::ArmKqueueWriter
1679
+ *******************************/
1680
+
1681
+ #ifdef HAVE_KQUEUE
1682
+ void EventMachine_t::ArmKqueueWriter (EventableDescriptor *ed)
1683
+ {
1684
+ if (Poller == Poller_Kqueue) {
1685
+ if (!ed)
1686
+ throw std::runtime_error ("added bad descriptor");
1687
+ struct kevent k;
1688
+ #ifdef __NetBSD__
1689
+ EV_SET (&k, ed->GetSocket(), EVFILT_WRITE, EV_ADD | EV_ONESHOT, 0, 0, (intptr_t)ed);
1690
+ #else
1691
+ EV_SET (&k, ed->GetSocket(), EVFILT_WRITE, EV_ADD | EV_ONESHOT, 0, 0, ed);
1692
+ #endif
1693
+ int t = kevent (kqfd, &k, 1, NULL, 0, NULL);
1694
+ if (t < 0) {
1695
+ char buf [200];
1696
+ snprintf (buf, sizeof(buf)-1, "arm kqueue writer failed on %d: %s", ed->GetSocket(), strerror(errno));
1697
+ throw std::runtime_error (buf);
1698
+ }
1699
+ }
1700
+ }
1701
+ #else
1702
+ void EventMachine_t::ArmKqueueWriter (EventableDescriptor *ed UNUSED) { }
1703
+ #endif
1704
+
1705
+ /*******************************
1706
+ EventMachine_t::ArmKqueueReader
1707
+ *******************************/
1708
+
1709
+ #ifdef HAVE_KQUEUE
1710
+ void EventMachine_t::ArmKqueueReader (EventableDescriptor *ed)
1711
+ {
1712
+ if (Poller == Poller_Kqueue) {
1713
+ if (!ed)
1714
+ throw std::runtime_error ("added bad descriptor");
1715
+ struct kevent k;
1716
+ #ifdef __NetBSD__
1717
+ EV_SET (&k, ed->GetSocket(), EVFILT_READ, EV_ADD, 0, 0, (intptr_t)ed);
1718
+ #else
1719
+ EV_SET (&k, ed->GetSocket(), EVFILT_READ, EV_ADD, 0, 0, ed);
1720
+ #endif
1721
+ int t = kevent (kqfd, &k, 1, NULL, 0, NULL);
1722
+ if (t < 0) {
1723
+ char buf [200];
1724
+ snprintf (buf, sizeof(buf)-1, "arm kqueue reader failed on %d: %s", ed->GetSocket(), strerror(errno));
1725
+ throw std::runtime_error (buf);
1726
+ }
1727
+ }
1728
+ }
1729
+ #else
1730
+ void EventMachine_t::ArmKqueueReader (EventableDescriptor *ed UNUSED) { }
1731
+ #endif
1732
+
1733
+ /**********************************
1734
+ EventMachine_t::_AddNewDescriptors
1735
+ **********************************/
1736
+
1737
+ void EventMachine_t::_AddNewDescriptors()
1738
+ {
1739
+ /* Avoid adding descriptors to the main descriptor list
1740
+ * while we're actually traversing the list.
1741
+ * Any descriptors that are added as a result of processing timers
1742
+ * or acceptors should go on a temporary queue and then added
1743
+ * while we're not traversing the main list.
1744
+ * Also, it (rarely) happens that a newly-created descriptor
1745
+ * is immediately scheduled to close. It might be a good
1746
+ * idea not to bother scheduling these for I/O but if
1747
+ * we do that, we might bypass some important processing.
1748
+ */
1749
+
1750
+ for (size_t i = 0; i < NewDescriptors.size(); i++) {
1751
+ EventableDescriptor *ed = NewDescriptors[i];
1752
+ if (ed == NULL)
1753
+ throw std::runtime_error ("adding bad descriptor");
1754
+
1755
+ #if HAVE_EPOLL
1756
+ if (Poller == Poller_Epoll) {
1757
+ assert (epfd != -1);
1758
+ int e = epoll_ctl (epfd, EPOLL_CTL_ADD, ed->GetSocket(), ed->GetEpollEvent());
1759
+ if (e) {
1760
+ char buf [200];
1761
+ snprintf (buf, sizeof(buf)-1, "unable to add new descriptor: %s", strerror(errno));
1762
+ throw std::runtime_error (buf);
1763
+ }
1764
+ }
1765
+ #endif
1766
+
1767
+ #if HAVE_KQUEUE
1768
+ /*
1769
+ if (Poller == Poller_Kqueue) {
1770
+ // INCOMPLETE. Some descriptors don't want to be readable.
1771
+ assert (kqfd != -1);
1772
+ struct kevent k;
1773
+ #ifdef __NetBSD__
1774
+ EV_SET (&k, ed->GetSocket(), EVFILT_READ, EV_ADD, 0, 0, (intptr_t)ed);
1775
+ #else
1776
+ EV_SET (&k, ed->GetSocket(), EVFILT_READ, EV_ADD, 0, 0, ed);
1777
+ #endif
1778
+ int t = kevent (kqfd, &k, 1, NULL, 0, NULL);
1779
+ assert (t == 0);
1780
+ }
1781
+ */
1782
+ #endif
1783
+
1784
+ QueueHeartbeat(ed);
1785
+ Descriptors.push_back (ed);
1786
+ }
1787
+ NewDescriptors.clear();
1788
+ }
1789
+
1790
+
1791
+ /**********************************
1792
+ EventMachine_t::_ModifyDescriptors
1793
+ **********************************/
1794
+
1795
+ void EventMachine_t::_ModifyDescriptors()
1796
+ {
1797
+ /* For implementations which don't level check every descriptor on
1798
+ * every pass through the machine, as select does.
1799
+ * If we're not selecting, then descriptors need a way to signal to the
1800
+ * machine that their readable or writable status has changed.
1801
+ * That's what the ::Modify call is for. We do it this way to avoid
1802
+ * modifying descriptors during the loop traversal, where it can easily
1803
+ * happen that an object (like a UDP socket) gets data written on it by
1804
+ * the application during #post_init. That would take place BEFORE the
1805
+ * descriptor even gets added to the epoll descriptor, so the modify
1806
+ * operation will crash messily.
1807
+ * Another really messy possibility is for a descriptor to put itself
1808
+ * on the Modified list, and then get deleted before we get here.
1809
+ * Remember, deletes happen after the I/O traversal and before the
1810
+ * next pass through here. So we have to make sure when we delete a
1811
+ * descriptor to remove it from the Modified list.
1812
+ */
1813
+
1814
+ #ifdef HAVE_EPOLL
1815
+ if (Poller == Poller_Epoll) {
1816
+ std::set<EventableDescriptor*>::iterator i = ModifiedDescriptors.begin();
1817
+ while (i != ModifiedDescriptors.end()) {
1818
+ assert (*i);
1819
+ _ModifyEpollEvent (*i);
1820
+ ++i;
1821
+ }
1822
+ }
1823
+ #endif
1824
+
1825
+ #ifdef HAVE_KQUEUE
1826
+ if (Poller == Poller_Kqueue) {
1827
+ std::set<EventableDescriptor*>::iterator i = ModifiedDescriptors.begin();
1828
+ while (i != ModifiedDescriptors.end()) {
1829
+ assert (*i);
1830
+ if ((*i)->GetKqueueArmWrite())
1831
+ ArmKqueueWriter (*i);
1832
+ ++i;
1833
+ }
1834
+ }
1835
+ #endif
1836
+
1837
+ ModifiedDescriptors.clear();
1838
+ }
1839
+
1840
+
1841
+ /**********************
1842
+ EventMachine_t::Modify
1843
+ **********************/
1844
+
1845
+ void EventMachine_t::Modify (EventableDescriptor *ed)
1846
+ {
1847
+ if (!ed)
1848
+ throw std::runtime_error ("modified bad descriptor");
1849
+ ModifiedDescriptors.insert (ed);
1850
+ }
1851
+
1852
+
1853
+ /***********************
1854
+ EventMachine_t::Deregister
1855
+ ***********************/
1856
+
1857
+ void EventMachine_t::Deregister (EventableDescriptor *ed)
1858
+ {
1859
+ if (!ed)
1860
+ throw std::runtime_error ("modified bad descriptor");
1861
+ #ifdef HAVE_EPOLL
1862
+ // cut/paste from _CleanupSockets(). The error handling could be
1863
+ // refactored out of there, but it is cut/paste all over the
1864
+ // file already.
1865
+ if (Poller == Poller_Epoll) {
1866
+ assert (epfd != -1);
1867
+ assert (ed->GetSocket() != INVALID_SOCKET);
1868
+ int e = epoll_ctl (epfd, EPOLL_CTL_DEL, ed->GetSocket(), ed->GetEpollEvent());
1869
+ // ENOENT or EBADF are not errors because the socket may be already closed when we get here.
1870
+ if (e && (errno != ENOENT) && (errno != EBADF) && (errno != EPERM)) {
1871
+ char buf [200];
1872
+ snprintf (buf, sizeof(buf)-1, "unable to delete epoll event: %s", strerror(errno));
1873
+ throw std::runtime_error (buf);
1874
+ }
1875
+ ModifiedDescriptors.erase(ed);
1876
+ }
1877
+ #endif
1878
+
1879
+ #ifdef HAVE_KQUEUE
1880
+ if (Poller == Poller_Kqueue) {
1881
+ assert (ed->GetSocket() != INVALID_SOCKET);
1882
+
1883
+ ModifiedDescriptors.erase(ed);
1884
+ }
1885
+ #endif
1886
+ }
1887
+
1888
+
1889
+ /**************************************
1890
+ EventMachine_t::CreateUnixDomainServer
1891
+ **************************************/
1892
+
1893
+ #ifdef OS_UNIX
1894
+ const uintptr_t EventMachine_t::CreateUnixDomainServer (const char *filename)
1895
+ {
1896
+ /* Create a UNIX-domain acceptor (server) socket and add it to the event machine.
1897
+ * Return the binding of the new acceptor to the caller.
1898
+ * This binding will be referenced when the new acceptor sends events
1899
+ * to indicate accepted connections.
1900
+ * THERE IS NO MEANINGFUL IMPLEMENTATION ON WINDOWS.
1901
+ */
1902
+
1903
+ struct sockaddr_un s_sun;
1904
+
1905
+ SOCKET sd_accept = EmSocket (AF_LOCAL, SOCK_STREAM, 0);
1906
+ if (sd_accept == INVALID_SOCKET) {
1907
+ goto fail;
1908
+ }
1909
+
1910
+ if (!filename || !*filename)
1911
+ goto fail;
1912
+ unlink (filename);
1913
+
1914
+ bzero (&s_sun, sizeof(s_sun));
1915
+ s_sun.sun_family = AF_LOCAL;
1916
+ strncpy (s_sun.sun_path, filename, sizeof(s_sun.sun_path)-1);
1917
+
1918
+ // don't bother with reuseaddr for a local socket.
1919
+
1920
+ { // set CLOEXEC. Only makes sense on Unix
1921
+ #ifdef OS_UNIX
1922
+ int cloexec = fcntl (sd_accept, F_GETFD, 0);
1923
+ assert (cloexec >= 0);
1924
+ cloexec |= FD_CLOEXEC;
1925
+ fcntl (sd_accept, F_SETFD, cloexec);
1926
+ #endif
1927
+ }
1928
+
1929
+ if (bind (sd_accept, (struct sockaddr*)&s_sun, sizeof(s_sun))) {
1930
+ //__warning ("binding failed");
1931
+ goto fail;
1932
+ }
1933
+
1934
+ if (listen (sd_accept, 100)) {
1935
+ //__warning ("listen failed");
1936
+ goto fail;
1937
+ }
1938
+
1939
+ return AttachSD(sd_accept);
1940
+
1941
+ fail:
1942
+ if (sd_accept != INVALID_SOCKET)
1943
+ close (sd_accept);
1944
+ return 0;
1945
+ }
1946
+ #else
1947
+ const uintptr_t EventMachine_t::CreateUnixDomainServer (const char *filename UNUSED)
1948
+ {
1949
+ throw std::runtime_error ("unix-domain server unavailable on this platform");
1950
+ }
1951
+ #endif
1952
+
1953
+
1954
+ /**************************************
1955
+ EventMachine_t::AttachSD
1956
+ **************************************/
1957
+
1958
+ const uintptr_t EventMachine_t::AttachSD (SOCKET sd_accept)
1959
+ {
1960
+ uintptr_t output_binding = 0;
1961
+
1962
+ {
1963
+ // Set the acceptor non-blocking.
1964
+ // THIS IS CRUCIALLY IMPORTANT because we read it in a select loop.
1965
+ if (!SetSocketNonblocking (sd_accept)) {
1966
+ //int val = fcntl (sd_accept, F_GETFL, 0);
1967
+ //if (fcntl (sd_accept, F_SETFL, val | O_NONBLOCK) == -1) {
1968
+ goto fail;
1969
+ }
1970
+ }
1971
+
1972
+ { // Looking good.
1973
+ AcceptorDescriptor *ad = new AcceptorDescriptor (sd_accept, this);
1974
+ if (!ad)
1975
+ throw std::runtime_error ("unable to allocate acceptor");
1976
+ Add (ad);
1977
+ output_binding = ad->GetBinding();
1978
+ }
1979
+
1980
+ return output_binding;
1981
+
1982
+ fail:
1983
+ if (sd_accept != INVALID_SOCKET)
1984
+ close (sd_accept);
1985
+ return 0;
1986
+ }
1987
+
1988
+
1989
+ /**************************
1990
+ EventMachine_t::Socketpair
1991
+ **************************/
1992
+
1993
+ #ifdef OS_UNIX
1994
+ const uintptr_t EventMachine_t::Socketpair (char * const * cmd_strings)
1995
+ {
1996
+ // Make sure the incoming array of command strings is sane.
1997
+ if (!cmd_strings)
1998
+ return 0;
1999
+ int j;
2000
+ for (j=0; j < 2048 && cmd_strings[j]; j++)
2001
+ ;
2002
+ if ((j==0) || (j==2048))
2003
+ return 0;
2004
+
2005
+ uintptr_t output_binding = 0;
2006
+
2007
+ int sv[2];
2008
+ if (socketpair (AF_LOCAL, SOCK_STREAM, 0, sv) < 0)
2009
+ return 0;
2010
+ // from here, all early returns must close the pair of sockets.
2011
+
2012
+ // Set the parent side of the socketpair nonblocking.
2013
+ // We don't care about the child side, and most child processes will expect their
2014
+ // stdout to be blocking. Thanks to Duane Johnson and Bill Kelly for pointing this out.
2015
+ // Obviously DON'T set CLOEXEC.
2016
+ if (!SetSocketNonblocking (sv[0])) {
2017
+ close (sv[0]);
2018
+ close (sv[1]);
2019
+ return 0;
2020
+ }
2021
+
2022
+ pid_t f = fork();
2023
+ if (f > 0) {
2024
+ close (sv[1]);
2025
+ PipeDescriptor *pd = new PipeDescriptor (sv[0], f, this);
2026
+ if (!pd)
2027
+ throw std::runtime_error ("unable to allocate pipe");
2028
+ Add (pd);
2029
+ output_binding = pd->GetBinding();
2030
+ }
2031
+ else if (f == 0) {
2032
+ close (sv[0]);
2033
+ dup2 (sv[1], STDIN_FILENO);
2034
+ close (sv[1]);
2035
+ dup2 (STDIN_FILENO, STDOUT_FILENO);
2036
+ execvp (cmd_strings[0], cmd_strings+1);
2037
+ exit (-1); // end the child process if the exec doesn't work.
2038
+ }
2039
+ else
2040
+ throw std::runtime_error ("no fork");
2041
+
2042
+ return output_binding;
2043
+ }
2044
+ #else
2045
+ const uintptr_t EventMachine_t::Socketpair (char * const * cmd_strings UNUSED)
2046
+ {
2047
+ throw std::runtime_error ("socketpair is currently unavailable on this platform");
2048
+ }
2049
+ #endif
2050
+
2051
+
2052
+
2053
+ /****************************
2054
+ EventMachine_t::OpenKeyboard
2055
+ ****************************/
2056
+
2057
+ const uintptr_t EventMachine_t::OpenKeyboard()
2058
+ {
2059
+ KeyboardDescriptor *kd = new KeyboardDescriptor (this);
2060
+ if (!kd)
2061
+ throw std::runtime_error ("no keyboard-object allocated");
2062
+ Add (kd);
2063
+ return kd->GetBinding();
2064
+ }
2065
+
2066
+
2067
+ /**********************************
2068
+ EventMachine_t::GetConnectionCount
2069
+ **********************************/
2070
+
2071
+ int EventMachine_t::GetConnectionCount ()
2072
+ {
2073
+ int i = 0;
2074
+ // Subtract one for epoll or kqueue because of the LoopbreakDescriptor
2075
+ if (Poller == Poller_Epoll || Poller == Poller_Kqueue)
2076
+ i = 1;
2077
+
2078
+ return Descriptors.size() + NewDescriptors.size() - i;
2079
+ }
2080
+
2081
+
2082
+ /************************
2083
+ EventMachine_t::WatchPid
2084
+ ************************/
2085
+
2086
+ #ifdef HAVE_KQUEUE
2087
+ const uintptr_t EventMachine_t::WatchPid (int pid)
2088
+ {
2089
+ if (Poller != Poller_Kqueue)
2090
+ throw std::runtime_error("must enable kqueue (EM.kqueue=true) for pid watching support");
2091
+
2092
+ struct kevent event;
2093
+ int kqres;
2094
+
2095
+ EV_SET(&event, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT | NOTE_FORK, 0, 0);
2096
+
2097
+ // Attempt to register the event
2098
+ kqres = kevent(kqfd, &event, 1, NULL, 0, NULL);
2099
+ if (kqres == -1) {
2100
+ char errbuf[200];
2101
+ sprintf(errbuf, "failed to register file watch descriptor with kqueue: %s", strerror(errno));
2102
+ throw std::runtime_error(errbuf);
2103
+ }
2104
+ Bindable_t* b = new Bindable_t();
2105
+ Pids.insert(std::make_pair (pid, b));
2106
+
2107
+ return b->GetBinding();
2108
+ }
2109
+ #else
2110
+ const uintptr_t EventMachine_t::WatchPid (int pid UNUSED)
2111
+ {
2112
+ throw std::runtime_error("no pid watching support on this system");
2113
+ }
2114
+ #endif
2115
+
2116
+ /**************************
2117
+ EventMachine_t::UnwatchPid
2118
+ **************************/
2119
+
2120
+ void EventMachine_t::UnwatchPid (int pid)
2121
+ {
2122
+ Bindable_t *b = Pids[pid];
2123
+ assert(b);
2124
+ Pids.erase(pid);
2125
+
2126
+ #ifdef HAVE_KQUEUE
2127
+ struct kevent k;
2128
+
2129
+ EV_SET(&k, pid, EVFILT_PROC, EV_DELETE, 0, 0, 0);
2130
+ /*int t =*/ kevent (kqfd, &k, 1, NULL, 0, NULL);
2131
+ // t==-1 if the process already exited; ignore this for now
2132
+ #endif
2133
+
2134
+ if (EventCallback)
2135
+ (*EventCallback)(b->GetBinding(), EM_CONNECTION_UNBOUND, NULL, 0);
2136
+
2137
+ delete b;
2138
+ }
2139
+
2140
+ void EventMachine_t::UnwatchPid (const uintptr_t sig)
2141
+ {
2142
+ for(std::map<int, Bindable_t*>::iterator i=Pids.begin(); i != Pids.end(); i++)
2143
+ {
2144
+ if (i->second->GetBinding() == sig) {
2145
+ UnwatchPid (i->first);
2146
+ return;
2147
+ }
2148
+ }
2149
+
2150
+ throw std::runtime_error("attempted to remove invalid pid signature");
2151
+ }
2152
+
2153
+
2154
+ /*************************
2155
+ EventMachine_t::WatchFile
2156
+ *************************/
2157
+
2158
+ const uintptr_t EventMachine_t::WatchFile (const char *fpath)
2159
+ {
2160
+ struct stat sb;
2161
+ int sres;
2162
+ int wd = -1;
2163
+
2164
+ sres = stat(fpath, &sb);
2165
+
2166
+ if (sres == -1) {
2167
+ char errbuf[300];
2168
+ sprintf(errbuf, "error registering file %s for watching: %s", fpath, strerror(errno));
2169
+ throw std::runtime_error(errbuf);
2170
+ }
2171
+
2172
+ #ifdef HAVE_INOTIFY
2173
+ if (!inotify) {
2174
+ inotify = new InotifyDescriptor(this);
2175
+ assert (inotify);
2176
+ Add(inotify);
2177
+ }
2178
+
2179
+ wd = inotify_add_watch(inotify->GetSocket(), fpath,
2180
+ IN_MODIFY | IN_DELETE_SELF | IN_MOVE_SELF | IN_CREATE | IN_DELETE | IN_MOVE) ;
2181
+ if (wd == -1) {
2182
+ char errbuf[300];
2183
+ sprintf(errbuf, "failed to open file %s for registering with inotify: %s", fpath, strerror(errno));
2184
+ throw std::runtime_error(errbuf);
2185
+ }
2186
+ #endif
2187
+
2188
+ #ifdef HAVE_KQUEUE
2189
+ if (Poller != Poller_Kqueue)
2190
+ throw std::runtime_error("must enable kqueue (EM.kqueue=true) for file watching support");
2191
+
2192
+ // With kqueue we have to open the file first and use the resulting fd to register for events
2193
+ wd = open(fpath, O_RDONLY);
2194
+ if (wd == -1) {
2195
+ char errbuf[300];
2196
+ sprintf(errbuf, "failed to open file %s for registering with kqueue: %s", fpath, strerror(errno));
2197
+ throw std::runtime_error(errbuf);
2198
+ }
2199
+ _RegisterKqueueFileEvent(wd);
2200
+ #endif
2201
+
2202
+ if (wd != -1) {
2203
+ Bindable_t* b = new Bindable_t();
2204
+ Files.insert(std::make_pair (wd, b));
2205
+
2206
+ return b->GetBinding();
2207
+ }
2208
+
2209
+ throw std::runtime_error("no file watching support on this system"); // is this the right thing to do?
2210
+ }
2211
+
2212
+
2213
+ /***************************
2214
+ EventMachine_t::UnwatchFile
2215
+ ***************************/
2216
+
2217
+ void EventMachine_t::UnwatchFile (int wd)
2218
+ {
2219
+ Bindable_t *b = Files[wd];
2220
+ assert(b);
2221
+ Files.erase(wd);
2222
+
2223
+ #ifdef HAVE_INOTIFY
2224
+ inotify_rm_watch(inotify->GetSocket(), wd);
2225
+ #elif HAVE_KQUEUE
2226
+ // With kqueue, closing the monitored fd automatically clears all registered events for it
2227
+ close(wd);
2228
+ #endif
2229
+
2230
+ if (EventCallback)
2231
+ (*EventCallback)(b->GetBinding(), EM_CONNECTION_UNBOUND, NULL, 0);
2232
+
2233
+ delete b;
2234
+ }
2235
+
2236
+ void EventMachine_t::UnwatchFile (const uintptr_t sig)
2237
+ {
2238
+ for(std::map<int, Bindable_t*>::iterator i=Files.begin(); i != Files.end(); i++)
2239
+ {
2240
+ if (i->second->GetBinding() == sig) {
2241
+ UnwatchFile (i->first);
2242
+ return;
2243
+ }
2244
+ }
2245
+ throw std::runtime_error("attempted to remove invalid watch signature");
2246
+ }
2247
+
2248
+
2249
+ /***********************************
2250
+ EventMachine_t::_ReadInotify_Events
2251
+ ************************************/
2252
+
2253
+ void EventMachine_t::_ReadInotifyEvents()
2254
+ {
2255
+ #ifdef HAVE_INOTIFY
2256
+ char buffer[1024];
2257
+
2258
+ assert(EventCallback);
2259
+
2260
+ for (;;) {
2261
+ int returned = read(inotify->GetSocket(), buffer, sizeof(buffer));
2262
+ assert(!(returned == 0 || (returned == -1 && errno == EINVAL)));
2263
+ if (returned <= 0) {
2264
+ break;
2265
+ }
2266
+ int current = 0;
2267
+ while (current < returned) {
2268
+ struct inotify_event* event = (struct inotify_event*)(buffer+current);
2269
+ std::map<int, Bindable_t*>::const_iterator bindable = Files.find(event->wd);
2270
+ if (bindable != Files.end()) {
2271
+ if (event->mask & (IN_MODIFY | IN_CREATE | IN_DELETE | IN_MOVE)){
2272
+ (*EventCallback)(bindable->second->GetBinding(), EM_CONNECTION_READ, "modified", 8);
2273
+ }
2274
+ if (event->mask & IN_MOVE_SELF){
2275
+ (*EventCallback)(bindable->second->GetBinding(), EM_CONNECTION_READ, "moved", 5);
2276
+ }
2277
+ if (event->mask & IN_DELETE_SELF) {
2278
+ (*EventCallback)(bindable->second->GetBinding(), EM_CONNECTION_READ, "deleted", 7);
2279
+ UnwatchFile ((int)event->wd);
2280
+ }
2281
+ }
2282
+ current += sizeof(struct inotify_event) + event->len;
2283
+ }
2284
+ }
2285
+ #endif
2286
+ }
2287
+
2288
+
2289
+ /*************************************
2290
+ EventMachine_t::_HandleKqueuePidEvent
2291
+ *************************************/
2292
+
2293
+ #ifdef HAVE_KQUEUE
2294
+ void EventMachine_t::_HandleKqueuePidEvent(struct kevent *event)
2295
+ {
2296
+ assert(EventCallback);
2297
+
2298
+ if (event->fflags & NOTE_FORK)
2299
+ (*EventCallback)(Pids [(int) event->ident]->GetBinding(), EM_CONNECTION_READ, "fork", 4);
2300
+ if (event->fflags & NOTE_EXIT) {
2301
+ (*EventCallback)(Pids [(int) event->ident]->GetBinding(), EM_CONNECTION_READ, "exit", 4);
2302
+ // stop watching the pid if it died
2303
+ UnwatchPid ((int)event->ident);
2304
+ }
2305
+ }
2306
+ #endif
2307
+
2308
+
2309
+ /**************************************
2310
+ EventMachine_t::_HandleKqueueFileEvent
2311
+ ***************************************/
2312
+
2313
+ #ifdef HAVE_KQUEUE
2314
+ void EventMachine_t::_HandleKqueueFileEvent(struct kevent *event)
2315
+ {
2316
+ assert(EventCallback);
2317
+
2318
+ if (event->fflags & NOTE_WRITE)
2319
+ (*EventCallback)(Files [(int) event->ident]->GetBinding(), EM_CONNECTION_READ, "modified", 8);
2320
+ if (event->fflags & NOTE_RENAME)
2321
+ (*EventCallback)(Files [(int) event->ident]->GetBinding(), EM_CONNECTION_READ, "moved", 5);
2322
+ if (event->fflags & NOTE_DELETE) {
2323
+ (*EventCallback)(Files [(int) event->ident]->GetBinding(), EM_CONNECTION_READ, "deleted", 7);
2324
+ UnwatchFile ((int)event->ident);
2325
+ }
2326
+ }
2327
+ #endif
2328
+
2329
+
2330
+ /****************************************
2331
+ EventMachine_t::_RegisterKqueueFileEvent
2332
+ *****************************************/
2333
+
2334
+ #ifdef HAVE_KQUEUE
2335
+ void EventMachine_t::_RegisterKqueueFileEvent(int fd)
2336
+ {
2337
+ struct kevent newevent;
2338
+ int kqres;
2339
+
2340
+ // Setup the event with our fd and proper flags
2341
+ EV_SET(&newevent, fd, EVFILT_VNODE, EV_ADD | EV_CLEAR, NOTE_DELETE | NOTE_RENAME | NOTE_WRITE, 0, 0);
2342
+
2343
+ // Attempt to register the event
2344
+ kqres = kevent(kqfd, &newevent, 1, NULL, 0, NULL);
2345
+ if (kqres == -1) {
2346
+ char errbuf[200];
2347
+ sprintf(errbuf, "failed to register file watch descriptor with kqueue: %s", strerror(errno));
2348
+ close(fd);
2349
+ throw std::runtime_error(errbuf);
2350
+ }
2351
+ }
2352
+ #endif
2353
+
2354
+
2355
+ /************************************
2356
+ EventMachine_t::GetHeartbeatInterval
2357
+ *************************************/
2358
+
2359
+ float EventMachine_t::GetHeartbeatInterval()
2360
+ {
2361
+ return ((float)HeartbeatInterval / 1000000);
2362
+ }
2363
+
2364
+
2365
+ /************************************
2366
+ EventMachine_t::SetHeartbeatInterval
2367
+ *************************************/
2368
+
2369
+ int EventMachine_t::SetHeartbeatInterval(float interval)
2370
+ {
2371
+ int iv = (int)(interval * 1000000);
2372
+ if (iv > 0) {
2373
+ HeartbeatInterval = iv;
2374
+ return 1;
2375
+ }
2376
+ return 0;
2377
+ }
2378
+ //#endif // OS_UNIX