asyncengine 0.0.1.testing1 → 0.0.2.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (251) hide show
  1. data/README.markdown +3 -0
  2. data/Rakefile +38 -0
  3. data/asyncengine.gemspec +8 -4
  4. data/ext/asyncengine/ae_call_from_other_thread.c +106 -0
  5. data/ext/asyncengine/ae_call_from_other_thread.h +12 -0
  6. data/ext/asyncengine/ae_handle_common.c +193 -48
  7. data/ext/asyncengine/ae_handle_common.h +40 -13
  8. data/ext/asyncengine/ae_ip_utils.c +246 -0
  9. data/ext/asyncengine/ae_ip_utils.h +25 -0
  10. data/ext/asyncengine/ae_next_tick.c +81 -21
  11. data/ext/asyncengine/ae_next_tick.h +4 -2
  12. data/ext/asyncengine/ae_resolver.c +156 -0
  13. data/ext/asyncengine/ae_resolver.h +10 -0
  14. data/ext/asyncengine/ae_tcp.c +908 -0
  15. data/ext/asyncengine/ae_tcp.h +20 -0
  16. data/ext/asyncengine/ae_timer.c +355 -81
  17. data/ext/asyncengine/ae_timer.h +11 -4
  18. data/ext/asyncengine/ae_udp.c +579 -13
  19. data/ext/asyncengine/ae_udp.h +15 -2
  20. data/ext/asyncengine/ae_utils.c +192 -0
  21. data/ext/asyncengine/ae_utils.h +16 -0
  22. data/ext/asyncengine/asyncengine_ruby.c +469 -26
  23. data/ext/asyncengine/asyncengine_ruby.h +49 -11
  24. data/ext/asyncengine/debug.h +68 -0
  25. data/ext/asyncengine/extconf.rb +26 -2
  26. data/ext/asyncengine/ip_parser.c +5954 -0
  27. data/ext/asyncengine/ip_parser.h +16 -0
  28. data/ext/asyncengine/libuv/AUTHORS +16 -0
  29. data/ext/asyncengine/libuv/common.gypi +4 -4
  30. data/ext/asyncengine/libuv/config-mingw.mk +6 -6
  31. data/ext/asyncengine/libuv/config-unix.mk +13 -13
  32. data/ext/asyncengine/libuv/gyp_uv +5 -1
  33. data/ext/asyncengine/libuv/ibc_tests/exec_test.sh +8 -0
  34. data/ext/asyncengine/libuv/ibc_tests/uv_shutdown_write_issue.c +171 -0
  35. data/ext/asyncengine/libuv/ibc_tests/uv_tcp_close_while_connecting.c +102 -0
  36. data/ext/asyncengine/libuv/include/uv-private/ngx-queue.h +3 -1
  37. data/ext/asyncengine/libuv/include/uv-private/uv-unix.h +103 -50
  38. data/ext/asyncengine/libuv/include/uv-private/uv-win.h +76 -24
  39. data/ext/asyncengine/libuv/include/uv.h +353 -88
  40. data/ext/asyncengine/libuv/src/ares/ares__close_sockets.o +0 -0
  41. data/ext/asyncengine/libuv/src/ares/ares__get_hostent.o +0 -0
  42. data/ext/asyncengine/libuv/src/ares/ares__read_line.o +0 -0
  43. data/ext/asyncengine/libuv/src/ares/ares__timeval.o +0 -0
  44. data/ext/asyncengine/libuv/src/ares/ares_cancel.o +0 -0
  45. data/ext/asyncengine/libuv/src/ares/ares_data.o +0 -0
  46. data/ext/asyncengine/libuv/src/ares/ares_destroy.o +0 -0
  47. data/ext/asyncengine/libuv/src/ares/ares_expand_name.o +0 -0
  48. data/ext/asyncengine/libuv/src/ares/ares_expand_string.o +0 -0
  49. data/ext/asyncengine/libuv/src/ares/ares_fds.o +0 -0
  50. data/ext/asyncengine/libuv/src/ares/ares_free_hostent.o +0 -0
  51. data/ext/asyncengine/libuv/src/ares/ares_free_string.o +0 -0
  52. data/ext/asyncengine/libuv/src/ares/ares_gethostbyaddr.o +0 -0
  53. data/ext/asyncengine/libuv/src/ares/ares_gethostbyname.o +0 -0
  54. data/ext/asyncengine/libuv/src/ares/ares_getnameinfo.o +0 -0
  55. data/ext/asyncengine/libuv/src/ares/ares_getopt.o +0 -0
  56. data/ext/asyncengine/libuv/src/ares/ares_getsock.o +0 -0
  57. data/ext/asyncengine/libuv/src/ares/ares_init.o +0 -0
  58. data/ext/asyncengine/libuv/src/ares/ares_library_init.o +0 -0
  59. data/ext/asyncengine/libuv/src/ares/ares_llist.o +0 -0
  60. data/ext/asyncengine/libuv/src/ares/ares_mkquery.o +0 -0
  61. data/ext/asyncengine/libuv/src/ares/ares_nowarn.o +0 -0
  62. data/ext/asyncengine/libuv/src/ares/ares_options.o +0 -0
  63. data/ext/asyncengine/libuv/src/ares/ares_parse_a_reply.o +0 -0
  64. data/ext/asyncengine/libuv/src/ares/ares_parse_aaaa_reply.o +0 -0
  65. data/ext/asyncengine/libuv/src/ares/ares_parse_mx_reply.o +0 -0
  66. data/ext/asyncengine/libuv/src/ares/ares_parse_ns_reply.o +0 -0
  67. data/ext/asyncengine/libuv/src/ares/ares_parse_ptr_reply.o +0 -0
  68. data/ext/asyncengine/libuv/src/ares/ares_parse_srv_reply.o +0 -0
  69. data/ext/asyncengine/libuv/src/ares/ares_parse_txt_reply.o +0 -0
  70. data/ext/asyncengine/libuv/src/ares/ares_process.o +0 -0
  71. data/ext/asyncengine/libuv/src/ares/ares_query.o +0 -0
  72. data/ext/asyncengine/libuv/src/ares/ares_search.o +0 -0
  73. data/ext/asyncengine/libuv/src/ares/ares_send.o +0 -0
  74. data/ext/asyncengine/libuv/src/ares/ares_strcasecmp.o +0 -0
  75. data/ext/asyncengine/libuv/src/ares/ares_strdup.o +0 -0
  76. data/ext/asyncengine/libuv/src/ares/ares_strerror.o +0 -0
  77. data/ext/asyncengine/libuv/src/ares/ares_timeout.o +0 -0
  78. data/ext/asyncengine/libuv/src/ares/ares_version.o +0 -0
  79. data/ext/asyncengine/libuv/src/ares/ares_writev.o +0 -0
  80. data/ext/asyncengine/libuv/src/ares/bitncmp.o +0 -0
  81. data/ext/asyncengine/libuv/src/ares/inet_net_pton.o +0 -0
  82. data/ext/asyncengine/libuv/src/ares/inet_ntop.o +0 -0
  83. data/ext/asyncengine/libuv/src/cares.c +225 -0
  84. data/ext/asyncengine/libuv/src/cares.o +0 -0
  85. data/ext/asyncengine/libuv/src/fs-poll.c +237 -0
  86. data/ext/asyncengine/libuv/src/fs-poll.o +0 -0
  87. data/ext/asyncengine/libuv/src/unix/async.c +78 -17
  88. data/ext/asyncengine/libuv/src/unix/async.o +0 -0
  89. data/ext/asyncengine/libuv/src/unix/core.c +305 -213
  90. data/ext/asyncengine/libuv/src/unix/core.o +0 -0
  91. data/ext/asyncengine/libuv/src/unix/cygwin.c +1 -1
  92. data/ext/asyncengine/libuv/src/unix/darwin.c +2 -1
  93. data/ext/asyncengine/libuv/src/unix/dl.c +36 -44
  94. data/ext/asyncengine/libuv/src/unix/dl.o +0 -0
  95. data/ext/asyncengine/libuv/src/unix/eio/eio.o +0 -0
  96. data/ext/asyncengine/libuv/src/unix/error.c +6 -0
  97. data/ext/asyncengine/libuv/src/unix/error.o +0 -0
  98. data/ext/asyncengine/libuv/src/unix/ev/ev.c +8 -4
  99. data/ext/asyncengine/libuv/src/unix/ev/ev.o +0 -0
  100. data/ext/asyncengine/libuv/src/unix/freebsd.c +1 -1
  101. data/ext/asyncengine/libuv/src/unix/fs.c +25 -33
  102. data/ext/asyncengine/libuv/src/unix/fs.o +0 -0
  103. data/ext/asyncengine/libuv/src/unix/internal.h +50 -31
  104. data/ext/asyncengine/libuv/src/unix/kqueue.c +2 -7
  105. data/ext/asyncengine/libuv/src/unix/linux/core.o +0 -0
  106. data/ext/asyncengine/libuv/src/unix/linux/inotify.c +12 -14
  107. data/ext/asyncengine/libuv/src/unix/linux/inotify.o +0 -0
  108. data/ext/asyncengine/libuv/src/unix/linux/{core.c → linux-core.c} +1 -1
  109. data/ext/asyncengine/libuv/src/unix/linux/linux-core.o +0 -0
  110. data/ext/asyncengine/libuv/src/unix/linux/syscalls.c +147 -1
  111. data/ext/asyncengine/libuv/src/unix/linux/syscalls.h +39 -2
  112. data/ext/asyncengine/libuv/src/unix/linux/syscalls.o +0 -0
  113. data/ext/asyncengine/libuv/src/unix/loop-watcher.c +63 -0
  114. data/ext/asyncengine/libuv/src/unix/loop-watcher.o +0 -0
  115. data/ext/asyncengine/libuv/src/unix/loop.c +29 -6
  116. data/ext/asyncengine/libuv/src/unix/loop.o +0 -0
  117. data/ext/asyncengine/libuv/src/unix/netbsd.c +1 -1
  118. data/ext/asyncengine/libuv/src/unix/openbsd.c +1 -1
  119. data/ext/asyncengine/libuv/src/unix/pipe.c +31 -36
  120. data/ext/asyncengine/libuv/src/unix/pipe.o +0 -0
  121. data/ext/asyncengine/libuv/src/unix/poll.c +116 -0
  122. data/ext/asyncengine/libuv/src/unix/poll.o +0 -0
  123. data/ext/asyncengine/libuv/src/unix/process.c +193 -115
  124. data/ext/asyncengine/libuv/src/unix/process.o +0 -0
  125. data/ext/asyncengine/libuv/src/unix/stream.c +146 -153
  126. data/ext/asyncengine/libuv/src/unix/stream.o +0 -0
  127. data/ext/asyncengine/libuv/src/unix/sunos.c +45 -36
  128. data/ext/asyncengine/libuv/src/unix/tcp.c +6 -5
  129. data/ext/asyncengine/libuv/src/unix/tcp.o +0 -0
  130. data/ext/asyncengine/libuv/src/unix/thread.c +82 -25
  131. data/ext/asyncengine/libuv/src/unix/thread.o +0 -0
  132. data/ext/asyncengine/libuv/src/unix/timer.c +69 -58
  133. data/ext/asyncengine/libuv/src/unix/timer.o +0 -0
  134. data/ext/asyncengine/libuv/src/unix/tty.c +3 -3
  135. data/ext/asyncengine/libuv/src/unix/tty.o +0 -0
  136. data/ext/asyncengine/libuv/src/unix/udp.c +57 -66
  137. data/ext/asyncengine/libuv/src/unix/udp.o +0 -0
  138. data/ext/asyncengine/libuv/src/unix/uv-eio.c +33 -50
  139. data/ext/asyncengine/libuv/src/unix/uv-eio.o +0 -0
  140. data/ext/asyncengine/libuv/src/uv-common.c +68 -38
  141. data/ext/asyncengine/libuv/src/uv-common.h +104 -20
  142. data/ext/asyncengine/libuv/src/uv-common.o +0 -0
  143. data/ext/asyncengine/libuv/src/win/async.c +20 -17
  144. data/ext/asyncengine/libuv/src/win/core.c +44 -31
  145. data/ext/asyncengine/libuv/src/win/dl.c +40 -36
  146. data/ext/asyncengine/libuv/src/win/error.c +21 -1
  147. data/ext/asyncengine/libuv/src/win/fs-event.c +19 -21
  148. data/ext/asyncengine/libuv/src/win/fs.c +541 -189
  149. data/ext/asyncengine/libuv/src/win/getaddrinfo.c +56 -63
  150. data/ext/asyncengine/libuv/src/win/handle-inl.h +145 -0
  151. data/ext/asyncengine/libuv/src/win/handle.c +26 -101
  152. data/ext/asyncengine/libuv/src/win/internal.h +92 -107
  153. data/ext/asyncengine/libuv/src/win/loop-watcher.c +6 -14
  154. data/ext/asyncengine/libuv/src/win/pipe.c +78 -64
  155. data/ext/asyncengine/libuv/src/win/poll.c +618 -0
  156. data/ext/asyncengine/libuv/src/win/process-stdio.c +479 -0
  157. data/ext/asyncengine/libuv/src/win/process.c +147 -274
  158. data/ext/asyncengine/libuv/src/win/req-inl.h +225 -0
  159. data/ext/asyncengine/libuv/src/win/req.c +0 -149
  160. data/ext/asyncengine/libuv/src/{unix/check.c → win/stream-inl.h} +31 -42
  161. data/ext/asyncengine/libuv/src/win/stream.c +9 -43
  162. data/ext/asyncengine/libuv/src/win/tcp.c +200 -82
  163. data/ext/asyncengine/libuv/src/win/thread.c +42 -2
  164. data/ext/asyncengine/libuv/src/win/threadpool.c +3 -2
  165. data/ext/asyncengine/libuv/src/win/timer.c +13 -63
  166. data/ext/asyncengine/libuv/src/win/tty.c +26 -20
  167. data/ext/asyncengine/libuv/src/win/udp.c +26 -17
  168. data/ext/asyncengine/libuv/src/win/util.c +312 -167
  169. data/ext/asyncengine/libuv/src/win/winapi.c +16 -1
  170. data/ext/asyncengine/libuv/src/win/winapi.h +33 -9
  171. data/ext/asyncengine/libuv/src/win/winsock.c +88 -1
  172. data/ext/asyncengine/libuv/src/win/winsock.h +36 -3
  173. data/ext/asyncengine/libuv/test/benchmark-ares.c +16 -17
  174. data/ext/asyncengine/libuv/test/benchmark-fs-stat.c +164 -0
  175. data/ext/asyncengine/libuv/test/benchmark-list.h +9 -0
  176. data/ext/asyncengine/libuv/{src/unix/prepare.c → test/benchmark-loop-count.c} +42 -33
  177. data/ext/asyncengine/libuv/test/benchmark-million-timers.c +65 -0
  178. data/ext/asyncengine/libuv/test/benchmark-pound.c +1 -1
  179. data/ext/asyncengine/libuv/test/benchmark-sizes.c +2 -0
  180. data/ext/asyncengine/libuv/test/benchmark-spawn.c +7 -1
  181. data/ext/asyncengine/libuv/test/benchmark-udp-packet-storm.c +1 -1
  182. data/ext/asyncengine/libuv/test/echo-server.c +8 -0
  183. data/ext/asyncengine/libuv/test/run-tests.c +30 -0
  184. data/ext/asyncengine/libuv/test/runner-unix.c +6 -26
  185. data/ext/asyncengine/libuv/test/runner-win.c +5 -63
  186. data/ext/asyncengine/libuv/test/runner.c +10 -1
  187. data/ext/asyncengine/libuv/test/task.h +0 -8
  188. data/ext/asyncengine/libuv/test/test-async.c +43 -141
  189. data/ext/asyncengine/libuv/test/test-callback-order.c +76 -0
  190. data/ext/asyncengine/libuv/test/test-counters-init.c +2 -3
  191. data/ext/asyncengine/libuv/test/test-dlerror.c +17 -8
  192. data/ext/asyncengine/libuv/test/test-fs-event.c +31 -39
  193. data/ext/asyncengine/libuv/test/test-fs-poll.c +146 -0
  194. data/ext/asyncengine/libuv/test/test-fs.c +114 -2
  195. data/ext/asyncengine/libuv/test/test-gethostbyname.c +8 -8
  196. data/ext/asyncengine/libuv/test/test-hrtime.c +18 -15
  197. data/ext/asyncengine/libuv/test/test-ipc.c +8 -2
  198. data/ext/asyncengine/libuv/test/test-list.h +59 -9
  199. data/ext/asyncengine/libuv/test/test-loop-handles.c +2 -25
  200. data/ext/asyncengine/libuv/{src/unix/idle.c → test/test-poll-close.c} +37 -39
  201. data/ext/asyncengine/libuv/test/test-poll.c +573 -0
  202. data/ext/asyncengine/libuv/test/test-ref.c +79 -63
  203. data/ext/asyncengine/libuv/test/test-run-once.c +15 -11
  204. data/ext/asyncengine/libuv/test/test-semaphore.c +111 -0
  205. data/ext/asyncengine/libuv/test/test-spawn.c +368 -20
  206. data/ext/asyncengine/libuv/test/test-stdio-over-pipes.c +25 -35
  207. data/ext/asyncengine/libuv/test/test-tcp-close-while-connecting.c +80 -0
  208. data/ext/asyncengine/libuv/test/test-tcp-close.c +1 -1
  209. data/ext/asyncengine/libuv/test/test-tcp-connect-error-after-write.c +95 -0
  210. data/ext/asyncengine/libuv/test/test-tcp-connect-timeout.c +85 -0
  211. data/ext/asyncengine/libuv/test/test-tcp-shutdown-after-write.c +131 -0
  212. data/ext/asyncengine/libuv/test/test-tcp-write-error.c +2 -2
  213. data/ext/asyncengine/libuv/test/test-tcp-writealot.c +29 -54
  214. data/ext/asyncengine/libuv/test/test-timer-again.c +1 -1
  215. data/ext/asyncengine/libuv/test/test-timer.c +23 -1
  216. data/ext/asyncengine/libuv/test/test-udp-options.c +1 -1
  217. data/ext/asyncengine/libuv/test/{test-eio-overflow.c → test-walk-handles.c} +31 -44
  218. data/ext/asyncengine/libuv/uv.gyp +26 -9
  219. data/ext/asyncengine/rb_utilities.c +54 -0
  220. data/ext/asyncengine/rb_utilities.h +63 -0
  221. data/lib/asyncengine.rb +45 -38
  222. data/lib/asyncengine/asyncengine_ext.so +0 -0
  223. data/lib/asyncengine/debug.rb +37 -0
  224. data/lib/asyncengine/handle.rb +9 -0
  225. data/lib/asyncengine/tcp.rb +28 -0
  226. data/lib/asyncengine/timer.rb +18 -28
  227. data/lib/asyncengine/udp.rb +29 -0
  228. data/lib/asyncengine/utils.rb +32 -0
  229. data/lib/asyncengine/uv_error.rb +17 -0
  230. data/lib/asyncengine/version.rb +9 -1
  231. data/test/ae_test_helper.rb +62 -0
  232. data/test/test_basic.rb +169 -0
  233. data/test/test_call_from_other_thread.rb +55 -0
  234. data/test/test_error.rb +92 -0
  235. data/test/test_ip_utils.rb +44 -0
  236. data/test/test_next_tick.rb +37 -0
  237. data/test/test_resolver.rb +51 -0
  238. data/test/test_threads.rb +69 -0
  239. data/test/test_timer.rb +95 -0
  240. data/test/test_udp.rb +216 -0
  241. data/test/test_utils.rb +49 -0
  242. metadata +84 -57
  243. data/ext/asyncengine/libuv/mkmf.log +0 -24
  244. data/ext/asyncengine/libuv/src/unix/cares.c +0 -194
  245. data/ext/asyncengine/libuv/src/unix/cares.o +0 -0
  246. data/ext/asyncengine/libuv/src/unix/check.o +0 -0
  247. data/ext/asyncengine/libuv/src/unix/idle.o +0 -0
  248. data/ext/asyncengine/libuv/src/unix/prepare.o +0 -0
  249. data/ext/asyncengine/libuv/src/win/cares.c +0 -290
  250. data/lib/asyncengine/errors.rb +0 -5
  251. data/lib/asyncengine/next_tick.rb +0 -24
