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
@@ -32,7 +32,7 @@
32
32
  #include <time.h>
33
33
 
34
34
  #undef NANOSEC
35
- #define NANOSEC 1000000000
35
+ #define NANOSEC ((uint64_t) 1e9)
36
36
 
37
37
 
38
38
  uint64_t uv_hrtime(void) {
@@ -37,7 +37,7 @@
37
37
  #include <unistd.h>
38
38
 
39
39
  #undef NANOSEC
40
- #define NANOSEC 1000000000
40
+ #define NANOSEC ((uint64_t) 1e9)
41
41
 
42
42
 
43
43
  static char *process_title;
@@ -29,10 +29,14 @@
29
29
  #include <unistd.h>
30
30
  #include <stdlib.h>
31
31
 
32
+ static void uv__pipe_accept(uv_loop_t* loop, uv__io_t* w, int events);
33
+
32
34
 
33
35
  int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) {
34
36
  uv__stream_init(loop, (uv_stream_t*)handle, UV_NAMED_PIPE);
35
37
  loop->counters.pipe_init++;
38
+ handle->shutdown_req = NULL;
39
+ handle->connect_req = NULL;
36
40
  handle->pipe_fname = NULL;
37
41
  handle->ipc = ipc;
38
42
  return 0;
@@ -77,22 +81,10 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
77
81
  uv_strlcpy(saddr.sun_path, pipe_fname, sizeof(saddr.sun_path));
78
82
  saddr.sun_family = AF_UNIX;
79
83
 
80
- if (bind(sockfd, (struct sockaddr*)&saddr, sizeof saddr) == -1) {
81
- /* On EADDRINUSE:
82
- *
83
- * We hold the file lock so there is no other process listening
84
- * on the socket. Ergo, it's stale - remove it.
85
- *
86
- * This assumes that the other process uses locking too
87
- * but that's a good enough assumption for now.
88
- */
89
- if (errno != EADDRINUSE
90
- || unlink(pipe_fname) == -1
91
- || bind(sockfd, (struct sockaddr*)&saddr, sizeof saddr) == -1) {
92
- /* Convert ENOENT to EACCES for compatibility with Windows. */
93
- uv__set_sys_error(handle->loop, (errno == ENOENT) ? EACCES : errno);
94
- goto out;
95
- }
84
+ if (bind(sockfd, (struct sockaddr*)&saddr, sizeof saddr)) {
85
+ /* Convert ENOENT to EACCES for compatibility with Windows. */
86
+ uv__set_sys_error(handle->loop, (errno == ENOENT) ? EACCES : errno);
87
+ goto out;
96
88
  }
97
89
  bound = 1;
98
90
 
@@ -136,8 +128,11 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
136
128
  uv__set_sys_error(handle->loop, errno);
137
129
  } else {
138
130
  handle->connection_cb = cb;
139
- ev_io_init(&handle->read_watcher, uv__pipe_accept, handle->fd, EV_READ);
140
- ev_io_start(handle->loop->ev, &handle->read_watcher);
131
+ uv__io_init(&handle->read_watcher,
132
+ uv__pipe_accept,
133
+ handle->fd,
134
+ UV__IO_READ);
135
+ uv__io_start(handle->loop, &handle->read_watcher);
141
136
  }
142
137
 
143
138
  out:
@@ -163,7 +158,9 @@ void uv__pipe_close(uv_pipe_t* handle) {
163
158
 
164
159
 
165
160
  void uv_pipe_open(uv_pipe_t* handle, uv_file fd) {
166
- uv__stream_open((uv_stream_t*)handle, fd, UV_READABLE | UV_WRITABLE);
161
+ uv__stream_open((uv_stream_t*)handle,
162
+ fd,
163
+ UV_STREAM_READABLE | UV_STREAM_WRITABLE);
167
164
  }
168
165
 
169
166
 
@@ -204,24 +201,24 @@ void uv_pipe_connect(uv_connect_t* req,
204
201
  goto out;
205
202
  }
206
203
 
207
- uv__stream_open((uv_stream_t*)handle, sockfd, UV_READABLE | UV_WRITABLE);
208
-
209
- ev_io_start(handle->loop->ev, &handle->read_watcher);
210
- ev_io_start(handle->loop->ev, &handle->write_watcher);
211
-
204
+ uv__stream_open((uv_stream_t*)handle,
205
+ sockfd,
206
+ UV_STREAM_READABLE | UV_STREAM_WRITABLE);
207
+ uv__io_start(handle->loop, &handle->read_watcher);
208
+ uv__io_start(handle->loop, &handle->write_watcher);
212
209
  status = 0;
213
210
 
214
211
  out:
215
212
  handle->delayed_error = status; /* Passed to callback. */
216
213
  handle->connect_req = req;
214
+
215
+ uv__req_init(handle->loop, req, UV_CONNECT);
217
216
  req->handle = (uv_stream_t*)handle;
218
- req->type = UV_CONNECT;
219
217
  req->cb = cb;
220
218
  ngx_queue_init(&req->queue);
221
219
 
222
220
  /* Run callback on next tick. */
223
- ev_feed_event(handle->loop->ev, &handle->read_watcher, EV_CUSTOM);
224
- assert(ev_is_pending(&handle->read_watcher));
221
+ uv__io_feed(handle->loop, &handle->write_watcher, UV__IO_WRITE);
225
222
 
226
223
  /* Mimic the Windows pipe implementation, always
227
224
  * return 0 and let the callback handle errors.
@@ -231,30 +228,28 @@ out:
231
228
 
232
229
 
233
230
  /* TODO merge with uv__server_io()? */
234
- void uv__pipe_accept(EV_P_ ev_io* watcher, int revents) {
235
- struct sockaddr_un saddr;
231
+ static void uv__pipe_accept(uv_loop_t* loop, uv__io_t* w, int events) {
236
232
  uv_pipe_t* pipe;
237
233
  int saved_errno;
238
234
  int sockfd;
239
235
 
240
236
  saved_errno = errno;
241
- pipe = watcher->data;
237
+ pipe = container_of(w, uv_pipe_t, read_watcher);
242
238
 
243
239
  assert(pipe->type == UV_NAMED_PIPE);
244
240
 
245
- sockfd = uv__accept(pipe->fd, (struct sockaddr *)&saddr, sizeof saddr);
241
+ sockfd = uv__accept(pipe->fd);
246
242
  if (sockfd == -1) {
247
- if (errno == EAGAIN || errno == EWOULDBLOCK) {
248
- assert(0 && "EAGAIN on uv__accept(pipefd)");
249
- } else {
243
+ if (errno != EAGAIN && errno != EWOULDBLOCK) {
250
244
  uv__set_sys_error(pipe->loop, errno);
245
+ pipe->connection_cb((uv_stream_t*)pipe, -1);
251
246
  }
252
247
  } else {
253
248
  pipe->accepted_fd = sockfd;
254
249
  pipe->connection_cb((uv_stream_t*)pipe, 0);
255
250
  if (pipe->accepted_fd == sockfd) {
256
- /* The user hasn't yet accepted called uv_accept() */
257
- ev_io_stop(pipe->loop->ev, &pipe->read_watcher);
251
+ /* The user hasn't called uv_accept() yet */
252
+ uv__io_stop(pipe->loop, &pipe->read_watcher);
258
253
  }
259
254
  }
260
255
 
@@ -0,0 +1,116 @@
1
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2
+ *
3
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ * of this software and associated documentation files (the "Software"), to
5
+ * deal in the Software without restriction, including without limitation the
6
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
+ * sell copies of the Software, and to permit persons to whom the Software is
8
+ * furnished to do so, subject to the following conditions:
9
+ *
10
+ * The above copyright notice and this permission notice shall be included in
11
+ * all copies or substantial portions of the Software.
12
+ *
13
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19
+ * IN THE SOFTWARE.
20
+ */
21
+
22
+ #include "uv.h"
23
+ #include "internal.h"
24
+
25
+ #include <unistd.h>
26
+ #include <assert.h>
27
+ #include <errno.h>
28
+
29
+
30
+ static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, int events) {
31
+ uv_poll_t* handle;
32
+ int pevents;
33
+
34
+ handle = container_of(w, uv_poll_t, io_watcher);
35
+
36
+ if (events & UV__IO_ERROR) {
37
+ /* An error happened. Libev has implicitly stopped the watcher, but we */
38
+ /* need to fix the refcount. */
39
+ uv__handle_stop(handle);
40
+ uv__set_sys_error(handle->loop, EBADF);
41
+ handle->poll_cb(handle, -1, 0);
42
+ return;
43
+ }
44
+
45
+ pevents = 0;
46
+ if (events & UV__IO_READ)
47
+ pevents |= UV_READABLE;
48
+ if (events & UV__IO_WRITE)
49
+ pevents |= UV_WRITABLE;
50
+
51
+ handle->poll_cb(handle, 0, pevents);
52
+ }
53
+
54
+
55
+ int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) {
56
+ uv__handle_init(loop, (uv_handle_t*) handle, UV_POLL);
57
+ loop->counters.poll_init++;
58
+
59
+ handle->fd = fd;
60
+ handle->poll_cb = NULL;
61
+ uv__io_init(&handle->io_watcher, uv__poll_io, fd, 0);
62
+
63
+ return 0;
64
+ }
65
+
66
+
67
+ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
68
+ uv_os_sock_t socket) {
69
+ return uv_poll_init(loop, handle, socket);
70
+ }
71
+
72
+
73
+ static void uv__poll_stop(uv_poll_t* handle) {
74
+ uv__io_stop(handle->loop, &handle->io_watcher);
75
+ uv__handle_stop(handle);
76
+ }
77
+
78
+
79
+ int uv_poll_stop(uv_poll_t* handle) {
80
+ assert(!(handle->flags & (UV_CLOSING | UV_CLOSED)));
81
+ uv__poll_stop(handle);
82
+ return 0;
83
+ }
84
+
85
+
86
+ int uv_poll_start(uv_poll_t* handle, int pevents, uv_poll_cb poll_cb) {
87
+ int events;
88
+
89
+ assert((pevents & ~(UV_READABLE | UV_WRITABLE)) == 0);
90
+ assert(!(handle->flags & (UV_CLOSING | UV_CLOSED)));
91
+
92
+ if (pevents == 0) {
93
+ uv__poll_stop(handle);
94
+ return 0;
95
+ }
96
+
97
+ events = 0;
98
+ if (pevents & UV_READABLE)
99
+ events |= UV__IO_READ;
100
+ if (pevents & UV_WRITABLE)
101
+ events |= UV__IO_WRITE;
102
+
103
+ uv__io_stop(handle->loop, &handle->io_watcher);
104
+ uv__io_set(&handle->io_watcher, uv__poll_io, handle->fd, events);
105
+ uv__io_start(handle->loop, &handle->io_watcher);
106
+
107
+ handle->poll_cb = poll_cb;
108
+ uv__handle_start(handle);
109
+
110
+ return 0;
111
+ }
112
+
113
+
114
+ void uv__poll_close(uv_poll_t* handle) {
115
+ uv__poll_stop(handle);
116
+ }
@@ -25,10 +25,10 @@
25
25
  #include <assert.h>
26
26
  #include <errno.h>
27
27
  #include <sys/wait.h>
28
- #include <fcntl.h> /* O_CLOEXEC, O_NONBLOCK */
29
28
  #include <poll.h>
30
29
  #include <unistd.h>
31
30
  #include <stdio.h>
31
+ #include <fcntl.h>
32
32
 
33
33
  #ifdef __APPLE__
34
34
  # include <TargetConditionals.h>
@@ -68,25 +68,15 @@ static void uv__chld(EV_P_ ev_child* watcher, int revents) {
68
68
 
69
69
 
70
70
  int uv__make_socketpair(int fds[2], int flags) {
71
- #ifdef SOCK_NONBLOCK
72
- int fl;
73
-
74
- fl = SOCK_CLOEXEC;
75
-
76
- if (flags & UV__F_NONBLOCK)
77
- fl |= SOCK_NONBLOCK;
78
-
79
- if (socketpair(AF_UNIX, SOCK_STREAM|fl, 0, fds) == 0)
71
+ #if __linux__
72
+ if (socketpair(AF_UNIX, SOCK_STREAM | UV__SOCK_CLOEXEC | flags, 0, fds) == 0)
80
73
  return 0;
81
74
 
75
+ /* Retry on EINVAL, it means SOCK_CLOEXEC is not supported.
76
+ * Anything else is a genuine error.
77
+ */
82
78
  if (errno != EINVAL)
83
79
  return -1;
84
-
85
- /* errno == EINVAL so maybe the kernel headers lied about
86
- * the availability of SOCK_NONBLOCK. This can happen if people
87
- * build libuv against newer kernel headers than the kernel
88
- * they actually run the software on.
89
- */
90
80
  #endif
91
81
 
92
82
  if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds))
@@ -106,14 +96,7 @@ int uv__make_socketpair(int fds[2], int flags) {
106
96
 
107
97
  int uv__make_pipe(int fds[2], int flags) {
108
98
  #if __linux__
109
- int fl;
110
-
111
- fl = O_CLOEXEC;
112
-
113
- if (flags & UV__F_NONBLOCK)
114
- fl |= O_NONBLOCK;
115
-
116
- if (uv__pipe2(fds, fl) == 0)
99
+ if (uv__pipe2(fds, flags | UV__O_CLOEXEC) == 0)
117
100
  return 0;
118
101
 
119
102
  if (errno != ENOSYS)
@@ -139,16 +122,146 @@ int uv__make_pipe(int fds[2], int flags) {
139
122
  * Used for initializing stdio streams like options.stdin_stream. Returns
140
123
  * zero on success.
141
124
  */
142
- static int uv__process_init_pipe(uv_pipe_t* handle, int fds[2], int flags) {
143
- if (handle->type != UV_NAMED_PIPE) {
144
- errno = EINVAL;
145
- return -1;
125
+ static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2],
126
+ int writable) {
127
+ int fd = -1;
128
+ switch (container->flags & (UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD |
129
+ UV_INHERIT_STREAM)) {
130
+ case UV_IGNORE:
131
+ return 0;
132
+ case UV_CREATE_PIPE:
133
+ assert(container->data.stream != NULL);
134
+
135
+ if (container->data.stream->type != UV_NAMED_PIPE) {
136
+ errno = EINVAL;
137
+ return -1;
138
+ }
139
+
140
+ return uv__make_socketpair(fds, 0);
141
+ case UV_INHERIT_FD:
142
+ case UV_INHERIT_STREAM:
143
+ if (container->flags & UV_INHERIT_FD) {
144
+ fd = container->data.fd;
145
+ } else {
146
+ fd = container->data.stream->fd;
147
+ }
148
+
149
+ if (fd == -1) {
150
+ errno = EINVAL;
151
+ return -1;
152
+ }
153
+
154
+ fds[writable ? 1 : 0] = fd;
155
+
156
+ return 0;
157
+ default:
158
+ assert(0 && "Unexpected flags");
159
+ return -1;
146
160
  }
161
+ }
162
+
147
163
 
148
- if (handle->ipc)
149
- return uv__make_socketpair(fds, flags);
150
- else
151
- return uv__make_pipe(fds, flags);
164
+ static int uv__process_stdio_flags(uv_stdio_container_t* container,
165
+ int writable) {
166
+ if (container->data.stream->type == UV_NAMED_PIPE &&
167
+ ((uv_pipe_t*)container->data.stream)->ipc) {
168
+ return UV_STREAM_READABLE | UV_STREAM_WRITABLE;
169
+ } else if (writable) {
170
+ return UV_STREAM_WRITABLE;
171
+ } else {
172
+ return UV_STREAM_READABLE;
173
+ }
174
+ }
175
+
176
+
177
+ static int uv__process_open_stream(uv_stdio_container_t* container, int fds[2],
178
+ int writable) {
179
+ int fd = fds[writable ? 1 : 0];
180
+ int child_fd = fds[writable ? 0 : 1];
181
+ int flags;
182
+
183
+ /* No need to create stream */
184
+ if (!(container->flags & UV_CREATE_PIPE) || fd < 0) {
185
+ return 0;
186
+ }
187
+
188
+ assert(child_fd >= 0);
189
+ close(child_fd);
190
+
191
+ uv__nonblock(fd, 1);
192
+ flags = uv__process_stdio_flags(container, writable);
193
+
194
+ return uv__stream_open((uv_stream_t*)container->data.stream, fd, flags);
195
+ }
196
+
197
+
198
+ static void uv__process_close_stream(uv_stdio_container_t* container) {
199
+ if (!(container->flags & UV_CREATE_PIPE)) return;
200
+
201
+ uv__stream_close((uv_stream_t*)container->data.stream);
202
+ }
203
+
204
+
205
+ static void uv__process_child_init(uv_process_options_t options,
206
+ int stdio_count,
207
+ int* pipes) {
208
+ int i;
209
+
210
+ if (options.flags & UV_PROCESS_DETACHED) {
211
+ setsid();
212
+ }
213
+
214
+ /* Dup fds */
215
+ for (i = 0; i < stdio_count; i++) {
216
+ /*
217
+ * stdin has swapped ends of pipe
218
+ * (it's the only one readable stream)
219
+ */
220
+ int close_fd = i == 0 ? pipes[i * 2 + 1] : pipes[i * 2];
221
+ int use_fd = i == 0 ? pipes[i * 2] : pipes[i * 2 + 1];
222
+
223
+ if (use_fd >= 0) {
224
+ close(close_fd);
225
+ } else if (i < 3) {
226
+ /* `/dev/null` stdin, stdout, stderr even if they've flag UV_IGNORE */
227
+ use_fd = open("/dev/null", i == 0 ? O_RDONLY : O_RDWR);
228
+
229
+ if (use_fd < 0) {
230
+ perror("failed to open stdio");
231
+ _exit(127);
232
+ }
233
+ } else {
234
+ continue;
235
+ }
236
+
237
+ if (i != use_fd) {
238
+ dup2(use_fd, i);
239
+ close(use_fd);
240
+ } else {
241
+ uv__cloexec(use_fd, 0);
242
+ }
243
+ }
244
+
245
+ if (options.cwd && chdir(options.cwd)) {
246
+ perror("chdir()");
247
+ _exit(127);
248
+ }
249
+
250
+ if ((options.flags & UV_PROCESS_SETGID) && setgid(options.gid)) {
251
+ perror("setgid()");
252
+ _exit(127);
253
+ }
254
+
255
+ if ((options.flags & UV_PROCESS_SETUID) && setuid(options.uid)) {
256
+ perror("setuid()");
257
+ _exit(127);
258
+ }
259
+
260
+ environ = options.env;
261
+
262
+ execvp(options.file, options.args);
263
+ perror("execvp()");
264
+ _exit(127);
152
265
  }
153
266
 
154
267
 
@@ -163,35 +276,47 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
163
276
  * by the child process.
164
277
  */
165
278
  char** save_our_env = environ;
166
- int stdin_pipe[2] = { -1, -1 };
167
- int stdout_pipe[2] = { -1, -1 };
168
- int stderr_pipe[2] = { -1, -1 };
279
+
280
+ int stdio_count = options.stdio_count < 3 ? 3 : options.stdio_count;
281
+ int* pipes = malloc(2 * stdio_count * sizeof(int));
282
+
169
283
  #if SPAWN_WAIT_EXEC
170
284
  int signal_pipe[2] = { -1, -1 };
171
285
  struct pollfd pfd;
172
286
  #endif
173
287
  int status;
174
288
  pid_t pid;
175
- int flags;
289
+ int i;
290
+
291
+ if (pipes == NULL) {
292
+ errno = ENOMEM;
293
+ goto error;
294
+ }
295
+
296
+ assert(options.file != NULL);
297
+ assert(!(options.flags & ~(UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS |
298
+ UV_PROCESS_DETACHED |
299
+ UV_PROCESS_SETGID |
300
+ UV_PROCESS_SETUID)));
301
+
176
302
 
177
303
  uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS);
178
304
  loop->counters.process_init++;
305
+ uv__handle_start(process);
179
306
 
180
307
  process->exit_cb = options.exit_cb;
181
308
 
182
- if (options.stdin_stream &&
183
- uv__process_init_pipe(options.stdin_stream, stdin_pipe, 0)) {
184
- goto error;
185
- }
186
-
187
- if (options.stdout_stream &&
188
- uv__process_init_pipe(options.stdout_stream, stdout_pipe, 0)) {
189
- goto error;
309
+ /* Init pipe pairs */
310
+ for (i = 0; i < stdio_count; i++) {
311
+ pipes[i * 2] = -1;
312
+ pipes[i * 2 + 1] = -1;
190
313
  }
191
314
 
192
- if (options.stderr_stream &&
193
- uv__process_init_pipe(options.stderr_stream, stderr_pipe, 0)) {
194
- goto error;
315
+ /* Create socketpairs/pipes, or use raw fd */
316
+ for (i = 0; i < options.stdio_count; i++) {
317
+ if (uv__process_init_stdio(&options.stdio[i], pipes + i * 2, i != 0)) {
318
+ goto error;
319
+ }
195
320
  }
196
321
 
197
322
  /* This pipe is used by the parent to wait until
@@ -231,43 +356,9 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
231
356
  }
232
357
 
233
358
  if (pid == 0) {
234
- if (stdin_pipe[0] >= 0) {
235
- close(stdin_pipe[1]);
236
- dup2(stdin_pipe[0], STDIN_FILENO);
237
- } else {
238
- /* Reset flags that might be set by Node */
239
- uv__cloexec(STDIN_FILENO, 0);
240
- uv__nonblock(STDIN_FILENO, 0);
241
- }
359
+ /* Child */
360
+ uv__process_child_init(options, stdio_count, pipes);
242
361
 
243
- if (stdout_pipe[1] >= 0) {
244
- close(stdout_pipe[0]);
245
- dup2(stdout_pipe[1], STDOUT_FILENO);
246
- } else {
247
- /* Reset flags that might be set by Node */
248
- uv__cloexec(STDOUT_FILENO, 0);
249
- uv__nonblock(STDOUT_FILENO, 0);
250
- }
251
-
252
- if (stderr_pipe[1] >= 0) {
253
- close(stderr_pipe[0]);
254
- dup2(stderr_pipe[1], STDERR_FILENO);
255
- } else {
256
- /* Reset flags that might be set by Node */
257
- uv__cloexec(STDERR_FILENO, 0);
258
- uv__nonblock(STDERR_FILENO, 0);
259
- }
260
-
261
- if (options.cwd && chdir(options.cwd)) {
262
- perror("chdir()");
263
- _exit(127);
264
- }
265
-
266
- environ = options.env;
267
-
268
- execvp(options.file, options.args);
269
- perror("execvp()");
270
- _exit(127);
271
362
  /* Execution never reaches here. */
272
363
  }
273
364
 
@@ -297,46 +388,32 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
297
388
  ev_child_start(process->loop->ev, &process->child_watcher);
298
389
  process->child_watcher.data = process;
299
390
 
300
- if (stdin_pipe[1] >= 0) {
301
- assert(options.stdin_stream);
302
- assert(stdin_pipe[0] >= 0);
303
- close(stdin_pipe[0]);
304
- uv__nonblock(stdin_pipe[1], 1);
305
- flags = UV_WRITABLE | (options.stdin_stream->ipc ? UV_READABLE : 0);
306
- uv__stream_open((uv_stream_t*)options.stdin_stream, stdin_pipe[1],
307
- flags);
308
- }
391
+ for (i = 0; i < options.stdio_count; i++) {
392
+ if (uv__process_open_stream(&options.stdio[i], pipes + i * 2, i == 0)) {
393
+ int j;
394
+ /* Close all opened streams */
395
+ for (j = 0; j < i; j++) {
396
+ uv__process_close_stream(&options.stdio[j]);
397
+ }
309
398
 
310
- if (stdout_pipe[0] >= 0) {
311
- assert(options.stdout_stream);
312
- assert(stdout_pipe[1] >= 0);
313
- close(stdout_pipe[1]);
314
- uv__nonblock(stdout_pipe[0], 1);
315
- flags = UV_READABLE | (options.stdout_stream->ipc ? UV_WRITABLE : 0);
316
- uv__stream_open((uv_stream_t*)options.stdout_stream, stdout_pipe[0],
317
- flags);
399
+ goto error;
400
+ }
318
401
  }
319
402
 
320
- if (stderr_pipe[0] >= 0) {
321
- assert(options.stderr_stream);
322
- assert(stderr_pipe[1] >= 0);
323
- close(stderr_pipe[1]);
324
- uv__nonblock(stderr_pipe[0], 1);
325
- flags = UV_READABLE | (options.stderr_stream->ipc ? UV_WRITABLE : 0);
326
- uv__stream_open((uv_stream_t*)options.stderr_stream, stderr_pipe[0],
327
- flags);
328
- }
403
+ free(pipes);
329
404
 
330
405
  return 0;
331
406
 
332
407
  error:
333
408
  uv__set_sys_error(process->loop, errno);
334
- close(stdin_pipe[0]);
335
- close(stdin_pipe[1]);
336
- close(stdout_pipe[0]);
337
- close(stdout_pipe[1]);
338
- close(stderr_pipe[0]);
339
- close(stderr_pipe[1]);
409
+
410
+ for (i = 0; i < stdio_count; i++) {
411
+ close(pipes[i * 2]);
412
+ close(pipes[i * 2 + 1]);
413
+ }
414
+
415
+ free(pipes);
416
+
340
417
  return -1;
341
418
  }
342
419
 
@@ -366,4 +443,5 @@ uv_err_t uv_kill(int pid, int signum) {
366
443
 
367
444
  void uv__process_close(uv_process_t* handle) {
368
445
  ev_child_stop(handle->loop->ev, &handle->child_watcher);
446
+ uv__handle_stop(handle);
369
447
  }