asyncengine 0.0.1.testing1 → 0.0.2.alpha1

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