asyncengine 0.0.1.testing

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 (317) hide show
  1. data/README.markdown +0 -0
  2. data/asyncengine.gemspec +26 -0
  3. data/ext/asyncengine_ext/asyncengine_ruby.c +82 -0
  4. data/ext/asyncengine_ext/extconf.rb +47 -0
  5. data/ext/asyncengine_ext/libuv/AUTHORS +45 -0
  6. data/ext/asyncengine_ext/libuv/LICENSE +42 -0
  7. data/ext/asyncengine_ext/libuv/Makefile +119 -0
  8. data/ext/asyncengine_ext/libuv/README.md +88 -0
  9. data/ext/asyncengine_ext/libuv/build/gcc_version.py +20 -0
  10. data/ext/asyncengine_ext/libuv/common.gypi +176 -0
  11. data/ext/asyncengine_ext/libuv/config-mingw.mk +61 -0
  12. data/ext/asyncengine_ext/libuv/config-unix.mk +173 -0
  13. data/ext/asyncengine_ext/libuv/gyp_uv +60 -0
  14. data/ext/asyncengine_ext/libuv/include/ares.h +591 -0
  15. data/ext/asyncengine_ext/libuv/include/ares_version.h +24 -0
  16. data/ext/asyncengine_ext/libuv/include/uv-private/eio.h +403 -0
  17. data/ext/asyncengine_ext/libuv/include/uv-private/ev.h +838 -0
  18. data/ext/asyncengine_ext/libuv/include/uv-private/ngx-queue.h +106 -0
  19. data/ext/asyncengine_ext/libuv/include/uv-private/tree.h +768 -0
  20. data/ext/asyncengine_ext/libuv/include/uv-private/uv-unix.h +256 -0
  21. data/ext/asyncengine_ext/libuv/include/uv-private/uv-win.h +458 -0
  22. data/ext/asyncengine_ext/libuv/include/uv.h +1556 -0
  23. data/ext/asyncengine_ext/libuv/src/ares/AUTHORS +37 -0
  24. data/ext/asyncengine_ext/libuv/src/ares/CHANGES +1218 -0
  25. data/ext/asyncengine_ext/libuv/src/ares/CMakeLists.txt +22 -0
  26. data/ext/asyncengine_ext/libuv/src/ares/NEWS +21 -0
  27. data/ext/asyncengine_ext/libuv/src/ares/README +60 -0
  28. data/ext/asyncengine_ext/libuv/src/ares/README.cares +13 -0
  29. data/ext/asyncengine_ext/libuv/src/ares/README.msvc +142 -0
  30. data/ext/asyncengine_ext/libuv/src/ares/README.node +21 -0
  31. data/ext/asyncengine_ext/libuv/src/ares/RELEASE-NOTES +26 -0
  32. data/ext/asyncengine_ext/libuv/src/ares/TODO +23 -0
  33. data/ext/asyncengine_ext/libuv/src/ares/ares__close_sockets.c +66 -0
  34. data/ext/asyncengine_ext/libuv/src/ares/ares__get_hostent.c +263 -0
  35. data/ext/asyncengine_ext/libuv/src/ares/ares__read_line.c +71 -0
  36. data/ext/asyncengine_ext/libuv/src/ares/ares__timeval.c +111 -0
  37. data/ext/asyncengine_ext/libuv/src/ares/ares_cancel.c +63 -0
  38. data/ext/asyncengine_ext/libuv/src/ares/ares_data.c +190 -0
  39. data/ext/asyncengine_ext/libuv/src/ares/ares_data.h +65 -0
  40. data/ext/asyncengine_ext/libuv/src/ares/ares_destroy.c +105 -0
  41. data/ext/asyncengine_ext/libuv/src/ares/ares_dns.h +90 -0
  42. data/ext/asyncengine_ext/libuv/src/ares/ares_expand_name.c +200 -0
  43. data/ext/asyncengine_ext/libuv/src/ares/ares_expand_string.c +75 -0
  44. data/ext/asyncengine_ext/libuv/src/ares/ares_fds.c +63 -0
  45. data/ext/asyncengine_ext/libuv/src/ares/ares_free_hostent.c +42 -0
  46. data/ext/asyncengine_ext/libuv/src/ares/ares_free_string.c +25 -0
  47. data/ext/asyncengine_ext/libuv/src/ares/ares_getenv.c +30 -0
  48. data/ext/asyncengine_ext/libuv/src/ares/ares_getenv.h +26 -0
  49. data/ext/asyncengine_ext/libuv/src/ares/ares_gethostbyaddr.c +301 -0
  50. data/ext/asyncengine_ext/libuv/src/ares/ares_gethostbyname.c +523 -0
  51. data/ext/asyncengine_ext/libuv/src/ares/ares_getnameinfo.c +427 -0
  52. data/ext/asyncengine_ext/libuv/src/ares/ares_getopt.c +122 -0
  53. data/ext/asyncengine_ext/libuv/src/ares/ares_getopt.h +53 -0
  54. data/ext/asyncengine_ext/libuv/src/ares/ares_getsock.c +72 -0
  55. data/ext/asyncengine_ext/libuv/src/ares/ares_init.c +1809 -0
  56. data/ext/asyncengine_ext/libuv/src/ares/ares_iphlpapi.h +221 -0
  57. data/ext/asyncengine_ext/libuv/src/ares/ares_ipv6.h +78 -0
  58. data/ext/asyncengine_ext/libuv/src/ares/ares_library_init.c +142 -0
  59. data/ext/asyncengine_ext/libuv/src/ares/ares_library_init.h +42 -0
  60. data/ext/asyncengine_ext/libuv/src/ares/ares_llist.c +86 -0
  61. data/ext/asyncengine_ext/libuv/src/ares/ares_llist.h +42 -0
  62. data/ext/asyncengine_ext/libuv/src/ares/ares_mkquery.c +195 -0
  63. data/ext/asyncengine_ext/libuv/src/ares/ares_nowarn.c +181 -0
  64. data/ext/asyncengine_ext/libuv/src/ares/ares_nowarn.h +55 -0
  65. data/ext/asyncengine_ext/libuv/src/ares/ares_options.c +248 -0
  66. data/ext/asyncengine_ext/libuv/src/ares/ares_parse_a_reply.c +263 -0
  67. data/ext/asyncengine_ext/libuv/src/ares/ares_parse_aaaa_reply.c +259 -0
  68. data/ext/asyncengine_ext/libuv/src/ares/ares_parse_mx_reply.c +170 -0
  69. data/ext/asyncengine_ext/libuv/src/ares/ares_parse_ns_reply.c +182 -0
  70. data/ext/asyncengine_ext/libuv/src/ares/ares_parse_ptr_reply.c +217 -0
  71. data/ext/asyncengine_ext/libuv/src/ares/ares_parse_srv_reply.c +179 -0
  72. data/ext/asyncengine_ext/libuv/src/ares/ares_parse_txt_reply.c +201 -0
  73. data/ext/asyncengine_ext/libuv/src/ares/ares_platform.c +11035 -0
  74. data/ext/asyncengine_ext/libuv/src/ares/ares_platform.h +43 -0
  75. data/ext/asyncengine_ext/libuv/src/ares/ares_private.h +355 -0
  76. data/ext/asyncengine_ext/libuv/src/ares/ares_process.c +1295 -0
  77. data/ext/asyncengine_ext/libuv/src/ares/ares_query.c +183 -0
  78. data/ext/asyncengine_ext/libuv/src/ares/ares_rules.h +144 -0
  79. data/ext/asyncengine_ext/libuv/src/ares/ares_search.c +321 -0
  80. data/ext/asyncengine_ext/libuv/src/ares/ares_send.c +134 -0
  81. data/ext/asyncengine_ext/libuv/src/ares/ares_setup.h +199 -0
  82. data/ext/asyncengine_ext/libuv/src/ares/ares_strcasecmp.c +66 -0
  83. data/ext/asyncengine_ext/libuv/src/ares/ares_strcasecmp.h +30 -0
  84. data/ext/asyncengine_ext/libuv/src/ares/ares_strdup.c +42 -0
  85. data/ext/asyncengine_ext/libuv/src/ares/ares_strdup.h +26 -0
  86. data/ext/asyncengine_ext/libuv/src/ares/ares_strerror.c +56 -0
  87. data/ext/asyncengine_ext/libuv/src/ares/ares_timeout.c +80 -0
  88. data/ext/asyncengine_ext/libuv/src/ares/ares_version.c +11 -0
  89. data/ext/asyncengine_ext/libuv/src/ares/ares_writev.c +79 -0
  90. data/ext/asyncengine_ext/libuv/src/ares/ares_writev.h +36 -0
  91. data/ext/asyncengine_ext/libuv/src/ares/bitncmp.c +59 -0
  92. data/ext/asyncengine_ext/libuv/src/ares/bitncmp.h +26 -0
  93. data/ext/asyncengine_ext/libuv/src/ares/config_cygwin/ares_config.h +512 -0
  94. data/ext/asyncengine_ext/libuv/src/ares/config_darwin/ares_config.h +512 -0
  95. data/ext/asyncengine_ext/libuv/src/ares/config_freebsd/ares_config.h +512 -0
  96. data/ext/asyncengine_ext/libuv/src/ares/config_linux/ares_config.h +512 -0
  97. data/ext/asyncengine_ext/libuv/src/ares/config_netbsd/ares_config.h +512 -0
  98. data/ext/asyncengine_ext/libuv/src/ares/config_openbsd/ares_config.h +512 -0
  99. data/ext/asyncengine_ext/libuv/src/ares/config_sunos/ares_config.h +512 -0
  100. data/ext/asyncengine_ext/libuv/src/ares/config_win32/ares_config.h +369 -0
  101. data/ext/asyncengine_ext/libuv/src/ares/get_ver.awk +35 -0
  102. data/ext/asyncengine_ext/libuv/src/ares/inet_net_pton.c +451 -0
  103. data/ext/asyncengine_ext/libuv/src/ares/inet_net_pton.h +31 -0
  104. data/ext/asyncengine_ext/libuv/src/ares/inet_ntop.c +208 -0
  105. data/ext/asyncengine_ext/libuv/src/ares/inet_ntop.h +26 -0
  106. data/ext/asyncengine_ext/libuv/src/ares/nameser.h +203 -0
  107. data/ext/asyncengine_ext/libuv/src/ares/setup_once.h +504 -0
  108. data/ext/asyncengine_ext/libuv/src/ares/windows_port.c +22 -0
  109. data/ext/asyncengine_ext/libuv/src/unix/async.c +58 -0
  110. data/ext/asyncengine_ext/libuv/src/unix/cares.c +194 -0
  111. data/ext/asyncengine_ext/libuv/src/unix/check.c +80 -0
  112. data/ext/asyncengine_ext/libuv/src/unix/core.c +588 -0
  113. data/ext/asyncengine_ext/libuv/src/unix/cygwin.c +84 -0
  114. data/ext/asyncengine_ext/libuv/src/unix/darwin.c +341 -0
  115. data/ext/asyncengine_ext/libuv/src/unix/dl.c +91 -0
  116. data/ext/asyncengine_ext/libuv/src/unix/eio/Changes +63 -0
  117. data/ext/asyncengine_ext/libuv/src/unix/eio/LICENSE +36 -0
  118. data/ext/asyncengine_ext/libuv/src/unix/eio/Makefile.am +15 -0
  119. data/ext/asyncengine_ext/libuv/src/unix/eio/aclocal.m4 +8957 -0
  120. data/ext/asyncengine_ext/libuv/src/unix/eio/autogen.sh +3 -0
  121. data/ext/asyncengine_ext/libuv/src/unix/eio/config.h.in +86 -0
  122. data/ext/asyncengine_ext/libuv/src/unix/eio/config_cygwin.h +80 -0
  123. data/ext/asyncengine_ext/libuv/src/unix/eio/config_darwin.h +141 -0
  124. data/ext/asyncengine_ext/libuv/src/unix/eio/config_freebsd.h +81 -0
  125. data/ext/asyncengine_ext/libuv/src/unix/eio/config_linux.h +94 -0
  126. data/ext/asyncengine_ext/libuv/src/unix/eio/config_netbsd.h +81 -0
  127. data/ext/asyncengine_ext/libuv/src/unix/eio/config_openbsd.h +137 -0
  128. data/ext/asyncengine_ext/libuv/src/unix/eio/config_sunos.h +84 -0
  129. data/ext/asyncengine_ext/libuv/src/unix/eio/configure.ac +22 -0
  130. data/ext/asyncengine_ext/libuv/src/unix/eio/demo.c +194 -0
  131. data/ext/asyncengine_ext/libuv/src/unix/eio/ecb.h +370 -0
  132. data/ext/asyncengine_ext/libuv/src/unix/eio/eio.3 +3428 -0
  133. data/ext/asyncengine_ext/libuv/src/unix/eio/eio.c +2593 -0
  134. data/ext/asyncengine_ext/libuv/src/unix/eio/eio.pod +969 -0
  135. data/ext/asyncengine_ext/libuv/src/unix/eio/libeio.m4 +195 -0
  136. data/ext/asyncengine_ext/libuv/src/unix/eio/xthread.h +164 -0
  137. data/ext/asyncengine_ext/libuv/src/unix/error.c +98 -0
  138. data/ext/asyncengine_ext/libuv/src/unix/ev/Changes +388 -0
  139. data/ext/asyncengine_ext/libuv/src/unix/ev/LICENSE +36 -0
  140. data/ext/asyncengine_ext/libuv/src/unix/ev/Makefile.am +18 -0
  141. data/ext/asyncengine_ext/libuv/src/unix/ev/Makefile.in +771 -0
  142. data/ext/asyncengine_ext/libuv/src/unix/ev/README +58 -0
  143. data/ext/asyncengine_ext/libuv/src/unix/ev/aclocal.m4 +8957 -0
  144. data/ext/asyncengine_ext/libuv/src/unix/ev/autogen.sh +6 -0
  145. data/ext/asyncengine_ext/libuv/src/unix/ev/config.guess +1526 -0
  146. data/ext/asyncengine_ext/libuv/src/unix/ev/config.h.in +125 -0
  147. data/ext/asyncengine_ext/libuv/src/unix/ev/config.sub +1658 -0
  148. data/ext/asyncengine_ext/libuv/src/unix/ev/config_cygwin.h +123 -0
  149. data/ext/asyncengine_ext/libuv/src/unix/ev/config_darwin.h +122 -0
  150. data/ext/asyncengine_ext/libuv/src/unix/ev/config_freebsd.h +120 -0
  151. data/ext/asyncengine_ext/libuv/src/unix/ev/config_linux.h +141 -0
  152. data/ext/asyncengine_ext/libuv/src/unix/ev/config_netbsd.h +120 -0
  153. data/ext/asyncengine_ext/libuv/src/unix/ev/config_openbsd.h +126 -0
  154. data/ext/asyncengine_ext/libuv/src/unix/ev/config_sunos.h +122 -0
  155. data/ext/asyncengine_ext/libuv/src/unix/ev/configure +13037 -0
  156. data/ext/asyncengine_ext/libuv/src/unix/ev/configure.ac +18 -0
  157. data/ext/asyncengine_ext/libuv/src/unix/ev/depcomp +630 -0
  158. data/ext/asyncengine_ext/libuv/src/unix/ev/ev++.h +816 -0
  159. data/ext/asyncengine_ext/libuv/src/unix/ev/ev.3 +5311 -0
  160. data/ext/asyncengine_ext/libuv/src/unix/ev/ev.c +3921 -0
  161. data/ext/asyncengine_ext/libuv/src/unix/ev/ev.pod +5243 -0
  162. data/ext/asyncengine_ext/libuv/src/unix/ev/ev_epoll.c +266 -0
  163. data/ext/asyncengine_ext/libuv/src/unix/ev/ev_kqueue.c +235 -0
  164. data/ext/asyncengine_ext/libuv/src/unix/ev/ev_poll.c +148 -0
  165. data/ext/asyncengine_ext/libuv/src/unix/ev/ev_port.c +179 -0
  166. data/ext/asyncengine_ext/libuv/src/unix/ev/ev_select.c +310 -0
  167. data/ext/asyncengine_ext/libuv/src/unix/ev/ev_vars.h +203 -0
  168. data/ext/asyncengine_ext/libuv/src/unix/ev/ev_win32.c +153 -0
  169. data/ext/asyncengine_ext/libuv/src/unix/ev/ev_wrap.h +196 -0
  170. data/ext/asyncengine_ext/libuv/src/unix/ev/event.c +402 -0
  171. data/ext/asyncengine_ext/libuv/src/unix/ev/event.h +170 -0
  172. data/ext/asyncengine_ext/libuv/src/unix/ev/install-sh +294 -0
  173. data/ext/asyncengine_ext/libuv/src/unix/ev/libev.m4 +39 -0
  174. data/ext/asyncengine_ext/libuv/src/unix/ev/ltmain.sh +8413 -0
  175. data/ext/asyncengine_ext/libuv/src/unix/ev/missing +336 -0
  176. data/ext/asyncengine_ext/libuv/src/unix/ev/mkinstalldirs +111 -0
  177. data/ext/asyncengine_ext/libuv/src/unix/freebsd.c +312 -0
  178. data/ext/asyncengine_ext/libuv/src/unix/fs.c +707 -0
  179. data/ext/asyncengine_ext/libuv/src/unix/idle.c +79 -0
  180. data/ext/asyncengine_ext/libuv/src/unix/internal.h +161 -0
  181. data/ext/asyncengine_ext/libuv/src/unix/kqueue.c +127 -0
  182. data/ext/asyncengine_ext/libuv/src/unix/linux/core.c +474 -0
  183. data/ext/asyncengine_ext/libuv/src/unix/linux/inotify.c +211 -0
  184. data/ext/asyncengine_ext/libuv/src/unix/linux/syscalls.c +230 -0
  185. data/ext/asyncengine_ext/libuv/src/unix/linux/syscalls.h +87 -0
  186. data/ext/asyncengine_ext/libuv/src/unix/loop.c +58 -0
  187. data/ext/asyncengine_ext/libuv/src/unix/netbsd.c +108 -0
  188. data/ext/asyncengine_ext/libuv/src/unix/openbsd.c +295 -0
  189. data/ext/asyncengine_ext/libuv/src/unix/pipe.c +266 -0
  190. data/ext/asyncengine_ext/libuv/src/unix/prepare.c +79 -0
  191. data/ext/asyncengine_ext/libuv/src/unix/process.c +369 -0
  192. data/ext/asyncengine_ext/libuv/src/unix/stream.c +1033 -0
  193. data/ext/asyncengine_ext/libuv/src/unix/sunos.c +466 -0
  194. data/ext/asyncengine_ext/libuv/src/unix/tcp.c +327 -0
  195. data/ext/asyncengine_ext/libuv/src/unix/thread.c +154 -0
  196. data/ext/asyncengine_ext/libuv/src/unix/timer.c +127 -0
  197. data/ext/asyncengine_ext/libuv/src/unix/tty.c +146 -0
  198. data/ext/asyncengine_ext/libuv/src/unix/udp.c +670 -0
  199. data/ext/asyncengine_ext/libuv/src/unix/uv-eio.c +124 -0
  200. data/ext/asyncengine_ext/libuv/src/unix/uv-eio.h +13 -0
  201. data/ext/asyncengine_ext/libuv/src/uv-common.c +354 -0
  202. data/ext/asyncengine_ext/libuv/src/uv-common.h +87 -0
  203. data/ext/asyncengine_ext/libuv/src/win/async.c +127 -0
  204. data/ext/asyncengine_ext/libuv/src/win/cares.c +290 -0
  205. data/ext/asyncengine_ext/libuv/src/win/core.c +270 -0
  206. data/ext/asyncengine_ext/libuv/src/win/dl.c +82 -0
  207. data/ext/asyncengine_ext/libuv/src/win/error.c +132 -0
  208. data/ext/asyncengine_ext/libuv/src/win/fs-event.c +514 -0
  209. data/ext/asyncengine_ext/libuv/src/win/fs.c +1576 -0
  210. data/ext/asyncengine_ext/libuv/src/win/getaddrinfo.c +372 -0
  211. data/ext/asyncengine_ext/libuv/src/win/handle.c +225 -0
  212. data/ext/asyncengine_ext/libuv/src/win/internal.h +352 -0
  213. data/ext/asyncengine_ext/libuv/src/win/loop-watcher.c +131 -0
  214. data/ext/asyncengine_ext/libuv/src/win/pipe.c +1661 -0
  215. data/ext/asyncengine_ext/libuv/src/win/process.c +1140 -0
  216. data/ext/asyncengine_ext/libuv/src/win/req.c +174 -0
  217. data/ext/asyncengine_ext/libuv/src/win/stream.c +201 -0
  218. data/ext/asyncengine_ext/libuv/src/win/tcp.c +1282 -0
  219. data/ext/asyncengine_ext/libuv/src/win/thread.c +332 -0
  220. data/ext/asyncengine_ext/libuv/src/win/threadpool.c +73 -0
  221. data/ext/asyncengine_ext/libuv/src/win/timer.c +276 -0
  222. data/ext/asyncengine_ext/libuv/src/win/tty.c +1795 -0
  223. data/ext/asyncengine_ext/libuv/src/win/udp.c +709 -0
  224. data/ext/asyncengine_ext/libuv/src/win/util.c +719 -0
  225. data/ext/asyncengine_ext/libuv/src/win/winapi.c +117 -0
  226. data/ext/asyncengine_ext/libuv/src/win/winapi.h +4419 -0
  227. data/ext/asyncengine_ext/libuv/src/win/winsock.c +470 -0
  228. data/ext/asyncengine_ext/libuv/src/win/winsock.h +138 -0
  229. data/ext/asyncengine_ext/libuv/test/benchmark-ares.c +118 -0
  230. data/ext/asyncengine_ext/libuv/test/benchmark-getaddrinfo.c +94 -0
  231. data/ext/asyncengine_ext/libuv/test/benchmark-list.h +105 -0
  232. data/ext/asyncengine_ext/libuv/test/benchmark-ping-pongs.c +213 -0
  233. data/ext/asyncengine_ext/libuv/test/benchmark-pound.c +324 -0
  234. data/ext/asyncengine_ext/libuv/test/benchmark-pump.c +462 -0
  235. data/ext/asyncengine_ext/libuv/test/benchmark-sizes.c +40 -0
  236. data/ext/asyncengine_ext/libuv/test/benchmark-spawn.c +156 -0
  237. data/ext/asyncengine_ext/libuv/test/benchmark-tcp-write-batch.c +140 -0
  238. data/ext/asyncengine_ext/libuv/test/benchmark-thread.c +64 -0
  239. data/ext/asyncengine_ext/libuv/test/benchmark-udp-packet-storm.c +247 -0
  240. data/ext/asyncengine_ext/libuv/test/blackhole-server.c +118 -0
  241. data/ext/asyncengine_ext/libuv/test/dns-server.c +321 -0
  242. data/ext/asyncengine_ext/libuv/test/echo-server.c +370 -0
  243. data/ext/asyncengine_ext/libuv/test/fixtures/empty_file +0 -0
  244. data/ext/asyncengine_ext/libuv/test/fixtures/load_error.node +1 -0
  245. data/ext/asyncengine_ext/libuv/test/run-benchmarks.c +64 -0
  246. data/ext/asyncengine_ext/libuv/test/run-tests.c +108 -0
  247. data/ext/asyncengine_ext/libuv/test/runner-unix.c +315 -0
  248. data/ext/asyncengine_ext/libuv/test/runner-unix.h +36 -0
  249. data/ext/asyncengine_ext/libuv/test/runner-win.c +343 -0
  250. data/ext/asyncengine_ext/libuv/test/runner-win.h +42 -0
  251. data/ext/asyncengine_ext/libuv/test/runner.c +317 -0
  252. data/ext/asyncengine_ext/libuv/test/runner.h +159 -0
  253. data/ext/asyncengine_ext/libuv/test/task.h +117 -0
  254. data/ext/asyncengine_ext/libuv/test/test-async.c +216 -0
  255. data/ext/asyncengine_ext/libuv/test/test-callback-stack.c +203 -0
  256. data/ext/asyncengine_ext/libuv/test/test-connection-fail.c +148 -0
  257. data/ext/asyncengine_ext/libuv/test/test-counters-init.c +216 -0
  258. data/ext/asyncengine_ext/libuv/test/test-cwd-and-chdir.c +64 -0
  259. data/ext/asyncengine_ext/libuv/test/test-delayed-accept.c +197 -0
  260. data/ext/asyncengine_ext/libuv/test/test-dlerror.c +49 -0
  261. data/ext/asyncengine_ext/libuv/test/test-eio-overflow.c +90 -0
  262. data/ext/asyncengine_ext/libuv/test/test-error.c +59 -0
  263. data/ext/asyncengine_ext/libuv/test/test-fail-always.c +29 -0
  264. data/ext/asyncengine_ext/libuv/test/test-fs-event.c +442 -0
  265. data/ext/asyncengine_ext/libuv/test/test-fs.c +1731 -0
  266. data/ext/asyncengine_ext/libuv/test/test-get-currentexe.c +63 -0
  267. data/ext/asyncengine_ext/libuv/test/test-get-loadavg.c +36 -0
  268. data/ext/asyncengine_ext/libuv/test/test-get-memory.c +38 -0
  269. data/ext/asyncengine_ext/libuv/test/test-getaddrinfo.c +122 -0
  270. data/ext/asyncengine_ext/libuv/test/test-gethostbyname.c +189 -0
  271. data/ext/asyncengine_ext/libuv/test/test-getsockname.c +342 -0
  272. data/ext/asyncengine_ext/libuv/test/test-hrtime.c +51 -0
  273. data/ext/asyncengine_ext/libuv/test/test-idle.c +81 -0
  274. data/ext/asyncengine_ext/libuv/test/test-ipc-send-recv.c +209 -0
  275. data/ext/asyncengine_ext/libuv/test/test-ipc.c +614 -0
  276. data/ext/asyncengine_ext/libuv/test/test-list.h +371 -0
  277. data/ext/asyncengine_ext/libuv/test/test-loop-handles.c +359 -0
  278. data/ext/asyncengine_ext/libuv/test/test-multiple-listen.c +102 -0
  279. data/ext/asyncengine_ext/libuv/test/test-mutexes.c +63 -0
  280. data/ext/asyncengine_ext/libuv/test/test-pass-always.c +28 -0
  281. data/ext/asyncengine_ext/libuv/test/test-ping-pong.c +253 -0
  282. data/ext/asyncengine_ext/libuv/test/test-pipe-bind-error.c +140 -0
  283. data/ext/asyncengine_ext/libuv/test/test-pipe-connect-error.c +96 -0
  284. data/ext/asyncengine_ext/libuv/test/test-platform-output.c +87 -0
  285. data/ext/asyncengine_ext/libuv/test/test-process-title.c +42 -0
  286. data/ext/asyncengine_ext/libuv/test/test-ref.c +322 -0
  287. data/ext/asyncengine_ext/libuv/test/test-run-once.c +44 -0
  288. data/ext/asyncengine_ext/libuv/test/test-shutdown-close.c +103 -0
  289. data/ext/asyncengine_ext/libuv/test/test-shutdown-eof.c +183 -0
  290. data/ext/asyncengine_ext/libuv/test/test-spawn.c +499 -0
  291. data/ext/asyncengine_ext/libuv/test/test-stdio-over-pipes.c +256 -0
  292. data/ext/asyncengine_ext/libuv/test/test-tcp-bind-error.c +191 -0
  293. data/ext/asyncengine_ext/libuv/test/test-tcp-bind6-error.c +154 -0
  294. data/ext/asyncengine_ext/libuv/test/test-tcp-close.c +129 -0
  295. data/ext/asyncengine_ext/libuv/test/test-tcp-connect-error.c +70 -0
  296. data/ext/asyncengine_ext/libuv/test/test-tcp-connect6-error.c +68 -0
  297. data/ext/asyncengine_ext/libuv/test/test-tcp-flags.c +51 -0
  298. data/ext/asyncengine_ext/libuv/test/test-tcp-write-error.c +168 -0
  299. data/ext/asyncengine_ext/libuv/test/test-tcp-write-to-half-open-connection.c +135 -0
  300. data/ext/asyncengine_ext/libuv/test/test-tcp-writealot.c +195 -0
  301. data/ext/asyncengine_ext/libuv/test/test-thread.c +183 -0
  302. data/ext/asyncengine_ext/libuv/test/test-threadpool.c +57 -0
  303. data/ext/asyncengine_ext/libuv/test/test-timer-again.c +141 -0
  304. data/ext/asyncengine_ext/libuv/test/test-timer.c +130 -0
  305. data/ext/asyncengine_ext/libuv/test/test-tty.c +110 -0
  306. data/ext/asyncengine_ext/libuv/test/test-udp-dgram-too-big.c +86 -0
  307. data/ext/asyncengine_ext/libuv/test/test-udp-ipv6.c +156 -0
  308. data/ext/asyncengine_ext/libuv/test/test-udp-multicast-join.c +139 -0
  309. data/ext/asyncengine_ext/libuv/test/test-udp-multicast-ttl.c +86 -0
  310. data/ext/asyncengine_ext/libuv/test/test-udp-options.c +86 -0
  311. data/ext/asyncengine_ext/libuv/test/test-udp-send-and-recv.c +208 -0
  312. data/ext/asyncengine_ext/libuv/test/test-util.c +97 -0
  313. data/ext/asyncengine_ext/libuv/uv.gyp +435 -0
  314. data/ext/asyncengine_ext/libuv/vcbuild.bat +105 -0
  315. data/lib/asyncengine/version.rb +3 -0
  316. data/lib/asyncengine.rb +41 -0
  317. metadata +384 -0