@@ -21,38 +21,99 @@
21
21
  #include "uv.h"
22
22
  #include "internal.h"
23
23
 
24
+ #include <errno.h>
25
+ #include <assert.h>
26
+ #include <stdlib.h>
27
+ #include <unistd.h>
24
28
 
25
- static void uv__async(EV_P_ ev_async* w, int revents) {
26
- uv_async_t* async = container_of(w, uv_async_t, async_watcher);
29
+ static int uv__async_init(uv_loop_t* loop);
30
+ static void uv__async_io(uv_loop_t* loop, uv__io_t* handle, int events);
27
31
 
28
- if (async->async_cb) {
29
- async->async_cb(async, 0);
30
- }
31
- }
32
32
 
33
+ int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) {
34
+ if (uv__async_init(loop))
35
+ return uv__set_sys_error(loop, errno);
33
36
 
34
- int uv_async_init(uv_loop_t* loop, uv_async_t* async, uv_async_cb async_cb) {
35
- uv__handle_init(loop, (uv_handle_t*)async, UV_ASYNC);
37
+ uv__handle_init(loop, (uv_handle_t*)handle, UV_ASYNC);
36
38
  loop->counters.async_init++;
37
39
 
38
- ev_async_init(&async->async_watcher, uv__async);
39
- async->async_cb = async_cb;
40
+ handle->async_cb = async_cb;
41
+ handle->pending = 0;
40
42
 
41
- /* Note: This does not have symmetry with the other libev wrappers. */
42
- ev_async_start(loop->ev, &async->async_watcher);
43
- ev_unref(loop->ev);
43
+ ngx_queue_insert_tail(&loop->async_handles, &handle->queue);
44
+ uv__handle_start(handle);
44
45
 
45
46
  return 0;
46
47
  }
47
48
 
48
49
 
49
- int uv_async_send(uv_async_t* async) {
50
- ev_async_send(async->loop->ev, &async->async_watcher);
50
+ int uv_async_send(uv_async_t* handle) {
51
+ int r;
52
+
53
+ handle->pending = 1; /* XXX needs a memory barrier? */
54
+
55
+ do
56
+ r = write(handle->loop->async_pipefd[1], "x", 1);
57
+ while (r == -1 && errno == EINTR);
58
+
59
+ if (r == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
60
+ return uv__set_sys_error(handle->loop, errno);
61
+
51
62
  return 0;
52
63
  }
53
64
 
54
65
 
55
66
  void uv__async_close(uv_async_t* handle) {
56
- ev_async_stop(handle->loop->ev, &handle->async_watcher);
57
- ev_ref(handle->loop->ev);
67
+ ngx_queue_remove(&handle->queue);
68
+ uv__handle_stop(handle);
69
+ }
70
+
71
+
72
+ static int uv__async_init(uv_loop_t* loop) {
73
+ if (loop->async_pipefd[0] != -1)
74
+ return 0;
75
+
76
+ if (uv__make_pipe(loop->async_pipefd, UV__F_NONBLOCK))
77
+ return -1;
78
+
79
+ uv__io_init(&loop->async_watcher,
80
+ uv__async_io,
81
+ loop->async_pipefd[0],
82
+ UV__IO_READ);
83
+ uv__io_start(loop, &loop->async_watcher);
84
+
85
+ return 0;
86
+ }
87
+
88
+
89
+ static void uv__async_io(uv_loop_t* loop, uv__io_t* handle, int events) {
90
+ char buf[1024];
91
+ ngx_queue_t* q;
92
+ uv_async_t* h;
93
+ ssize_t r;
94
+
95
+ while (1) {
96
+ r = read(loop->async_pipefd[0], buf, sizeof(buf));
97
+
98
+ if (r == sizeof(buf))
99
+ continue;
100
+
101
+ if (r != -1)
102
+ break;
103
+
104
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
105
+ break;
106
+
107
+ if (errno == EINTR)
108
+ continue;
109
+
110
+ abort();
111
+ }
112
+
113
+ ngx_queue_foreach(q, &loop->async_handles) {
114
+ h = ngx_queue_data(q, uv_async_t, queue);
115
+ if (!h->pending) continue;
116
+ h->pending = 0;
117
+ h->async_cb(h, 0);
118
+ }
58
119
  }
@@ -19,7 +19,7 @@
19
19
  */
20
20
 
21
21
  #include "uv.h"
22
- #include "unix/internal.h"
22
+ #include "internal.h"
23
23
 
24
24
  #include <stddef.h> /* NULL */
25
25
  #include <stdio.h> /* printf */
@@ -59,8 +59,6 @@
59
59
  static uv_loop_t default_loop_struct;
60
60
  static uv_loop_t* default_loop_ptr;
61
61
 
62
- static void uv__finish_close(uv_handle_t* handle);
63
-
64
62
 
65
63
  void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
66
64
  handle->close_cb = close_cb;
@@ -107,18 +105,86 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
107
105
  uv__fs_event_close((uv_fs_event_t*)handle);
108
106
  break;
109
107
 
108
+ case UV_POLL:
109
+ uv__poll_close((uv_poll_t*)handle);
110
+ break;
111
+
112
+ case UV_FS_POLL:
113
+ uv__fs_poll_close((uv_fs_poll_t*)handle);
114
+ break;
115
+
110
116
  default:
111
117
  assert(0);
112
118
  }
113
119
 
114
120
  handle->flags |= UV_CLOSING;
115
- handle->endgame_next = handle->loop->endgame_handles;
116
- handle->loop->endgame_handles = handle;
117
- uv_unref(handle->loop);
121
+
122
+ handle->next_closing = handle->loop->closing_handles;
123
+ handle->loop->closing_handles = handle;
124
+ }
125
+
126
+
127
+ static void uv__finish_close(uv_handle_t* handle) {
128
+ assert(!uv__is_active(handle));
129
+ assert(handle->flags & UV_CLOSING);
130
+ assert(!(handle->flags & UV_CLOSED));
131
+ handle->flags |= UV_CLOSED;
132
+
133
+ switch (handle->type) {
134
+ case UV_PREPARE:
135
+ case UV_CHECK:
136
+ case UV_IDLE:
137
+ case UV_ASYNC:
138
+ case UV_TIMER:
139
+ case UV_PROCESS:
140
+ case UV_FS_EVENT:
141
+ case UV_FS_POLL:
142
+ case UV_POLL:
143
+ break;
144
+
145
+ case UV_NAMED_PIPE:
146
+ case UV_TCP:
147
+ case UV_TTY:
148
+ assert(!uv__io_active(&((uv_stream_t*)handle)->read_watcher));
149
+ assert(!uv__io_active(&((uv_stream_t*)handle)->write_watcher));
150
+ assert(((uv_stream_t*)handle)->fd == -1);
151
+ uv__stream_destroy((uv_stream_t*)handle);
152
+ break;
153
+
154
+ case UV_UDP:
155
+ uv__udp_finish_close((uv_udp_t*)handle);
156
+ break;
157
+
158
+ default:
159
+ assert(0);
160
+ break;
161
+ }
162
+
163
+ uv__handle_unref(handle);
164
+ ngx_queue_remove(&handle->handle_queue);
165
+
166
+ if (handle->close_cb) {
167
+ handle->close_cb(handle);
168
+ }
118
169
  }
119
170
 
120
171
 
121
- int uv_is_closing(uv_handle_t* handle) {
172
+ static void uv__run_closing_handles(uv_loop_t* loop) {
173
+ uv_handle_t* p;
174
+ uv_handle_t* q;
175
+
176
+ p = loop->closing_handles;
177
+ loop->closing_handles = NULL;
178
+
179
+ while (p) {
180
+ q = p->next_closing;
181
+ uv__finish_close(p);
182
+ p = q;
183
+ }
184
+ }
185
+
186
+
187
+ int uv_is_closing(const uv_handle_t* handle) {
122
188
  return handle->flags & (UV_CLOSING | UV_CLOSED);
123
189
  }
124
190
 
@@ -161,247 +227,185 @@ void uv_loop_delete(uv_loop_t* loop) {
161
227
  }
162
228
 
163
229
 
164
- int uv_loop_refcount(const uv_loop_t* loop) {
165
- return ev_loop_refcount(loop->ev);
166
- }
167
-
168
-
169
- void uv__run(uv_loop_t* loop) {
170
- ev_run(loop->ev, EVRUN_ONCE);
171
-
172
- while (loop->endgame_handles)
173
- uv__finish_close(loop->endgame_handles);
174
- }
175
-
176
-
177
- int uv_run(uv_loop_t* loop) {
178
- do
179
- uv__run(loop);
180
- while (uv_loop_refcount(loop) > 0);
230
+ static unsigned int uv__poll_timeout(uv_loop_t* loop) {
231
+ if (!uv__has_active_handles(loop))
232
+ return 0;
181
233
 
182
- return 0;
183
- }
234
+ if (!ngx_queue_empty(&loop->idle_handles))
235
+ return 0;
184
236
 
237
+ if (loop->closing_handles)
238
+ return 0;
185
239
 
186
- int uv_run_once(uv_loop_t* loop) {
187
- uv__run(loop);
188
- return 0;
240
+ return uv__next_timeout(loop);
189
241
  }
190
242
 
191
243
 
192
- void uv__handle_init(uv_loop_t* loop, uv_handle_t* handle,
193
- uv_handle_type type) {
194
- loop->counters.handle_init++;
195
-
196
- handle->loop = loop;
197
- handle->type = type;
198
- handle->flags = 0;
199
- handle->endgame_next = NULL;
200
- uv_ref(loop); /* unref'd in uv_close() */
244
+ static void uv__poll(uv_loop_t* loop) {
245
+ void ev__run(EV_P_ ev_tstamp waittime);
246
+ ev_invoke_pending(loop->ev);
247
+ ev__run(loop->ev, uv__poll_timeout(loop) / 1000.);
248
+ ev_invoke_pending(loop->ev);
201
249
  }
202
250
 
203
251
 
204
- void uv__finish_close(uv_handle_t* handle) {
205
- uv_loop_t* loop = handle->loop;
206
-
207
- assert(handle->flags & UV_CLOSING);
208
- assert(!(handle->flags & UV_CLOSED));
209
- handle->flags |= UV_CLOSED;
210
-
211
- switch (handle->type) {
212
- case UV_PREPARE:
213
- assert(!ev_is_active(&((uv_prepare_t*)handle)->prepare_watcher));
214
- break;
215
-
216
- case UV_CHECK:
217
- assert(!ev_is_active(&((uv_check_t*)handle)->check_watcher));
218
- break;
219
-
220
- case UV_IDLE:
221
- assert(!ev_is_active(&((uv_idle_t*)handle)->idle_watcher));
222
- break;
223
-
224
- case UV_ASYNC:
225
- assert(!ev_is_active(&((uv_async_t*)handle)->async_watcher));
226
- break;
227
-
228
- case UV_TIMER:
229
- assert(!ev_is_active(&((uv_timer_t*)handle)->timer_watcher));
230
- break;
231
-
232
- case UV_NAMED_PIPE:
233
- case UV_TCP:
234
- case UV_TTY:
235
- assert(!ev_is_active(&((uv_stream_t*)handle)->read_watcher));
236
- assert(!ev_is_active(&((uv_stream_t*)handle)->write_watcher));
237
- assert(((uv_stream_t*)handle)->fd == -1);
238
- uv__stream_destroy((uv_stream_t*)handle);
239
- break;
240
-
241
- case UV_UDP:
242
- uv__udp_finish_close((uv_udp_t*)handle);
243
- break;
244
-
245
- case UV_PROCESS:
246
- assert(!ev_is_active(&((uv_process_t*)handle)->child_watcher));
247
- break;
248
-
249
- case UV_FS_EVENT:
250
- break;
251
-
252
- default:
253
- assert(0);
254
- break;
255
- }
256
-
257
-
258
- loop->endgame_handles = handle->endgame_next;
259
-
260
- if (handle->close_cb) {
261
- handle->close_cb(handle);
262
- }
252
+ static int uv__run(uv_loop_t* loop) {
253
+ uv_update_time(loop);
254
+ uv__run_timers(loop);
255
+ uv__run_idle(loop);
256
+ uv__run_prepare(loop);
257
+ uv__poll(loop);
258
+ uv__run_check(loop);
259
+ uv__run_closing_handles(loop);
260
+ return uv__has_active_handles(loop) || uv__has_active_reqs(loop);
263
261
  }
264
262
 
265
263
 
266
- void uv_ref(uv_loop_t* loop) {
267
- ev_ref(loop->ev);
264
+ int uv_run(uv_loop_t* loop) {
265
+ while (uv__run(loop));
266
+ return 0;
268
267
  }
269
268
 
270
269
 
271
- void uv_unref(uv_loop_t* loop) {
272
- ev_unref(loop->ev);
270
+ int uv_run_once(uv_loop_t* loop) {
271
+ return uv__run(loop);
273
272
  }
274
273
 
275
274
 
276
275
  void uv_update_time(uv_loop_t* loop) {
277
- ev_now_update(loop->ev);
276
+ loop->time = uv_hrtime() / 1000000;
278
277
  }
279
278
 
280
279
 
281
280
  int64_t uv_now(uv_loop_t* loop) {
282
- return (int64_t)(ev_now(loop->ev) * 1000);
281
+ return loop->time;
283
282
  }
284
283
 
285
284
 
286
- void uv__req_init(uv_loop_t* loop, uv_req_t* req) {
287
- loop->counters.req_init++;
288
- req->type = UV_UNKNOWN_REQ;
285
+ int uv_is_active(const uv_handle_t* handle) {
286
+ return uv__is_active(handle);
289
287
  }
290
288
 
291
289
 
292
- int uv_is_active(uv_handle_t* handle) {
293
- switch (handle->type) {
294
- case UV_CHECK:
295
- return uv__check_active((uv_check_t*)handle);
296
- case UV_IDLE:
297
- return uv__idle_active((uv_idle_t*)handle);
298
- case UV_PREPARE:
299
- return uv__prepare_active((uv_prepare_t*)handle);
300
- case UV_TIMER:
301
- return uv__timer_active((uv_timer_t*)handle);
302
- default:
303
- return 1;
304
- }
305
- }
306
-
307
-
308
- static int uv_getaddrinfo_done(eio_req* req) {
309
- uv_getaddrinfo_t* handle = req->data;
310
- struct addrinfo *res = handle->res;
290
+ static int uv_getaddrinfo_done(eio_req* req_) {
291
+ uv_getaddrinfo_t* req = req_->data;
292
+ struct addrinfo *res = req->res;
311
293
  #if __sun
312
- size_t hostlen = strlen(handle->hostname);
294
+ size_t hostlen = strlen(req->hostname);
313
295
  #endif
314
296
 
315
- handle->res = NULL;
297
+ req->res = NULL;
316
298
 
317
- uv_unref(handle->loop);
299
+ uv__req_unregister(req->loop, req);
318
300
 
319
- free(handle->hints);
320
- free(handle->service);
321
- free(handle->hostname);
301
+ /* see initialization in uv_getaddrinfo() */
302
+ if (req->hints)
303
+ free(req->hints);
304
+ else if (req->service)
305
+ free(req->service);
306
+ else if (req->hostname)
307
+ free(req->hostname);
308
+ else
309
+ assert(0);
322
310
 
323
- if (handle->retcode == 0) {
311
+ if (req->retcode == 0) {
324
312
  /* OK */
325
313
  #if EAI_NODATA /* FreeBSD deprecated EAI_NODATA */
326
- } else if (handle->retcode == EAI_NONAME || handle->retcode == EAI_NODATA) {
314
+ } else if (req->retcode == EAI_NONAME || req->retcode == EAI_NODATA) {
327
315
  #else
328
- } else if (handle->retcode == EAI_NONAME) {
316
+ } else if (req->retcode == EAI_NONAME) {
329
317
  #endif
330
- uv__set_sys_error(handle->loop, ENOENT); /* FIXME compatibility hack */
318
+ uv__set_sys_error(req->loop, ENOENT); /* FIXME compatibility hack */
331
319
  #if __sun
332
- } else if (handle->retcode == EAI_MEMORY && hostlen >= MAXHOSTNAMELEN) {
333
- uv__set_sys_error(handle->loop, ENOENT);
320
+ } else if (req->retcode == EAI_MEMORY && hostlen >= MAXHOSTNAMELEN) {
321
+ uv__set_sys_error(req->loop, ENOENT);
334
322
  #endif
335
323
  } else {
336
- handle->loop->last_err.code = UV_EADDRINFO;
337
- handle->loop->last_err.sys_errno_ = handle->retcode;
324
+ req->loop->last_err.code = UV_EADDRINFO;
325
+ req->loop->last_err.sys_errno_ = req->retcode;
338
326
  }
339
327
 
340
- handle->cb(handle, handle->retcode, res);
328
+ req->cb(req, req->retcode, res);
341
329
 
342
330
  return 0;
343
331
  }
344
332
 
345
333
 
346
- static void getaddrinfo_thread_proc(eio_req *req) {
347
- uv_getaddrinfo_t* handle = req->data;
334
+ static void getaddrinfo_thread_proc(eio_req *req_) {
335
+ uv_getaddrinfo_t* req = req_->data;
348
336
 
349
- handle->retcode = getaddrinfo(handle->hostname,
350
- handle->service,
351
- handle->hints,
352
- &handle->res);
337
+ req->retcode = getaddrinfo(req->hostname,
338
+ req->service,
339
+ req->hints,
340
+ &req->res);
353
341
  }
354
342
 
355
343
 
356
- /* stub implementation of uv_getaddrinfo */
357
344
  int uv_getaddrinfo(uv_loop_t* loop,
358
- uv_getaddrinfo_t* handle,
345
+ uv_getaddrinfo_t* req,
359
346
  uv_getaddrinfo_cb cb,
360
347
  const char* hostname,
361
348
  const char* service,
362
349
  const struct addrinfo* hints) {
363
- eio_req* req;
350
+ size_t hostname_len;
351
+ size_t service_len;
352
+ size_t hints_len;
353
+ eio_req* req_;
354
+ size_t len;
355
+ char* buf;
356
+
357
+ if (req == NULL || cb == NULL || (hostname == NULL && service == NULL))
358
+ return uv__set_artificial_error(loop, UV_EINVAL);
359
+
364
360
  uv_eio_init(loop);
365
361
 
366
- if (handle == NULL || cb == NULL ||
367
- (hostname == NULL && service == NULL)) {
368
- uv__set_artificial_error(loop, UV_EINVAL);
369
- return -1;
370
- }
362
+ hostname_len = hostname ? strlen(hostname) + 1 : 0;
363
+ service_len = service ? strlen(service) + 1 : 0;
364
+ hints_len = hints ? sizeof(*hints) : 0;
365
+ buf = malloc(hostname_len + service_len + hints_len);
366
+
367
+ if (buf == NULL)
368
+ return uv__set_artificial_error(loop, UV_ENOMEM);
371
369
 
372
- uv__req_init(loop, (uv_req_t*)handle);
373
- handle->type = UV_GETADDRINFO;
374
- handle->loop = loop;
375
- handle->cb = cb;
370
+ uv__req_init(loop, req, UV_GETADDRINFO);
371
+ req->loop = loop;
372
+ req->cb = cb;
373
+ req->res = NULL;
374
+ req->hints = NULL;
375
+ req->service = NULL;
376
+ req->hostname = NULL;
377
+ req->retcode = 0;
376
378
 
377
- /* TODO don't alloc so much. */
379
+ /* order matters, see uv_getaddrinfo_done() */
380
+ len = 0;
378
381
 
379
382
  if (hints) {
380
- handle->hints = malloc(sizeof(struct addrinfo));
381
- memcpy(handle->hints, hints, sizeof(struct addrinfo));
382
- }
383
- else {
384
- handle->hints = NULL;
383
+ req->hints = memcpy(buf + len, hints, sizeof(*hints));
384
+ len += sizeof(*hints);
385
385
  }
386
386
 
387
- /* TODO security! check lengths, check return values. */
387
+ if (service) {
388
+ req->service = memcpy(buf + len, service, service_len);
389
+ len += service_len;
390
+ }
388
391
 
389
- handle->hostname = hostname ? strdup(hostname) : NULL;
390
- handle->service = service ? strdup(service) : NULL;
391
- handle->res = NULL;
392
- handle->retcode = 0;
392
+ if (hostname) {
393
+ req->hostname = memcpy(buf + len, hostname, hostname_len);
394
+ len += hostname_len;
395
+ }
393
396
 
394
- /* TODO check handle->hostname == NULL */
395
- /* TODO check handle->service == NULL */
397
+ req_ = eio_custom(getaddrinfo_thread_proc,
398
+ EIO_PRI_DEFAULT,
399
+ uv_getaddrinfo_done,
400
+ req,
401
+ &loop->uv_eio_channel);
396
402
 
397
- uv_ref(loop);
403
+ if (req_)
404
+ return 0;
398
405
 
399
- req = eio_custom(getaddrinfo_thread_proc, EIO_PRI_DEFAULT,
400
- uv_getaddrinfo_done, handle, &loop->uv_eio_channel);
401
- assert(req);
402
- assert(req->data == handle);
406
+ free(buf);
403
407
 
404
- return 0;
408
+ return uv__set_artificial_error(loop, UV_ENOMEM);
405
409
  }
406
410
 
407
411
 
@@ -440,14 +444,18 @@ out:
440
444
  }
441
445
 
442
446
 
443
- int uv__accept(int sockfd, struct sockaddr* saddr, socklen_t slen) {
447
+ int uv__accept(int sockfd) {
444
448
  int peerfd;
445
449
 
446
450
  assert(sockfd >= 0);
447
451
 
448
452
  while (1) {
449
453
  #if __linux__
450
- peerfd = uv__accept4(sockfd, saddr, &slen, UV__SOCK_NONBLOCK|UV__SOCK_CLOEXEC);
454
+ peerfd = uv__accept4(sockfd,
455
+ NULL,
456
+ NULL,
457
+ UV__SOCK_NONBLOCK|UV__SOCK_CLOEXEC);
458
+
451
459
  if (peerfd != -1)
452
460
  break;
453
461
 
@@ -458,7 +466,9 @@ int uv__accept(int sockfd, struct sockaddr* saddr, socklen_t slen) {
458
466
  break;
459
467
  #endif
460
468
 
461
- if ((peerfd = accept(sockfd, saddr, &slen)) == -1) {
469
+ peerfd = accept(sockfd, NULL, NULL);
470
+
471
+ if (peerfd == -1) {
462
472
  if (errno == EINTR)
463
473
  continue;
464
474
  else
@@ -477,58 +487,80 @@ int uv__accept(int sockfd, struct sockaddr* saddr, socklen_t slen) {
477
487
  }
478
488
 
479
489
 
490
+ #if __linux__
491
+
492
+ int uv__nonblock(int fd, int set) {
493
+ int r;
494
+
495
+ do
496
+ r = ioctl(fd, FIONBIO, &set);
497
+ while (r == -1 && errno == EINTR);
498
+
499
+ return r;
500
+ }
501
+
502
+
503
+ int uv__cloexec(int fd, int set) {
504
+ int r;
505
+
506
+ do
507
+ r = ioctl(fd, set ? FIOCLEX : FIONCLEX);
508
+ while (r == -1 && errno == EINTR);
509
+
510
+ return r;
511
+ }
512
+
513
+ #else /* !__linux__ */
514
+
480
515
  int uv__nonblock(int fd, int set) {
481
- #if FIONBIO
482
- return ioctl(fd, FIONBIO, &set);
483
- #else
484
516
  int flags;
517
+ int r;
485
518
 
486
- if ((flags = fcntl(fd, F_GETFL)) == -1) {
519
+ do
520
+ r = fcntl(fd, F_GETFL);
521
+ while (r == -1 && errno == EINTR);
522
+
523
+ if (r == -1)
487
524
  return -1;
488
- }
489
525
 
490
- if (set) {
491
- flags |= O_NONBLOCK;
492
- } else {
493
- flags &= ~O_NONBLOCK;
494
- }
526
+ if (set)
527
+ flags = r | O_NONBLOCK;
528
+ else
529
+ flags = r & ~O_NONBLOCK;
495
530
 
496
- if (fcntl(fd, F_SETFL, flags) == -1) {
497
- return -1;
498
- }
531
+ do
532
+ r = fcntl(fd, F_SETFL, flags);
533
+ while (r == -1 && errno == EINTR);
499
534
 
500
- return 0;
501
- #endif
535
+ return r;
502
536
  }
503
537
 
504
538
 
505
539
  int uv__cloexec(int fd, int set) {
506
- #if __linux__
507
- /* Linux knows only FD_CLOEXEC so we can safely omit the fcntl(F_GETFD)
508
- * syscall. CHECKME: That's probably true for other Unices as well.
509
- */
510
- return fcntl(fd, F_SETFD, set ? FD_CLOEXEC : 0);
511
- #else
512
540
  int flags;
541
+ int r;
513
542
 
514
- if ((flags = fcntl(fd, F_GETFD)) == -1) {
543
+ do
544
+ r = fcntl(fd, F_GETFD);
545
+ while (r == -1 && errno == EINTR);
546
+
547
+ if (r == -1)
515
548
  return -1;
516
- }
517
549
 
518
- if (set) {
519
- flags |= FD_CLOEXEC;
520
- } else {
521
- flags &= ~FD_CLOEXEC;
522
- }
550
+ if (set)
551
+ flags = r | FD_CLOEXEC;
552
+ else
553
+ flags = r & ~FD_CLOEXEC;
523
554
 
524
- if (fcntl(fd, F_SETFD, flags) == -1) {
525
- return -1;
526
- }
555
+ do
556
+ r = fcntl(fd, F_SETFD, flags);
557
+ while (r == -1 && errno == EINTR);
527
558
 
528
- return 0;
529
- #endif
559
+ return r;
530
560
  }
531
561
 
562
+ #endif /* __linux__ */
563
+
532
564
 
533
565
  /* This function is not execve-safe, there is a race window
534
566
  * between the call to dup() and fcntl(FD_CLOEXEC).
@@ -586,3 +618,63 @@ uv_err_t uv_chdir(const char* dir) {
586
618
  return uv__new_sys_error(errno);
587
619
  }
588
620
  }
621
+
622
+
623
+ void uv_disable_stdio_inheritance(void) {
624
+ int fd;
625
+
626
+ /* Set the CLOEXEC flag on all open descriptors. Unconditionally try the
627
+ * first 16 file descriptors. After that, bail out after the first error.
628
+ */
629
+ for (fd = 0; ; fd++)
630
+ if (uv__cloexec(fd, 1) && fd > 15)
631
+ break;
632
+ }
633
+
634
+
635
+ static void uv__io_set_cb(uv__io_t* handle, uv__io_cb cb) {
636
+ union { void* data; uv__io_cb cb; } u;
637
+ u.cb = cb;
638
+ handle->io_watcher.data = u.data;
639
+ }
640
+
641
+
642
+ static void uv__io_rw(struct ev_loop* ev, ev_io* w, int events) {
643
+ union { void* data; uv__io_cb cb; } u;
644
+ uv_loop_t* loop = ev_userdata(ev);
645
+ uv__io_t* handle = container_of(w, uv__io_t, io_watcher);
646
+ u.data = handle->io_watcher.data;
647
+ u.cb(loop, handle, events & (EV_READ|EV_WRITE|EV_ERROR));
648
+ }
649
+
650
+
651
+ void uv__io_init(uv__io_t* handle, uv__io_cb cb, int fd, int events) {
652
+ ev_io_init(&handle->io_watcher, uv__io_rw, fd, events & (EV_READ|EV_WRITE));
653
+ uv__io_set_cb(handle, cb);
654
+ }
655
+
656
+
657
+ void uv__io_set(uv__io_t* handle, uv__io_cb cb, int fd, int events) {
658
+ ev_io_set(&handle->io_watcher, fd, events);
659
+ uv__io_set_cb(handle, cb);
660
+ }
661
+
662
+
663
+ void uv__io_start(uv_loop_t* loop, uv__io_t* handle) {
664
+ ev_io_start(loop->ev, &handle->io_watcher);
665
+ }
666
+
667
+
668
+ void uv__io_stop(uv_loop_t* loop, uv__io_t* handle) {
669
+ ev_io_stop(loop->ev, &handle->io_watcher);
670
+ }
671
+
672
+
673
+ void uv__io_feed(uv_loop_t* loop, uv__io_t* handle, int event) {
674
+ ev_feed_event(loop->ev, &handle->io_watcher, event);
675
+ }
676
+
677
+
678
+ int uv__io_active(uv__io_t* handle) {
679
+ return ev_is_active(&handle->io_watcher);
680
+ }