wj_eventmachine 1.3.0.dev.1

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 (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