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
@@ -0,0 +1,479 @@
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 <assert.h>
23
+ #include <io.h>
24
+ #include <stdio.h>
25
+ #include <stdlib.h>
26
+
27
+ #include "uv.h"
28
+ #include "internal.h"
29
+
30
+
31
+ /*
32
+ * The `child_stdio_buffer` buffer has the following layout:
33
+ * int number_of_fds
34
+ * unsigned char crt_flags[number_of_fds]
35
+ * HANDLE os_handle[number_of_fds]
36
+ */
37
+ #define CHILD_STDIO_SIZE(count) \
38
+ (sizeof(int) + \
39
+ sizeof(unsigned char) * (count) + \
40
+ sizeof(uintptr_t) * (count))
41
+
42
+ #define CHILD_STDIO_COUNT(buffer) \
43
+ *((unsigned int*) (buffer))
44
+
45
+ #define CHILD_STDIO_CRT_FLAGS(buffer, fd) \
46
+ *((unsigned char*) (buffer) + sizeof(int) + fd)
47
+
48
+ #define CHILD_STDIO_HANDLE(buffer, fd) \
49
+ *((HANDLE*) ((unsigned char*) (buffer) + \
50
+ sizeof(int) + \
51
+ sizeof(unsigned char) * \
52
+ CHILD_STDIO_COUNT((buffer)) + \
53
+ sizeof(HANDLE) * (fd)))
54
+
55
+
56
+ /* CRT file descriptor mode flags */
57
+ #define FOPEN 0x01
58
+ #define FEOFLAG 0x02
59
+ #define FCRLF 0x04
60
+ #define FPIPE 0x08
61
+ #define FNOINHERIT 0x10
62
+ #define FAPPEND 0x20
63
+ #define FDEV 0x40
64
+ #define FTEXT 0x80
65
+
66
+
67
+ /*
68
+ * Clear the HANDLE_FLAG_INHERIT flag from all HANDLEs that were inherited
69
+ * the parent process. Don't check for errors - the stdio handles may not be
70
+ * valid, or may be closed already. There is no guarantee that this function
71
+ * does a perfect job.
72
+ */
73
+ void uv_disable_stdio_inheritance(void) {
74
+ HANDLE handle;
75
+ STARTUPINFOW si;
76
+
77
+ /* Make the windows stdio handles non-inheritable. */
78
+ handle = GetStdHandle(STD_INPUT_HANDLE);
79
+ if (handle != NULL && handle != INVALID_HANDLE_VALUE)
80
+ SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0);
81
+
82
+ handle = GetStdHandle(STD_OUTPUT_HANDLE);
83
+ if (handle != NULL && handle != INVALID_HANDLE_VALUE)
84
+ SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0);
85
+
86
+ handle = GetStdHandle(STD_ERROR_HANDLE);
87
+ if (handle != NULL && handle != INVALID_HANDLE_VALUE)
88
+ SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0);
89
+
90
+ /* Make inherited CRT FDs non-inheritable. */
91
+ GetStartupInfoW(&si);
92
+ if (uv__stdio_verify(si.lpReserved2, si.cbReserved2))
93
+ uv__stdio_noinherit(si.lpReserved2);
94
+ }
95
+
96
+
97
+ static int uv__create_stdio_pipe_pair(uv_loop_t* loop, uv_pipe_t* server_pipe,
98
+ HANDLE* child_pipe_ptr, unsigned int flags) {
99
+ char pipe_name[64];
100
+ SECURITY_ATTRIBUTES sa;
101
+ DWORD server_access = 0;
102
+ DWORD client_access = 0;
103
+ HANDLE child_pipe = INVALID_HANDLE_VALUE;
104
+
105
+ if (flags & UV_READABLE_PIPE) {
106
+ server_access |= PIPE_ACCESS_OUTBOUND;
107
+ client_access |= GENERIC_READ | FILE_WRITE_ATTRIBUTES;
108
+ }
109
+ if (flags & UV_WRITABLE_PIPE) {
110
+ server_access |= PIPE_ACCESS_INBOUND;
111
+ client_access |= GENERIC_WRITE;
112
+ }
113
+
114
+ /* Create server pipe handle. */
115
+ if (uv_stdio_pipe_server(loop,
116
+ server_pipe,
117
+ server_access,
118
+ pipe_name,
119
+ sizeof(pipe_name)) < 0) {
120
+ goto error;
121
+ }
122
+
123
+ /* Create child pipe handle. */
124
+ sa.nLength = sizeof sa;
125
+ sa.lpSecurityDescriptor = NULL;
126
+ sa.bInheritHandle = TRUE;
127
+
128
+ child_pipe = CreateFileA(pipe_name,
129
+ client_access,
130
+ 0,
131
+ &sa,
132
+ OPEN_EXISTING,
133
+ server_pipe->ipc ? FILE_FLAG_OVERLAPPED : 0,
134
+ NULL);
135
+ if (child_pipe == INVALID_HANDLE_VALUE) {
136
+ uv__set_sys_error(loop, GetLastError());
137
+ goto error;
138
+ }
139
+
140
+ #ifndef NDEBUG
141
+ /* Validate that the pipe was opened in the right mode. */
142
+ {
143
+ DWORD mode;
144
+ BOOL r = GetNamedPipeHandleState(child_pipe,
145
+ &mode,
146
+ NULL,
147
+ NULL,
148
+ NULL,
149
+ NULL,
150
+ 0);
151
+ assert(r == TRUE);
152
+ assert(mode == (PIPE_READMODE_BYTE | PIPE_WAIT));
153
+ }
154
+ #endif
155
+
156
+ /* Do a blocking ConnectNamedPipe. This should not block because we have */
157
+ /* both ends of the pipe created. */
158
+ if (!ConnectNamedPipe(server_pipe->handle, NULL)) {
159
+ if (GetLastError() != ERROR_PIPE_CONNECTED) {
160
+ uv__set_sys_error(loop, GetLastError());
161
+ goto error;
162
+ }
163
+ }
164
+
165
+ *child_pipe_ptr = child_pipe;
166
+ return 0;
167
+
168
+ error:
169
+ if (server_pipe->handle != INVALID_HANDLE_VALUE) {
170
+ uv_pipe_cleanup(loop, server_pipe);
171
+ }
172
+
173
+ if (child_pipe != INVALID_HANDLE_VALUE) {
174
+ CloseHandle(child_pipe);
175
+ }
176
+
177
+ return -1;
178
+ }
179
+
180
+
181
+ static int uv__duplicate_handle(uv_loop_t* loop, HANDLE handle, HANDLE* dup) {
182
+ HANDLE current_process;
183
+
184
+ current_process = GetCurrentProcess();
185
+
186
+ if (!DuplicateHandle(current_process,
187
+ handle,
188
+ current_process,
189
+ dup,
190
+ 0,
191
+ TRUE,
192
+ DUPLICATE_SAME_ACCESS)) {
193
+ *dup = INVALID_HANDLE_VALUE;
194
+ uv__set_sys_error(loop, GetLastError());
195
+ return -1;
196
+ }
197
+
198
+ return 0;
199
+ }
200
+
201
+
202
+ static int uv__duplicate_fd(uv_loop_t* loop, int fd, HANDLE* dup) {
203
+ HANDLE handle;
204
+
205
+ if (fd == -1) {
206
+ *dup = INVALID_HANDLE_VALUE;
207
+ uv__set_artificial_error(loop, UV_EBADF);
208
+ return -1;
209
+ }
210
+
211
+ handle = (HANDLE)_get_osfhandle(fd);
212
+ return uv__duplicate_handle(loop, handle, dup);
213
+ }
214
+
215
+
216
+ static int uv__create_nul_handle(uv_loop_t* loop, HANDLE* handle_ptr,
217
+ DWORD access) {
218
+ HANDLE handle;
219
+ SECURITY_ATTRIBUTES sa;
220
+
221
+ sa.nLength = sizeof sa;
222
+ sa.lpSecurityDescriptor = NULL;
223
+ sa.bInheritHandle = TRUE;
224
+
225
+ handle = CreateFileW(L"NUL",
226
+ access,
227
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
228
+ &sa,
229
+ OPEN_EXISTING,
230
+ 0,
231
+ NULL);
232
+ if (handle == INVALID_HANDLE_VALUE) {
233
+ uv__set_sys_error(loop, GetLastError());
234
+ return -1;
235
+ }
236
+
237
+ *handle_ptr = handle;
238
+ return 0;
239
+ }
240
+
241
+
242
+ int uv__stdio_create(uv_loop_t* loop, uv_process_options_t* options,
243
+ BYTE** buffer_ptr) {
244
+ BYTE* buffer;
245
+ int count, i;
246
+
247
+ count = options->stdio_count;
248
+
249
+ if (count < 0 || count > 255) {
250
+ /* Only support FDs 0-255 */
251
+ uv__set_artificial_error(loop, UV_ENOTSUP);
252
+ return -1;
253
+ } else if (count < 3) {
254
+ /* There should always be at least 3 stdio handles. */
255
+ count = 3;
256
+ }
257
+
258
+ /* Allocate the child stdio buffer */
259
+ buffer = malloc(CHILD_STDIO_SIZE(count));
260
+ if (buffer == NULL) {
261
+ uv__set_artificial_error(loop, UV_ENOMEM);
262
+ return -1;
263
+ }
264
+
265
+ /* Prepopulate the buffer with INVALID_HANDLE_VALUE handles so we can */
266
+ /* clean up on failure. */
267
+ CHILD_STDIO_COUNT(buffer) = count;
268
+ for (i = 0; i < count; i++) {
269
+ CHILD_STDIO_CRT_FLAGS(buffer, i) = 0;
270
+ CHILD_STDIO_HANDLE(buffer, i) = INVALID_HANDLE_VALUE;
271
+ }
272
+
273
+ for (i = 0; i < count; i++) {
274
+ uv_stdio_container_t fdopt;
275
+ if (i < options->stdio_count) {
276
+ fdopt = options->stdio[i];
277
+ } else {
278
+ fdopt.flags = UV_IGNORE;
279
+ }
280
+
281
+ switch (fdopt.flags & (UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD |
282
+ UV_INHERIT_STREAM)) {
283
+ case UV_IGNORE:
284
+ /* Starting a process with no stdin/stout/stderr can confuse it. */
285
+ /* So no matter what the user specified, we make sure the first */
286
+ /* three FDs are always open in their typical modes, e.g. stdin */
287
+ /* be readable and stdout/err should be writable. For FDs > 2, don't */
288
+ /* do anything - all handles in the stdio buffer are initialized with */
289
+ /* INVALID_HANDLE_VALUE, which should be okay. */
290
+ if (i <= 2) {
291
+ DWORD access = (i == 0) ? FILE_GENERIC_READ :
292
+ FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES;
293
+ if (uv__create_nul_handle(loop,
294
+ &CHILD_STDIO_HANDLE(buffer, i),
295
+ access) < 0) {
296
+ goto error;
297
+ }
298
+ CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV;
299
+ }
300
+ break;
301
+
302
+ case UV_CREATE_PIPE: {
303
+ /* Create a pair of two connected pipe ends; one end is turned into */
304
+ /* an uv_pipe_t for use by the parent. The other one is given to */
305
+ /* the child. */
306
+ uv_pipe_t* parent_pipe = (uv_pipe_t*) fdopt.data.stream;
307
+ HANDLE child_pipe;
308
+
309
+ /* Create a new, connected pipe pair. stdio[i].stream should point */
310
+ /* to an uninitialized, but not connected pipe handle. */
311
+ assert(fdopt.data.stream->type == UV_NAMED_PIPE);
312
+ assert(!(fdopt.data.stream->flags & UV_HANDLE_CONNECTION));
313
+ assert(!(fdopt.data.stream->flags & UV_HANDLE_PIPESERVER));
314
+
315
+ if (uv__create_stdio_pipe_pair(loop,
316
+ parent_pipe,
317
+ &child_pipe,
318
+ fdopt.flags) < 0) {
319
+ goto error;
320
+ }
321
+
322
+ CHILD_STDIO_HANDLE(buffer, i) = child_pipe;
323
+ CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FPIPE;
324
+ break;
325
+ }
326
+
327
+ case UV_INHERIT_FD: {
328
+ /* Inherit a raw FD. */
329
+ HANDLE child_handle;
330
+
331
+ /* Make an inheritable duplicate of the handle. */
332
+ if (uv__duplicate_fd(loop, fdopt.data.fd, &child_handle) < 0) {
333
+ goto error;
334
+ }
335
+
336
+ /* Figure out what the type is. */
337
+ switch (GetFileType(child_handle)) {
338
+ case FILE_TYPE_DISK:
339
+ CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN;
340
+ break;
341
+
342
+ case FILE_TYPE_PIPE:
343
+ CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FPIPE;
344
+
345
+ case FILE_TYPE_CHAR:
346
+ case FILE_TYPE_REMOTE:
347
+ CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV;
348
+ break;
349
+
350
+ case FILE_TYPE_UNKNOWN:
351
+ if (GetLastError != 0) {
352
+ uv__set_sys_error(loop, GetLastError());
353
+ CloseHandle(child_handle);
354
+ goto error;
355
+ }
356
+ CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV;
357
+ break;
358
+
359
+ default:
360
+ assert(0);
361
+ }
362
+
363
+ CHILD_STDIO_HANDLE(buffer, i) = child_handle;
364
+ break;
365
+ }
366
+
367
+ case UV_INHERIT_STREAM: {
368
+ /* Use an existing stream as the stdio handle for the child. */
369
+ HANDLE stream_handle, child_handle;
370
+ unsigned char crt_flags;
371
+ uv_stream_t* stream = fdopt.data.stream;
372
+
373
+ /* Leech the handle out of the stream. */
374
+ if (stream->type == UV_TTY) {
375
+ stream_handle = ((uv_tty_t*) stream)->handle;
376
+ crt_flags = FOPEN | FDEV;
377
+ } else if (stream->type == UV_NAMED_PIPE &&
378
+ stream->flags & UV_HANDLE_CONNECTED) {
379
+ stream_handle = ((uv_pipe_t*) stream)->handle;
380
+ crt_flags = FOPEN | FPIPE;
381
+ } else {
382
+ stream_handle = INVALID_HANDLE_VALUE;
383
+ crt_flags = 0;
384
+ }
385
+
386
+ if (stream_handle == NULL ||
387
+ stream_handle == INVALID_HANDLE_VALUE) {
388
+ /* The handle is already closed, or not yet created, or the */
389
+ /* stream type is not supported. */
390
+ uv__set_artificial_error(loop, UV_ENOTSUP);
391
+ goto error;
392
+ }
393
+
394
+ /* Make an inheritable copy of the handle. */
395
+ if (uv__duplicate_handle(loop,
396
+ stream_handle,
397
+ &child_handle) < 0) {
398
+ goto error;
399
+ }
400
+
401
+ CHILD_STDIO_HANDLE(buffer, i) = child_handle;
402
+ CHILD_STDIO_CRT_FLAGS(buffer, i) = crt_flags;
403
+ break;
404
+ }
405
+
406
+ default:
407
+ assert(0);
408
+ }
409
+ }
410
+
411
+ *buffer_ptr = buffer;
412
+ return 0;
413
+
414
+ error:
415
+ uv__stdio_destroy(buffer);
416
+ return -1;
417
+ }
418
+
419
+
420
+ void uv__stdio_destroy(BYTE* buffer) {
421
+ int i, count;
422
+
423
+ count = CHILD_STDIO_COUNT(buffer);
424
+ for (i = 0; i < count; i++) {
425
+ HANDLE handle = CHILD_STDIO_HANDLE(buffer, i);
426
+ if (handle != INVALID_HANDLE_VALUE) {
427
+ CloseHandle(handle);
428
+ }
429
+ }
430
+
431
+ free(buffer);
432
+ }
433
+
434
+
435
+ void uv__stdio_noinherit(BYTE* buffer) {
436
+ int i, count;
437
+
438
+ count = CHILD_STDIO_COUNT(buffer);
439
+ for (i = 0; i < count; i++) {
440
+ HANDLE handle = CHILD_STDIO_HANDLE(buffer, i);
441
+ if (handle != INVALID_HANDLE_VALUE) {
442
+ SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0);
443
+ }
444
+ }
445
+ }
446
+
447
+
448
+ int uv__stdio_verify(BYTE* buffer, WORD size) {
449
+ unsigned int count;
450
+
451
+ /* Check the buffer pointer. */
452
+ if (buffer == NULL)
453
+ return 0;
454
+
455
+ /* Verify that the buffer is at least big enough to hold the count. */
456
+ if (size < CHILD_STDIO_SIZE(0))
457
+ return 0;
458
+
459
+ /* Verify if the count is within range. */
460
+ count = CHILD_STDIO_COUNT(buffer);
461
+ if (count > 256)
462
+ return 0;
463
+
464
+ /* Verify that the buffer size is big enough to hold info for N FDs. */
465
+ if (size < CHILD_STDIO_SIZE(count))
466
+ return 0;
467
+
468
+ return 1;
469
+ }
470
+
471
+
472
+ WORD uv__stdio_size(BYTE* buffer) {
473
+ return (WORD) CHILD_STDIO_SIZE(CHILD_STDIO_COUNT((buffer)));
474
+ }
475
+
476
+
477
+ HANDLE uv__stdio_handle(BYTE* buffer, int fd) {
478
+ return CHILD_STDIO_HANDLE(buffer, fd);
479
+ }