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
@@ -19,18 +19,21 @@
19
19
  * IN THE SOFTWARE.
20
20
  */
21
21
 
22
- #include "uv.h"
23
- #include "../uv-common.h"
24
- #include "internal.h"
25
-
26
- #include <stdio.h>
27
22
  #include <assert.h>
23
+ #include <io.h>
24
+ #include <stdio.h>
28
25
  #include <stdlib.h>
29
26
  #include <signal.h>
30
- #include <windows.h>
27
+
28
+ #include "uv.h"
29
+ #include "internal.h"
30
+ #include "handle-inl.h"
31
+ #include "req-inl.h"
32
+
31
33
 
32
34
  #define SIGKILL 9
33
35
 
36
+
34
37
  typedef struct env_var {
35
38
  const char* narrow;
36
39
  const wchar_t* wide;
@@ -41,6 +44,7 @@ typedef struct env_var {
41
44
 
42
45
  #define E_V(str) { str "=", L##str, sizeof(str), 0, 0 }
43
46
 
47
+
44
48
  #define UTF8_TO_UTF16(s, t) \
45
49
  size = uv_utf8_to_utf16(s, NULL, 0) * sizeof(wchar_t); \
46
50
  t = (wchar_t*)malloc(size); \
@@ -55,18 +59,14 @@ typedef struct env_var {
55
59
 
56
60
 
57
61
  static void uv_process_init(uv_loop_t* loop, uv_process_t* handle) {
58
- handle->type = UV_PROCESS;
59
- handle->loop = loop;
60
- handle->flags = 0;
62
+ uv__handle_init(loop, (uv_handle_t*) handle, UV_PROCESS);
61
63
  handle->exit_cb = NULL;
62
64
  handle->pid = 0;
63
65
  handle->exit_signal = 0;
64
66
  handle->wait_handle = INVALID_HANDLE_VALUE;
65
67
  handle->process_handle = INVALID_HANDLE_VALUE;
66
68
  handle->close_handle = INVALID_HANDLE_VALUE;
67
- handle->child_stdio[0] = INVALID_HANDLE_VALUE;
68
- handle->child_stdio[1] = INVALID_HANDLE_VALUE;
69
- handle->child_stdio[2] = INVALID_HANDLE_VALUE;
69
+ handle->child_stdio_buffer = NULL;
70
70
 
71
71
  uv_req_init(loop, (uv_req_t*)&handle->exit_req);
72
72
  handle->exit_req.type = UV_PROCESS_EXIT;
@@ -77,8 +77,6 @@ static void uv_process_init(uv_loop_t* loop, uv_process_t* handle) {
77
77
 
78
78
  loop->counters.handle_init++;
79
79
  loop->counters.process_init++;
80
-
81
- uv_ref(loop);
82
80
  }
83
81
 
84
82
 
@@ -639,30 +637,32 @@ static DWORD WINAPI spawn_failure(void* data) {
639
637
  char unknown[] = "unknown error\n";
640
638
  uv_process_t* process = (uv_process_t*) data;
641
639
  uv_loop_t* loop = process->loop;
642
- HANDLE child_stderr = process->child_stdio[2];
640
+ HANDLE child_stderr = uv__stdio_handle(process->child_stdio_buffer, 2);
643
641
  char* buf = NULL;
644
642
  DWORD count, written;
645
643
 
646
- WriteFile(child_stderr, syscall, sizeof(syscall) - 1, &written, NULL);
647
-
648
- count = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
649
- FORMAT_MESSAGE_FROM_SYSTEM |
650
- FORMAT_MESSAGE_IGNORE_INSERTS,
651
- NULL,
652
- process->spawn_errno,
653
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
654
- (LPSTR) &buf,
655
- 0,
656
- NULL);
657
-
658
- if (buf != NULL && count > 0) {
659
- WriteFile(child_stderr, buf, count, &written, NULL);
660
- LocalFree(buf);
661
- } else {
662
- WriteFile(child_stderr, unknown, sizeof(unknown) - 1, &written, NULL);
663
- }
644
+ if (child_stderr != INVALID_HANDLE_VALUE) {
645
+ WriteFile(child_stderr, syscall, sizeof(syscall) - 1, &written, NULL);
646
+
647
+ count = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
648
+ FORMAT_MESSAGE_FROM_SYSTEM |
649
+ FORMAT_MESSAGE_IGNORE_INSERTS,
650
+ NULL,
651
+ process->spawn_errno,
652
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
653
+ (LPSTR) &buf,
654
+ 0,
655
+ NULL);
656
+
657
+ if (buf != NULL && count > 0) {
658
+ WriteFile(child_stderr, buf, count, &written, NULL);
659
+ LocalFree(buf);
660
+ } else {
661
+ WriteFile(child_stderr, unknown, sizeof(unknown) - 1, &written, NULL);
662
+ }
664
663
 
665
- FlushFileBuffers(child_stderr);
664
+ FlushFileBuffers(child_stderr);
665
+ }
666
666
 
667
667
  /* Post completed */
668
668
  POST_COMPLETION_FOR_REQ(loop, &process->exit_req);
@@ -671,48 +671,32 @@ static DWORD WINAPI spawn_failure(void* data) {
671
671
  }
672
672
 
673
673
 
674
- static void close_child_stdio(uv_process_t* process) {
675
- int i;
676
- HANDLE handle;
677
-
678
- for (i = 0; i < ARRAY_SIZE(process->child_stdio); i++) {
679
- handle = process->child_stdio[i];
680
- if (handle != NULL && handle != INVALID_HANDLE_VALUE) {
681
- CloseHandle(handle);
682
- process->child_stdio[i] = INVALID_HANDLE_VALUE;
683
- }
684
- }
685
- }
686
-
687
-
688
674
  /* Called on main thread after a child process has exited. */
689
675
  void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) {
690
676
  DWORD exit_code;
691
677
 
678
+ /* FIXME: race condition. */
679
+ if (handle->flags & UV_HANDLE_CLOSING) {
680
+ return;
681
+ }
682
+
692
683
  /* Unregister from process notification. */
693
684
  if (handle->wait_handle != INVALID_HANDLE_VALUE) {
694
685
  UnregisterWait(handle->wait_handle);
695
686
  handle->wait_handle = INVALID_HANDLE_VALUE;
696
687
  }
697
688
 
698
- if (handle->process_handle != INVALID_HANDLE_VALUE) {
699
- /* Get the exit code. */
700
- if (!GetExitCodeProcess(handle->process_handle, &exit_code)) {
701
- exit_code = 127;
702
- }
703
-
704
- /* Clean-up the process handle. */
705
- CloseHandle(handle->process_handle);
706
- handle->process_handle = INVALID_HANDLE_VALUE;
707
- } else {
708
- /* We probably left the child stdio handles open to report the error */
709
- /* asynchronously, so close them now. */
710
- close_child_stdio(handle);
711
-
712
- /* The process never even started in the first place. */
689
+ if (handle->process_handle == INVALID_HANDLE_VALUE ||
690
+ !GetExitCodeProcess(handle->process_handle, &exit_code)) {
691
+ /* The process never even started in the first place, or we were unable */
692
+ /* to obtain the exit code. */
713
693
  exit_code = 127;
714
694
  }
715
695
 
696
+ /* Set the handle to inactive: no callbacks will be made after the exit */
697
+ /* callback.*/
698
+ uv__handle_stop(handle);
699
+
716
700
  /* Fire the exit callback. */
717
701
  if (handle->exit_cb) {
718
702
  handle->exit_cb(handle, exit_code, handle->exit_signal);
@@ -726,21 +710,9 @@ void uv_process_proc_close(uv_loop_t* loop, uv_process_t* handle) {
726
710
  }
727
711
 
728
712
 
729
- void uv_process_endgame(uv_loop_t* loop, uv_process_t* handle) {
730
- if (handle->flags & UV_HANDLE_CLOSING) {
731
- assert(!(handle->flags & UV_HANDLE_CLOSED));
732
- handle->flags |= UV_HANDLE_CLOSED;
733
-
734
- if (handle->close_cb) {
735
- handle->close_cb((uv_handle_t*)handle);
736
- }
737
-
738
- uv_unref(loop);
739
- }
740
- }
741
-
742
-
743
713
  void uv_process_close(uv_loop_t* loop, uv_process_t* handle) {
714
+ uv__handle_start(handle);
715
+
744
716
  if (handle->wait_handle != INVALID_HANDLE_VALUE) {
745
717
  handle->close_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
746
718
  UnregisterWaitEx(handle->wait_handle, handle->close_handle);
@@ -755,134 +727,52 @@ void uv_process_close(uv_loop_t* loop, uv_process_t* handle) {
755
727
  }
756
728
 
757
729
 
758
- static int uv_create_stdio_pipe_pair(uv_loop_t* loop, uv_pipe_t* server_pipe,
759
- HANDLE* child_pipe, DWORD server_access, DWORD child_access,
760
- int overlapped) {
761
- int err;
762
- SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
763
- char pipe_name[64];
764
- DWORD mode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT;
765
-
766
- if (server_pipe->type != UV_NAMED_PIPE) {
767
- uv__set_artificial_error(loop, UV_EINVAL);
768
- err = -1;
769
- goto done;
770
- }
771
-
772
- /* Create server pipe handle. */
773
- err = uv_stdio_pipe_server(loop,
774
- server_pipe,
775
- server_access,
776
- pipe_name,
777
- sizeof(pipe_name));
778
- if (err) {
779
- goto done;
780
- }
781
-
782
- /* Create child pipe handle. */
783
- *child_pipe = CreateFileA(pipe_name,
784
- child_access,
785
- 0,
786
- &sa,
787
- OPEN_EXISTING,
788
- overlapped ? FILE_FLAG_OVERLAPPED : 0,
789
- NULL);
790
-
791
- if (*child_pipe == INVALID_HANDLE_VALUE) {
792
- uv__set_sys_error(loop, GetLastError());
793
- err = -1;
794
- goto done;
795
- }
796
-
797
- if (!SetNamedPipeHandleState(*child_pipe, &mode, NULL, NULL)) {
798
- uv__set_sys_error(loop, GetLastError());
799
- err = -1;
800
- goto done;
801
- }
802
-
803
- /* Do a blocking ConnectNamedPipe. This should not block because
804
- * we have both ends of the pipe created.
805
- */
806
- if (!ConnectNamedPipe(server_pipe->handle, NULL)) {
807
- if (GetLastError() != ERROR_PIPE_CONNECTED) {
808
- uv__set_sys_error(loop, GetLastError());
809
- err = -1;
810
- goto done;
811
- }
812
- }
813
-
814
- err = 0;
730
+ void uv_process_endgame(uv_loop_t* loop, uv_process_t* handle) {
731
+ if (handle->flags & UV_HANDLE_CLOSING) {
732
+ assert(!(handle->flags & UV_HANDLE_CLOSED));
733
+ uv__handle_stop(handle);
815
734
 
816
- done:
817
- if (err) {
818
- if (server_pipe->handle != INVALID_HANDLE_VALUE) {
819
- close_pipe(server_pipe, NULL, NULL);
820
- }
735
+ /* Clean-up the process handle. */
736
+ CloseHandle(handle->process_handle);
821
737
 
822
- if (*child_pipe != INVALID_HANDLE_VALUE) {
823
- CloseHandle(*child_pipe);
824
- *child_pipe = INVALID_HANDLE_VALUE;
738
+ /* Clean up the child stdio ends that may have been left open. */
739
+ if (handle->child_stdio_buffer != NULL) {
740
+ uv__stdio_destroy(handle->child_stdio_buffer);
825
741
  }
826
- }
827
-
828
- return err;
829
- }
830
-
831
-
832
- static int duplicate_std_handle(uv_loop_t* loop, DWORD id, HANDLE* dup) {
833
- HANDLE handle;
834
- HANDLE current_process = GetCurrentProcess();
835
-
836
- handle = GetStdHandle(id);
837
-
838
- if (handle == NULL) {
839
- *dup = NULL;
840
- return 0;
841
- } else if (handle == INVALID_HANDLE_VALUE) {
842
- *dup = INVALID_HANDLE_VALUE;
843
- uv__set_sys_error(loop, GetLastError());
844
- return -1;
845
- }
846
742
 
847
- if (!DuplicateHandle(current_process,
848
- handle,
849
- current_process,
850
- dup,
851
- 0,
852
- TRUE,
853
- DUPLICATE_SAME_ACCESS)) {
854
- *dup = INVALID_HANDLE_VALUE;
855
- uv__set_sys_error(loop, GetLastError());
856
- return -1;
743
+ uv__handle_close(handle);
857
744
  }
858
-
859
- return 0;
860
745
  }
861
746
 
862
747
 
863
748
  int uv_spawn(uv_loop_t* loop, uv_process_t* process,
864
749
  uv_process_options_t options) {
865
- int err = 0, keep_child_stdio_open = 0;
750
+ int i, size, err = 0, keep_child_stdio_open = 0;
866
751
  wchar_t* path = NULL;
867
- int size;
868
752
  BOOL result;
869
753
  wchar_t* application_path = NULL, *application = NULL, *arguments = NULL,
870
- *env = NULL, *cwd = NULL;
871
- HANDLE* child_stdio = process->child_stdio;
754
+ *env = NULL, *cwd = NULL;
872
755
  STARTUPINFOW startup;
873
756
  PROCESS_INFORMATION info;
757
+ DWORD process_flags;
874
758
 
875
- if (!options.file) {
876
- uv__set_artificial_error(loop, UV_EINVAL);
759
+ if (options.flags & (UV_PROCESS_SETGID | UV_PROCESS_SETUID)) {
760
+ uv__set_artificial_error(loop, UV_ENOTSUP);
877
761
  return -1;
878
762
  }
879
763
 
764
+ assert(options.file != NULL);
765
+ assert(!(options.flags & ~(UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS |
766
+ UV_PROCESS_DETACHED |
767
+ UV_PROCESS_SETGID |
768
+ UV_PROCESS_SETUID)));
769
+
880
770
  uv_process_init(loop, process);
881
771
 
882
772
  process->exit_cb = options.exit_cb;
883
773
  UTF8_TO_UTF16(options.file, application);
884
774
  arguments = options.args ? make_program_args(options.args,
885
- options.windows_verbatim_arguments) : NULL;
775
+ options.flags & UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS) : NULL;
886
776
  env = options.env ? make_program_env(options.env) : NULL;
887
777
 
888
778
  if (options.cwd) {
@@ -892,8 +782,11 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
892
782
  if (size) {
893
783
  cwd = (wchar_t*)malloc(size);
894
784
  if (!cwd) {
895
- uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
785
+ uv__set_artificial_error(loop, UV_ENOMEM);
786
+ err = -1;
787
+ goto done;
896
788
  }
789
+
897
790
  GetCurrentDirectoryW(size, cwd);
898
791
  } else {
899
792
  uv__set_sys_error(loop, GetLastError());
@@ -921,59 +814,10 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
921
814
  application_path = application;
922
815
  }
923
816
 
924
- /* Create stdio pipes. */
925
- if (options.stdin_stream) {
926
- if (options.stdin_stream->ipc) {
927
- err = uv_create_stdio_pipe_pair(
928
- loop,
929
- options.stdin_stream,
930
- &child_stdio[0],
931
- PIPE_ACCESS_DUPLEX,
932
- GENERIC_READ | FILE_WRITE_ATTRIBUTES | GENERIC_WRITE,
933
- 1);
934
- } else {
935
- err = uv_create_stdio_pipe_pair(
936
- loop,
937
- options.stdin_stream,
938
- &child_stdio[0],
939
- PIPE_ACCESS_OUTBOUND,
940
- GENERIC_READ | FILE_WRITE_ATTRIBUTES,
941
- 0);
942
- }
943
- } else {
944
- err = duplicate_std_handle(loop, STD_INPUT_HANDLE, &child_stdio[0]);
945
- }
946
- if (err) {
947
- goto done;
948
- }
949
-
950
- if (options.stdout_stream) {
951
- err = uv_create_stdio_pipe_pair(
952
- loop, options.stdout_stream,
953
- &child_stdio[1],
954
- PIPE_ACCESS_INBOUND,
955
- GENERIC_WRITE,
956
- 0);
957
- } else {
958
- err = duplicate_std_handle(loop, STD_OUTPUT_HANDLE, &child_stdio[1]);
959
- }
960
- if (err) {
961
- goto done;
962
- }
963
817
 
964
- if (options.stderr_stream) {
965
- err = uv_create_stdio_pipe_pair(
966
- loop,
967
- options.stderr_stream,
968
- &child_stdio[2],
969
- PIPE_ACCESS_INBOUND,
970
- GENERIC_WRITE,
971
- 0);
972
- } else {
973
- err = duplicate_std_handle(loop, STD_ERROR_HANDLE, &child_stdio[2]);
974
- }
975
- if (err) {
976
- goto done;
818
+ if (uv__stdio_create(loop, &options, &process->child_stdio_buffer) < 0) {
819
+ err = -1;
820
+ goto done;
977
821
  }
978
822
 
979
823
  startup.cb = sizeof(startup);
@@ -981,18 +825,23 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
981
825
  startup.lpDesktop = NULL;
982
826
  startup.lpTitle = NULL;
983
827
  startup.dwFlags = STARTF_USESTDHANDLES;
984
- startup.cbReserved2 = 0;
985
- startup.lpReserved2 = NULL;
986
- startup.hStdInput = child_stdio[0];
987
- startup.hStdOutput = child_stdio[1];
988
- startup.hStdError = child_stdio[2];
828
+ startup.cbReserved2 = uv__stdio_size(process->child_stdio_buffer);
829
+ startup.lpReserved2 = (BYTE*) process->child_stdio_buffer;
830
+ startup.hStdInput = uv__stdio_handle(process->child_stdio_buffer, 0);
831
+ startup.hStdOutput = uv__stdio_handle(process->child_stdio_buffer, 1);
832
+ startup.hStdError = uv__stdio_handle(process->child_stdio_buffer, 2);
833
+
834
+ process_flags = CREATE_UNICODE_ENVIRONMENT;
835
+ if (options.flags & UV_PROCESS_DETACHED) {
836
+ process_flags |= DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP;
837
+ }
989
838
 
990
839
  if (CreateProcessW(application_path,
991
840
  arguments,
992
841
  NULL,
993
842
  NULL,
994
843
  1,
995
- CREATE_UNICODE_ENVIRONMENT,
844
+ process_flags,
996
845
  env,
997
846
  cwd,
998
847
  &startup,
@@ -1001,9 +850,14 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
1001
850
  process->process_handle = info.hProcess;
1002
851
  process->pid = info.dwProcessId;
1003
852
 
1004
- if (options.stdin_stream &&
1005
- options.stdin_stream->ipc) {
1006
- options.stdin_stream->ipc_pid = info.dwProcessId;
853
+ /* Set IPC pid to all IPC pipes. */
854
+ for (i = 0; i < options.stdio_count; i++) {
855
+ const uv_stdio_container_t* fdopt = &options.stdio[i];
856
+ if (fdopt->flags & UV_CREATE_PIPE &&
857
+ fdopt->data.stream->type == UV_NAMED_PIPE &&
858
+ ((uv_pipe_t*) fdopt->data.stream)->ipc) {
859
+ ((uv_pipe_t*) fdopt->data.stream)->ipc_pid = info.dwProcessId;
860
+ }
1007
861
  }
1008
862
 
1009
863
  /* Setup notifications for when the child process exits. */
@@ -1038,22 +892,27 @@ done:
1038
892
  free(env);
1039
893
  free(path);
1040
894
 
1041
- /* Under normal circumstances we should close the stdio handles now - */
1042
- /* the child now has its own duplicates, or something went horribly wrong. */
895
+ /* Under normal circumstances we should close the stdio handles now - the */
896
+ /* the child now has its own duplicates, or something went horribly wrong */
1043
897
  /* The only exception is when CreateProcess has failed, then we actually */
1044
898
  /* need to keep the stdio handles to report the error asynchronously. */
1045
- if (!keep_child_stdio_open) {
1046
- close_child_stdio(process);
899
+ if (process->child_stdio_buffer == NULL) {
900
+ /* Something went wrong before child stdio was initialized. */
901
+ } else if (!keep_child_stdio_open) {
902
+ uv__stdio_destroy(process->child_stdio_buffer);
903
+ process->child_stdio_buffer = NULL;
1047
904
  } else {
1048
905
  /* We're keeping the handles open, the thread pool is going to have */
1049
906
  /* it's way with them. But at least make them non-inheritable. */
1050
- int i;
1051
- for (i = 0; i < ARRAY_SIZE(process->child_stdio); i++) {
1052
- SetHandleInformation(child_stdio[i], HANDLE_FLAG_INHERIT, 0);
1053
- }
907
+ uv__stdio_noinherit(process->child_stdio_buffer);
1054
908
  }
1055
909
 
1056
- if (err) {
910
+ if (err == 0) {
911
+ /* Spawn was succesful. The handle will be active until the exit */
912
+ /* is made or the handle is closed, whichever happens first. */
913
+ uv__handle_start(process);
914
+ } else {
915
+ /* Spawn was not successful. Clean up. */
1057
916
  if (process->wait_handle != INVALID_HANDLE_VALUE) {
1058
917
  UnregisterWait(process->wait_handle);
1059
918
  process->wait_handle = INVALID_HANDLE_VALUE;
@@ -1070,32 +929,46 @@ done:
1070
929
 
1071
930
 
1072
931
  static uv_err_t uv__kill(HANDLE process_handle, int signum) {
1073
- DWORD status;
1074
- uv_err_t err;
932
+ switch (signum) {
933
+ case SIGTERM:
934
+ case SIGKILL:
935
+ case SIGINT: {
936
+ /* Unconditionally terminate the process. On Windows, killed processes */
937
+ /* normally return 1. */
938
+ DWORD error, status;
939
+
940
+ if (TerminateProcess(process_handle, 1))
941
+ return uv_ok_;
942
+
943
+ /* If the process already exited before TerminateProcess was called, */
944
+ /* TerminateProcess will fail with ERROR_ACESS_DENIED. */
945
+ error = GetLastError();
946
+ if (error == ERROR_ACCESS_DENIED &&
947
+ GetExitCodeProcess(process_handle, &status) &&
948
+ status != STILL_ACTIVE) {
949
+ return uv__new_artificial_error(UV_ESRCH);
950
+ }
1075
951
 
1076
- if (signum == SIGTERM || signum == SIGKILL || signum == SIGINT) {
1077
- /* Kill the process. On Windows, killed processes normally return 1. */
1078
- if (TerminateProcess(process_handle, 1)) {
1079
- err = uv_ok_;
1080
- } else {
1081
- err = uv__new_sys_error(GetLastError());
952
+ return uv__new_sys_error(error);
1082
953
  }
1083
- } else if (signum == 0) {
1084
- /* Health check: is the process still alive? */
1085
- if (GetExitCodeProcess(process_handle, &status)) {
1086
- if (status == STILL_ACTIVE) {
1087
- err = uv_ok_;
1088
- } else {
1089
- err = uv__new_artificial_error(UV_ESRCH);
1090
- }
1091
- } else {
1092
- err = uv__new_sys_error(GetLastError());
954
+
955
+ case 0: {
956
+ /* Health check: is the process still alive? */
957
+ DWORD status;
958
+
959
+ if (!GetExitCodeProcess(process_handle, &status))
960
+ return uv__new_sys_error(GetLastError());
961
+
962
+ if (status != STILL_ACTIVE)
963
+ return uv__new_artificial_error(UV_ESRCH);
964
+
965
+ return uv_ok_;
1093
966
  }
1094
- } else {
1095
- err = uv__new_artificial_error(UV_ENOSYS);
1096
- }
1097
967
 
1098
- return err;
968
+ default:
969
+ /* Unsupported signal. */
970
+ return uv__new_artificial_error(UV_ENOSYS);
971
+ }
1099
972
  }
1100
973
 
1101
974