@@ -0,0 +1,1140 @@
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 "../uv-common.h"
24
+ #include "internal.h"
25
+
26
+ #include <stdio.h>
27
+ #include <assert.h>
28
+ #include <stdlib.h>
29
+ #include <signal.h>
30
+ #include <windows.h>
31
+
32
+ #define SIGKILL 9
33
+
34
+ typedef struct env_var {
35
+ const char* narrow;
36
+ const wchar_t* wide;
37
+ int len; /* including null or '=' */
38
+ int supplied;
39
+ int value_len;
40
+ } env_var_t;
41
+
42
+ #define E_V(str) { str "=", L##str, sizeof(str), 0, 0 }
43
+
44
+ #define UTF8_TO_UTF16(s, t) \
45
+ size = uv_utf8_to_utf16(s, NULL, 0) * sizeof(wchar_t); \
46
+ t = (wchar_t*)malloc(size); \
47
+ if (!t) { \
48
+ uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); \
49
+ } \
50
+ if (!uv_utf8_to_utf16(s, t, size / sizeof(wchar_t))) { \
51
+ uv__set_sys_error(loop, GetLastError()); \
52
+ err = -1; \
53
+ goto done; \
54
+ }
55
+
56
+
57
+ 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;
61
+ handle->exit_cb = NULL;
62
+ handle->pid = 0;
63
+ handle->exit_signal = 0;
64
+ handle->wait_handle = INVALID_HANDLE_VALUE;
65
+ handle->process_handle = INVALID_HANDLE_VALUE;
66
+ 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;
70
+
71
+ uv_req_init(loop, (uv_req_t*)&handle->exit_req);
72
+ handle->exit_req.type = UV_PROCESS_EXIT;
73
+ handle->exit_req.data = handle;
74
+ uv_req_init(loop, (uv_req_t*)&handle->close_req);
75
+ handle->close_req.type = UV_PROCESS_CLOSE;
76
+ handle->close_req.data = handle;
77
+
78
+ loop->counters.handle_init++;
79
+ loop->counters.process_init++;
80
+
81
+ uv_ref(loop);
82
+ }
83
+
84
+
85
+ /*
86
+ * Path search functions
87
+ */
88
+
89
+ /*
90
+ * Helper function for search_path
91
+ */
92
+ static wchar_t* search_path_join_test(const wchar_t* dir,
93
+ int dir_len,
94
+ const wchar_t* name,
95
+ int name_len,
96
+ const wchar_t* ext,
97
+ int ext_len,
98
+ const wchar_t* cwd,
99
+ int cwd_len) {
100
+ wchar_t *result, *result_pos;
101
+ DWORD attrs;
102
+
103
+ if (dir_len >= 1 && (dir[0] == L'/' || dir[0] == L'\\')) {
104
+ /* It's a full path without drive letter, use cwd's drive letter only */
105
+ cwd_len = 2;
106
+ } else if (dir_len >= 2 && dir[1] == L':' &&
107
+ (dir_len < 3 || (dir[2] != L'/' && dir[2] != L'\\'))) {
108
+ /* It's a relative path with drive letter (ext.g. D:../some/file)
109
+ * Replace drive letter in dir by full cwd if it points to the same drive,
110
+ * otherwise use the dir only.
111
+ */
112
+ if (cwd_len < 2 || _wcsnicmp(cwd, dir, 2) != 0) {
113
+ cwd_len = 0;
114
+ } else {
115
+ dir += 2;
116
+ dir_len -= 2;
117
+ }
118
+ } else if (dir_len > 2 && dir[1] == L':') {
119
+ /* It's an absolute path with drive letter
120
+ * Don't use the cwd at all
121
+ */
122
+ cwd_len = 0;
123
+ }
124
+
125
+ /* Allocate buffer for output */
126
+ result = result_pos = (wchar_t*)malloc(sizeof(wchar_t) *
127
+ (cwd_len + 1 + dir_len + 1 + name_len + 1 + ext_len + 1));
128
+
129
+ /* Copy cwd */
130
+ wcsncpy(result_pos, cwd, cwd_len);
131
+ result_pos += cwd_len;
132
+
133
+ /* Add a path separator if cwd didn't end with one */
134
+ if (cwd_len && wcsrchr(L"\\/:", result_pos[-1]) == NULL) {
135
+ result_pos[0] = L'\\';
136
+ result_pos++;
137
+ }
138
+
139
+ /* Copy dir */
140
+ wcsncpy(result_pos, dir, dir_len);
141
+ result_pos += dir_len;
142
+
143
+ /* Add a separator if the dir didn't end with one */
144
+ if (dir_len && wcsrchr(L"\\/:", result_pos[-1]) == NULL) {
145
+ result_pos[0] = L'\\';
146
+ result_pos++;
147
+ }
148
+
149
+ /* Copy filename */
150
+ wcsncpy(result_pos, name, name_len);
151
+ result_pos += name_len;
152
+
153
+ if (ext_len) {
154
+ /* Add a dot if the filename didn't end with one */
155
+ if (name_len && result_pos[-1] != '.') {
156
+ result_pos[0] = L'.';
157
+ result_pos++;
158
+ }
159
+
160
+ /* Copy extension */
161
+ wcsncpy(result_pos, ext, ext_len);
162
+ result_pos += ext_len;
163
+ }
164
+
165
+ /* Null terminator */
166
+ result_pos[0] = L'\0';
167
+
168
+ attrs = GetFileAttributesW(result);
169
+
170
+ if (attrs != INVALID_FILE_ATTRIBUTES &&
171
+ !(attrs & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT))) {
172
+ return result;
173
+ }
174
+
175
+ free(result);
176
+ return NULL;
177
+ }
178
+
179
+
180
+ /*
181
+ * Helper function for search_path
182
+ */
183
+ static wchar_t* path_search_walk_ext(const wchar_t *dir,
184
+ int dir_len,
185
+ const wchar_t *name,
186
+ int name_len,
187
+ wchar_t *cwd,
188
+ int cwd_len,
189
+ int name_has_ext) {
190
+ wchar_t* result;
191
+
192
+ /* If the name itself has a nonempty extension, try this extension first */
193
+ if (name_has_ext) {
194
+ result = search_path_join_test(dir, dir_len,
195
+ name, name_len,
196
+ L"", 0,
197
+ cwd, cwd_len);
198
+ if (result != NULL) {
199
+ return result;
200
+ }
201
+ }
202
+
203
+ /* Try .com extension */
204
+ result = search_path_join_test(dir, dir_len,
205
+ name, name_len,
206
+ L"com", 3,
207
+ cwd, cwd_len);
208
+ if (result != NULL) {
209
+ return result;
210
+ }
211
+
212
+ /* Try .exe extension */
213
+ result = search_path_join_test(dir, dir_len,
214
+ name, name_len,
215
+ L"exe", 3,
216
+ cwd, cwd_len);
217
+ if (result != NULL) {
218
+ return result;
219
+ }
220
+
221
+ return NULL;
222
+ }
223
+
224
+
225
+ /*
226
+ * search_path searches the system path for an executable filename -
227
+ * the windows API doesn't provide this as a standalone function nor as an
228
+ * option to CreateProcess.
229
+ *
230
+ * It tries to return an absolute filename.
231
+ *
232
+ * Furthermore, it tries to follow the semantics that cmd.exe, with this
233
+ * exception that PATHEXT environment variable isn't used. Since CreateProcess
234
+ * can start only .com and .exe files, only those extensions are tried. This
235
+ * behavior equals that of msvcrt's spawn functions.
236
+ *
237
+ * - Do not search the path if the filename already contains a path (either
238
+ * relative or absolute).
239
+ *
240
+ * - If there's really only a filename, check the current directory for file,
241
+ * then search all path directories.
242
+ *
243
+ * - If filename specified has *any* extension, search for the file with the
244
+ * specified extension first.
245
+ *
246
+ * - If the literal filename is not found in a directory, try *appending*
247
+ * (not replacing) .com first and then .exe.
248
+ *
249
+ * - The path variable may contain relative paths; relative paths are relative
250
+ * to the cwd.
251
+ *
252
+ * - Directories in path may or may not end with a trailing backslash.
253
+ *
254
+ * - CMD does not trim leading/trailing whitespace from path/pathex entries
255
+ * nor from the environment variables as a whole.
256
+ *
257
+ * - When cmd.exe cannot read a directory, it will just skip it and go on
258
+ * searching. However, unlike posix-y systems, it will happily try to run a
259
+ * file that is not readable/executable; if the spawn fails it will not
260
+ * continue searching.
261
+ *
262
+ * TODO: correctly interpret UNC paths
263
+ */
264
+ static wchar_t* search_path(const wchar_t *file,
265
+ wchar_t *cwd,
266
+ const wchar_t *path) {
267
+ int file_has_dir;
268
+ wchar_t* result = NULL;
269
+ wchar_t *file_name_start;
270
+ wchar_t *dot;
271
+ const wchar_t *dir_start, *dir_end, *dir_path;
272
+ int dir_len;
273
+ int name_has_ext;
274
+
275
+ int file_len = wcslen(file);
276
+ int cwd_len = wcslen(cwd);
277
+
278
+ /* If the caller supplies an empty filename,
279
+ * we're not gonna return c:\windows\.exe -- GFY!
280
+ */
281
+ if (file_len == 0
282
+ || (file_len == 1 && file[0] == L'.')) {
283
+ return NULL;
284
+ }
285
+
286
+ /* Find the start of the filename so we can split the directory from the */
287
+ /* name. */
288
+ for (file_name_start = (wchar_t*)file + file_len;
289
+ file_name_start > file
290
+ && file_name_start[-1] != L'\\'
291
+ && file_name_start[-1] != L'/'
292
+ && file_name_start[-1] != L':';
293
+ file_name_start--);
294
+
295
+ file_has_dir = file_name_start != file;
296
+
297
+ /* Check if the filename includes an extension */
298
+ dot = wcschr(file_name_start, L'.');
299
+ name_has_ext = (dot != NULL && dot[1] != L'\0');
300
+
301
+ if (file_has_dir) {
302
+ /* The file has a path inside, don't use path */
303
+ result = path_search_walk_ext(
304
+ file, file_name_start - file,
305
+ file_name_start, file_len - (file_name_start - file),
306
+ cwd, cwd_len,
307
+ name_has_ext);
308
+
309
+ } else {
310
+ dir_end = path;
311
+
312
+ /* The file is really only a name; look in cwd first, then scan path */
313
+ result = path_search_walk_ext(L"", 0,
314
+ file, file_len,
315
+ cwd, cwd_len,
316
+ name_has_ext);
317
+
318
+ while (result == NULL) {
319
+ if (*dir_end == L'\0') {
320
+ break;
321
+ }
322
+
323
+ /* Skip the separator that dir_end now points to */
324
+ if (dir_end != path) {
325
+ dir_end++;
326
+ }
327
+
328
+ /* Next slice starts just after where the previous one ended */
329
+ dir_start = dir_end;
330
+
331
+ /* Slice until the next ; or \0 is found */
332
+ dir_end = wcschr(dir_start, L';');
333
+ if (dir_end == NULL) {
334
+ dir_end = wcschr(dir_start, L'\0');
335
+ }
336
+
337
+ /* If the slice is zero-length, don't bother */
338
+ if (dir_end - dir_start == 0) {
339
+ continue;
340
+ }
341
+
342
+ dir_path = dir_start;
343
+ dir_len = dir_end - dir_start;
344
+
345
+ /* Adjust if the path is quoted. */
346
+ if (dir_path[0] == '"' || dir_path[0] == '\'') {
347
+ ++dir_path;
348
+ --dir_len;
349
+ }
350
+
351
+ if (dir_path[dir_len - 1] == '"' || dir_path[dir_len - 1] == '\'') {
352
+ --dir_len;
353
+ }
354
+
355
+ result = path_search_walk_ext(dir_path, dir_len,
356
+ file, file_len,
357
+ cwd, cwd_len,
358
+ name_has_ext);
359
+ }
360
+ }
361
+
362
+ return result;
363
+ }
364
+
365
+
366
+ /*
367
+ * Quotes command line arguments
368
+ * Returns a pointer to the end (next char to be written) of the buffer
369
+ */
370
+ wchar_t* quote_cmd_arg(const wchar_t *source, wchar_t *target) {
371
+ int len = wcslen(source),
372
+ i, quote_hit;
373
+ wchar_t* start;
374
+
375
+ /*
376
+ * Check if the string must be quoted;
377
+ * if unnecessary, don't do it, it may only confuse older programs.
378
+ */
379
+ if (len == 0) {
380
+ return target;
381
+ }
382
+
383
+ if (NULL == wcspbrk(source, L" \t\"")) {
384
+ /* No quotation needed */
385
+ wcsncpy(target, source, len);
386
+ target += len;
387
+ return target;
388
+ }
389
+
390
+ if (NULL == wcspbrk(source, L"\"\\")) {
391
+ /*
392
+ * No embedded double quotes or backlashes, so I can just wrap
393
+ * quote marks around the whole thing.
394
+ */
395
+ *(target++) = L'"';
396
+ wcsncpy(target, source, len);
397
+ target += len;
398
+ *(target++) = L'"';
399
+ return target;
400
+ }
401
+
402
+ /*
403
+ * Expected input/output:
404
+ * input : hello"world
405
+ * output: "hello\"world"
406
+ * input : hello""world
407
+ * output: "hello\"\"world"
408
+ * input : hello\world
409
+ * output: hello\world
410
+ * input : hello\\world
411
+ * output: hello\\world
412
+ * input : hello\"world
413
+ * output: "hello\\\"world"
414
+ * input : hello\\"world
415
+ * output: "hello\\\\\"world"
416
+ * input : hello world\
417
+ * output: "hello world\"
418
+ */
419
+
420
+ *(target++) = L'"';
421
+ start = target;
422
+ quote_hit = 1;
423
+
424
+ for (i = len; i > 0; --i) {
425
+ *(target++) = source[i - 1];
426
+
427
+ if (quote_hit && source[i - 1] == L'\\') {
428
+ *(target++) = L'\\';
429
+ } else if(source[i - 1] == L'"') {
430
+ quote_hit = 1;
431
+ *(target++) = L'\\';
432
+ } else {
433
+ quote_hit = 0;
434
+ }
435
+ }
436
+ target[0] = L'\0';
437
+ wcsrev(start);
438
+ *(target++) = L'"';
439
+ return target;
440
+ }
441
+
442
+
443
+ wchar_t* make_program_args(char** args, int verbatim_arguments) {
444
+ wchar_t* dst;
445
+ wchar_t* ptr;
446
+ char** arg;
447
+ size_t size = 0;
448
+ size_t len;
449
+ int arg_count = 0;
450
+ wchar_t* buffer;
451
+ int arg_size;
452
+ int buffer_size = 0;
453
+
454
+ /* Count the required size. */
455
+ for (arg = args; *arg; arg++) {
456
+ arg_size = uv_utf8_to_utf16(*arg, NULL, 0) * sizeof(wchar_t);
457
+ size += arg_size;
458
+ buffer_size = arg_size > buffer_size ? arg_size : buffer_size;
459
+ arg_count++;
460
+ }
461
+
462
+ /* Adjust for potential quotes. Also assume the worst-case scenario
463
+ /* that every character needs escaping, so we need twice as much space. */
464
+ size = size * 2 + arg_count * 2;
465
+
466
+ dst = (wchar_t*)malloc(size);
467
+ if (!dst) {
468
+ uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
469
+ }
470
+
471
+ buffer = (wchar_t*)malloc(buffer_size);
472
+ if (!buffer) {
473
+ uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
474
+ }
475
+
476
+ ptr = dst;
477
+ for (arg = args; *arg; arg++) {
478
+ len = uv_utf8_to_utf16(*arg, buffer, (size_t)(size - (ptr - dst)));
479
+ if (!len) {
480
+ goto error;
481
+ }
482
+ if (verbatim_arguments) {
483
+ wcscpy(ptr, buffer);
484
+ ptr += len - 1;
485
+ } else {
486
+ ptr = quote_cmd_arg(buffer, ptr);
487
+ }
488
+ *ptr++ = *(arg + 1) ? L' ' : L'\0';
489
+ }
490
+
491
+ free(buffer);
492
+ return dst;
493
+
494
+ error:
495
+ free(dst);
496
+ free(buffer);
497
+ return NULL;
498
+ }
499
+
500
+
501
+ /*
502
+ * If we learn that people are passing in huge environment blocks
503
+ * then we should probably qsort() the array and then bsearch()
504
+ * to see if it contains this variable. But there are ownership
505
+ * issues associated with that solution; this is the caller's
506
+ * char**, and modifying it is rude.
507
+ */
508
+ static void check_required_vars_contains_var(env_var_t* required, int size,
509
+ const char* var) {
510
+ int i;
511
+ for (i = 0; i < size; ++i) {
512
+ if (_strnicmp(required[i].narrow, var, required[i].len) == 0) {
513
+ required[i].supplied = 1;
514
+ return;
515
+ }
516
+ }
517
+ }
518
+
519
+
520
+ /*
521
+ * The way windows takes environment variables is different than what C does;
522
+ * Windows wants a contiguous block of null-terminated strings, terminated
523
+ * with an additional null.
524
+ *
525
+ * Windows has a few "essential" environment variables. winsock will fail
526
+ * to initialize if SYSTEMROOT is not defined; some APIs make reference to
527
+ * TEMP. SYSTEMDRIVE is probably also important. We therefore ensure that
528
+ * these get defined if the input environment block does not contain any
529
+ * values for them.
530
+ */
531
+ wchar_t* make_program_env(char** env_block) {
532
+ wchar_t* dst;
533
+ wchar_t* ptr;
534
+ char** env;
535
+ int env_len = 1 * sizeof(wchar_t); /* room for closing null */
536
+ int len;
537
+ int i;
538
+ DWORD var_size;
539
+
540
+ env_var_t required_vars[] = {
541
+ E_V("SYSTEMROOT"),
542
+ E_V("SYSTEMDRIVE"),
543
+ E_V("TEMP"),
544
+ };
545
+
546
+ for (env = env_block; *env; env++) {
547
+ check_required_vars_contains_var(required_vars,
548
+ ARRAY_SIZE(required_vars),
549
+ *env);
550
+ env_len += (uv_utf8_to_utf16(*env, NULL, 0) * sizeof(wchar_t));
551
+ }
552
+
553
+ for (i = 0; i < ARRAY_SIZE(required_vars); ++i) {
554
+ if (!required_vars[i].supplied) {
555
+ env_len += required_vars[i].len * sizeof(wchar_t);
556
+ var_size = GetEnvironmentVariableW(required_vars[i].wide, NULL, 0);
557
+ if (var_size == 0) {
558
+ uv_fatal_error(GetLastError(), "GetEnvironmentVariableW");
559
+ }
560
+ required_vars[i].value_len = (int)var_size;
561
+ env_len += (int)var_size * sizeof(wchar_t);
562
+ }
563
+ }
564
+
565
+ dst = malloc(env_len);
566
+ if (!dst) {
567
+ uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
568
+ }
569
+
570
+ ptr = dst;
571
+
572
+ for (env = env_block; *env; env++, ptr += len) {
573
+ len = uv_utf8_to_utf16(*env, ptr, (size_t)(env_len - (ptr - dst)));
574
+ if (!len) {
575
+ free(dst);
576
+ return NULL;
577
+ }
578
+ }
579
+
580
+ for (i = 0; i < ARRAY_SIZE(required_vars); ++i) {
581
+ if (!required_vars[i].supplied) {
582
+ wcscpy(ptr, required_vars[i].wide);
583
+ ptr += required_vars[i].len - 1;
584
+ *ptr++ = L'=';
585
+ var_size = GetEnvironmentVariableW(required_vars[i].wide,
586
+ ptr,
587
+ required_vars[i].value_len);
588
+ if (var_size == 0) {
589
+ uv_fatal_error(GetLastError(), "GetEnvironmentVariableW");
590
+ }
591
+ ptr += required_vars[i].value_len;
592
+ }
593
+ }
594
+
595
+ *ptr = L'\0';
596
+ return dst;
597
+ }
598
+
599
+
600
+ /*
601
+ * Called on Windows thread-pool thread to indicate that
602
+ * a child process has exited.
603
+ */
604
+ static void CALLBACK exit_wait_callback(void* data, BOOLEAN didTimeout) {
605
+ uv_process_t* process = (uv_process_t*)data;
606
+ uv_loop_t* loop = process->loop;
607
+
608
+ assert(didTimeout == FALSE);
609
+ assert(process);
610
+
611
+ /* Post completed */
612
+ POST_COMPLETION_FOR_REQ(loop, &process->exit_req);
613
+ }
614
+
615
+
616
+ /*
617
+ * Called on Windows thread-pool thread to indicate that
618
+ * UnregisterWaitEx has completed.
619
+ */
620
+ static void CALLBACK close_wait_callback(void* data, BOOLEAN didTimeout) {
621
+ uv_process_t* process = (uv_process_t*)data;
622
+ uv_loop_t* loop = process->loop;
623
+
624
+ assert(didTimeout == FALSE);
625
+ assert(process);
626
+
627
+ /* Post completed */
628
+ POST_COMPLETION_FOR_REQ(loop, &process->close_req);
629
+ }
630
+
631
+
632
+ /*
633
+ * Called on windows thread pool when CreateProcess failed. It writes an error
634
+ * message to the process' intended stderr and then posts a PROCESS_EXIT
635
+ * packet to the completion port.
636
+ */
637
+ static DWORD WINAPI spawn_failure(void* data) {
638
+ char syscall[] = "CreateProcessW: ";
639
+ char unknown[] = "unknown error\n";
640
+ uv_process_t* process = (uv_process_t*) data;
641
+ uv_loop_t* loop = process->loop;
642
+ HANDLE child_stderr = process->child_stdio[2];
643
+ char* buf = NULL;
644
+ DWORD count, written;
645
+
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
+ }
664
+
665
+ FlushFileBuffers(child_stderr);
666
+
667
+ /* Post completed */
668
+ POST_COMPLETION_FOR_REQ(loop, &process->exit_req);
669
+
670
+ return 0;
671
+ }
672
+
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
+ /* Called on main thread after a child process has exited. */
689
+ void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) {
690
+ DWORD exit_code;
691
+
692
+ /* Unregister from process notification. */
693
+ if (handle->wait_handle != INVALID_HANDLE_VALUE) {
694
+ UnregisterWait(handle->wait_handle);
695
+ handle->wait_handle = INVALID_HANDLE_VALUE;
696
+ }
697
+
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. */
713
+ exit_code = 127;
714
+ }
715
+
716
+ /* Fire the exit callback. */
717
+ if (handle->exit_cb) {
718
+ handle->exit_cb(handle, exit_code, handle->exit_signal);
719
+ }
720
+ }
721
+
722
+
723
+ /* Called on main thread after UnregisterWaitEx finishes. */
724
+ void uv_process_proc_close(uv_loop_t* loop, uv_process_t* handle) {
725
+ uv_want_endgame(loop, (uv_handle_t*)handle);
726
+ }
727
+
728
+
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
+ void uv_process_close(uv_loop_t* loop, uv_process_t* handle) {
744
+ if (handle->wait_handle != INVALID_HANDLE_VALUE) {
745
+ handle->close_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
746
+ UnregisterWaitEx(handle->wait_handle, handle->close_handle);
747
+ handle->wait_handle = NULL;
748
+
749
+ RegisterWaitForSingleObject(&handle->wait_handle, handle->close_handle,
750
+ close_wait_callback, (void*)handle, INFINITE,
751
+ WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE);
752
+ } else {
753
+ uv_want_endgame(loop, (uv_handle_t*)handle);
754
+ }
755
+ }
756
+
757
+
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;
815
+
816
+ done:
817
+ if (err) {
818
+ if (server_pipe->handle != INVALID_HANDLE_VALUE) {
819
+ close_pipe(server_pipe, NULL, NULL);
820
+ }
821
+
822
+ if (*child_pipe != INVALID_HANDLE_VALUE) {
823
+ CloseHandle(*child_pipe);
824
+ *child_pipe = INVALID_HANDLE_VALUE;
825
+ }
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
+
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;
857
+ }
858
+
859
+ return 0;
860
+ }
861
+
862
+
863
+ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
864
+ uv_process_options_t options) {
865
+ int err = 0, keep_child_stdio_open = 0;
866
+ wchar_t* path = NULL;
867
+ int size;
868
+ BOOL result;
869
+ wchar_t* application_path = NULL, *application = NULL, *arguments = NULL,
870
+ *env = NULL, *cwd = NULL;
871
+ HANDLE* child_stdio = process->child_stdio;
872
+ STARTUPINFOW startup;
873
+ PROCESS_INFORMATION info;
874
+
875
+ if (!options.file) {
876
+ uv__set_artificial_error(loop, UV_EINVAL);
877
+ return -1;
878
+ }
879
+
880
+ uv_process_init(loop, process);
881
+
882
+ process->exit_cb = options.exit_cb;
883
+ UTF8_TO_UTF16(options.file, application);
884
+ arguments = options.args ? make_program_args(options.args,
885
+ options.windows_verbatim_arguments) : NULL;
886
+ env = options.env ? make_program_env(options.env) : NULL;
887
+
888
+ if (options.cwd) {
889
+ UTF8_TO_UTF16(options.cwd, cwd);
890
+ } else {
891
+ size = GetCurrentDirectoryW(0, NULL) * sizeof(wchar_t);
892
+ if (size) {
893
+ cwd = (wchar_t*)malloc(size);
894
+ if (!cwd) {
895
+ uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
896
+ }
897
+ GetCurrentDirectoryW(size, cwd);
898
+ } else {
899
+ uv__set_sys_error(loop, GetLastError());
900
+ err = -1;
901
+ goto done;
902
+ }
903
+ }
904
+
905
+ /* Get PATH env. variable. */
906
+ size = GetEnvironmentVariableW(L"PATH", NULL, 0) + 1;
907
+ path = (wchar_t*)malloc(size * sizeof(wchar_t));
908
+ if (!path) {
909
+ uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
910
+ }
911
+ GetEnvironmentVariableW(L"PATH", path, size * sizeof(wchar_t));
912
+ path[size - 1] = L'\0';
913
+
914
+ application_path = search_path(application,
915
+ cwd,
916
+ path);
917
+
918
+ if (!application_path) {
919
+ /* CreateProcess will fail, but this allows us to pass this error to */
920
+ /* the user asynchronously. */
921
+ application_path = application;
922
+ }
923
+
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
+
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;
977
+ }
978
+
979
+ startup.cb = sizeof(startup);
980
+ startup.lpReserved = NULL;
981
+ startup.lpDesktop = NULL;
982
+ startup.lpTitle = NULL;
983
+ 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];
989
+
990
+ if (CreateProcessW(application_path,
991
+ arguments,
992
+ NULL,
993
+ NULL,
994
+ 1,
995
+ CREATE_UNICODE_ENVIRONMENT,
996
+ env,
997
+ cwd,
998
+ &startup,
999
+ &info)) {
1000
+ /* Spawn succeeded */
1001
+ process->process_handle = info.hProcess;
1002
+ process->pid = info.dwProcessId;
1003
+
1004
+ if (options.stdin_stream &&
1005
+ options.stdin_stream->ipc) {
1006
+ options.stdin_stream->ipc_pid = info.dwProcessId;
1007
+ }
1008
+
1009
+ /* Setup notifications for when the child process exits. */
1010
+ result = RegisterWaitForSingleObject(&process->wait_handle,
1011
+ process->process_handle, exit_wait_callback, (void*)process, INFINITE,
1012
+ WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE);
1013
+ if (!result) {
1014
+ uv_fatal_error(GetLastError(), "RegisterWaitForSingleObject");
1015
+ }
1016
+
1017
+ CloseHandle(info.hThread);
1018
+
1019
+ } else {
1020
+ /* CreateProcessW failed, but this failure should be delivered */
1021
+ /* asynchronously to retain unix compatibility. So pretend spawn */
1022
+ /* succeeded, and start a thread instead that prints an error */
1023
+ /* to the child's intended stderr. */
1024
+ process->spawn_errno = GetLastError();
1025
+ keep_child_stdio_open = 1;
1026
+ if (!QueueUserWorkItem(spawn_failure, process, WT_EXECUTEDEFAULT)) {
1027
+ uv_fatal_error(GetLastError(), "QueueUserWorkItem");
1028
+ }
1029
+ }
1030
+
1031
+ done:
1032
+ free(application);
1033
+ if (application_path != application) {
1034
+ free(application_path);
1035
+ }
1036
+ free(arguments);
1037
+ free(cwd);
1038
+ free(env);
1039
+ free(path);
1040
+
1041
+ /* Under normal circumstances we should close the stdio handles now - */
1042
+ /* the child now has its own duplicates, or something went horribly wrong. */
1043
+ /* The only exception is when CreateProcess has failed, then we actually */
1044
+ /* need to keep the stdio handles to report the error asynchronously. */
1045
+ if (!keep_child_stdio_open) {
1046
+ close_child_stdio(process);
1047
+ } else {
1048
+ /* We're keeping the handles open, the thread pool is going to have */
1049
+ /* 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
+ }
1054
+ }
1055
+
1056
+ if (err) {
1057
+ if (process->wait_handle != INVALID_HANDLE_VALUE) {
1058
+ UnregisterWait(process->wait_handle);
1059
+ process->wait_handle = INVALID_HANDLE_VALUE;
1060
+ }
1061
+
1062
+ if (process->process_handle != INVALID_HANDLE_VALUE) {
1063
+ CloseHandle(process->process_handle);
1064
+ process->process_handle = INVALID_HANDLE_VALUE;
1065
+ }
1066
+ }
1067
+
1068
+ return err;
1069
+ }
1070
+
1071
+
1072
+ static uv_err_t uv__kill(HANDLE process_handle, int signum) {
1073
+ DWORD status;
1074
+ uv_err_t err;
1075
+
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());
1082
+ }
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());
1093
+ }
1094
+ } else {
1095
+ err = uv__new_artificial_error(UV_ENOSYS);
1096
+ }
1097
+
1098
+ return err;
1099
+ }
1100
+
1101
+
1102
+ int uv_process_kill(uv_process_t* process, int signum) {
1103
+ uv_err_t err;
1104
+
1105
+ if (process->process_handle == INVALID_HANDLE_VALUE) {
1106
+ uv__set_artificial_error(process->loop, UV_EINVAL);
1107
+ return -1;
1108
+ }
1109
+
1110
+ err = uv__kill(process->process_handle, signum);
1111
+
1112
+ if (err.code != UV_OK) {
1113
+ uv__set_error(process->loop, err.code, err.sys_errno_);
1114
+ return -1;
1115
+ }
1116
+
1117
+ process->exit_signal = signum;
1118
+
1119
+ return 0;
1120
+ }
1121
+
1122
+
1123
+ uv_err_t uv_kill(int pid, int signum) {
1124
+ uv_err_t err;
1125
+ HANDLE process_handle = OpenProcess(PROCESS_TERMINATE |
1126
+ PROCESS_QUERY_INFORMATION, FALSE, pid);
1127
+
1128
+ if (process_handle == NULL) {
1129
+ if (GetLastError() == ERROR_INVALID_PARAMETER) {
1130
+ return uv__new_artificial_error(UV_ESRCH);
1131
+ } else {
1132
+ return uv__new_sys_error(GetLastError());
1133
+ }
1134
+ }
1135
+
1136
+ err = uv__kill(process_handle, signum);
1137
+ CloseHandle(process_handle);
1138
+
1139
+ return err;
1140
+ }