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
@@ -22,34 +22,9 @@
22
22
  #include <assert.h>
23
23
 
24
24
  #include "uv.h"
25
- #include "../uv-common.h"
26
25
  #include "internal.h"
27
-
28
-
29
- void uv_stream_init(uv_loop_t* loop, uv_stream_t* handle) {
30
- handle->write_queue_size = 0;
31
- handle->loop = loop;
32
- handle->flags = 0;
33
-
34
- loop->counters.handle_init++;
35
- loop->counters.stream_init++;
36
-
37
- uv_ref(loop);
38
- }
39
-
40
-
41
- void uv_connection_init(uv_stream_t* handle) {
42
- handle->flags |= UV_HANDLE_CONNECTION;
43
- handle->write_reqs_pending = 0;
44
-
45
- uv_req_init(handle->loop, (uv_req_t*) &(handle->read_req));
46
- handle->read_req.event_handle = NULL;
47
- handle->read_req.wait_handle = INVALID_HANDLE_VALUE;
48
- handle->read_req.type = UV_READ;
49
- handle->read_req.data = handle;
50
-
51
- handle->shutdown_req = NULL;
52
- }
26
+ #include "handle-inl.h"
27
+ #include "req-inl.h"
53
28
 
54
29
 
55
30
  int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) {
@@ -109,8 +84,11 @@ int uv_read2_start(uv_stream_t* handle, uv_alloc_cb alloc_cb,
109
84
  int uv_read_stop(uv_stream_t* handle) {
110
85
  if (handle->type == UV_TTY) {
111
86
  return uv_tty_read_stop((uv_tty_t*) handle);
112
- } else {
87
+ } else if (handle->flags & UV_HANDLE_READING) {
113
88
  handle->flags &= ~UV_HANDLE_READING;
89
+ DECREASE_ACTIVE_COUNT(handle->loop, handle);
90
+ return 0;
91
+ } else {
114
92
  return 0;
115
93
  }
116
94
  }
@@ -171,7 +149,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) {
171
149
  handle->flags |= UV_HANDLE_SHUTTING;
172
150
  handle->shutdown_req = req;
173
151
  handle->reqs_pending++;
174
- uv_ref(loop);
152
+ REGISTER_HANDLE_REQ(loop, handle, req);
175
153
 
176
154
  uv_want_endgame(loop, (uv_handle_t*)handle);
177
155
 
@@ -179,23 +157,11 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) {
179
157
  }
180
158
 
181
159
 
182
- size_t uv_count_bufs(uv_buf_t bufs[], int count) {
183
- size_t bytes = 0;
184
- int i;
185
-
186
- for (i = 0; i < count; i++) {
187
- bytes += (size_t)bufs[i].len;
188
- }
189
-
190
- return bytes;
191
- }
192
-
193
-
194
- int uv_is_readable(uv_stream_t* handle) {
160
+ int uv_is_readable(const uv_stream_t* handle) {
195
161
  return !(handle->flags & UV_HANDLE_EOF);
196
162
  }
197
163
 
198
164
 
199
- int uv_is_writable(uv_stream_t* handle) {
165
+ int uv_is_writable(const uv_stream_t* handle) {
200
166
  return !(handle->flags & UV_HANDLE_SHUTTING);
201
167
  }
@@ -22,8 +22,10 @@
22
22
  #include <assert.h>
23
23
 
24
24
  #include "uv.h"
25
- #include "../uv-common.h"
26
25
  #include "internal.h"
26
+ #include "handle-inl.h"
27
+ #include "stream-inl.h"
28
+ #include "req-inl.h"
27
29
 
28
30
 
29
31
  /*
@@ -91,12 +93,6 @@ static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle,
91
93
  return -1;
92
94
  }
93
95
 
94
- /* Make the socket non-inheritable */
95
- if (!SetHandleInformation((HANDLE)socket, HANDLE_FLAG_INHERIT, 0)) {
96
- uv__set_sys_error(loop, GetLastError());
97
- return -1;
98
- }
99
-
100
96
  /* Associate it with the I/O completion port. */
101
97
  /* Use uv_handle_t pointer as completion key. */
102
98
  if (CreateIoCompletionPort((HANDLE)socket,
@@ -143,12 +139,11 @@ static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle,
143
139
 
144
140
 
145
141
  int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* handle) {
146
- uv_stream_init(loop, (uv_stream_t*)handle);
142
+ uv_stream_init(loop, (uv_stream_t*) handle, UV_TCP);
147
143
 
148
144
  handle->accept_reqs = NULL;
149
145
  handle->pending_accepts = NULL;
150
146
  handle->socket = INVALID_SOCKET;
151
- handle->type = UV_TCP;
152
147
  handle->reqs_pending = 0;
153
148
  handle->func_acceptex = NULL;
154
149
  handle->func_connectex = NULL;
@@ -170,6 +165,8 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
170
165
  handle->shutdown_req != NULL &&
171
166
  handle->write_reqs_pending == 0) {
172
167
 
168
+ UNREGISTER_HANDLE_REQ(loop, handle, handle->shutdown_req);
169
+
173
170
  if (handle->flags & UV_HANDLE_CLOSING) {
174
171
  status = -1;
175
172
  sys_error = WSAEINTR;
@@ -180,6 +177,7 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
180
177
  status = -1;
181
178
  sys_error = WSAGetLastError();
182
179
  }
180
+
183
181
  if (handle->shutdown_req->cb) {
184
182
  if (status == -1) {
185
183
  uv__set_sys_error(loop, sys_error);
@@ -188,8 +186,6 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
188
186
  }
189
187
 
190
188
  handle->shutdown_req = NULL;
191
-
192
- uv_unref(loop);
193
189
  DECREASE_PENDING_REQ_COUNT(handle);
194
190
  return;
195
191
  }
@@ -197,7 +193,7 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
197
193
  if (handle->flags & UV_HANDLE_CLOSING &&
198
194
  handle->reqs_pending == 0) {
199
195
  assert(!(handle->flags & UV_HANDLE_CLOSED));
200
- handle->flags |= UV_HANDLE_CLOSED;
196
+ uv__handle_stop(handle);
201
197
 
202
198
  if (!(handle->flags & UV_HANDLE_TCP_SOCKET_CLOSED)) {
203
199
  closesocket(handle->socket);
@@ -235,13 +231,8 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
235
231
  }
236
232
  }
237
233
 
238
- if (handle->close_cb) {
239
- handle->close_cb((uv_handle_t*)handle);
240
- }
241
-
234
+ uv__handle_close(handle);
242
235
  loop->active_tcp_streams--;
243
-
244
- uv_unref(loop);
245
236
  }
246
237
  }
247
238
 
@@ -260,6 +251,13 @@ static int uv__bind(uv_tcp_t* handle,
260
251
  return -1;
261
252
  }
262
253
 
254
+ /* Make the socket non-inheritable */
255
+ if (!SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0)) {
256
+ uv__set_sys_error(handle->loop, GetLastError());
257
+ closesocket(sock);
258
+ return -1;
259
+ }
260
+
263
261
  if (uv_tcp_set_socket(handle->loop, handle, sock, 0) == -1) {
264
262
  closesocket(sock);
265
263
  return -1;
@@ -310,10 +308,10 @@ int uv__tcp_bind6(uv_tcp_t* handle, struct sockaddr_in6 addr) {
310
308
 
311
309
 
312
310
  static void CALLBACK post_completion(void* context, BOOLEAN timed_out) {
313
- uv_tcp_accept_t* req;
311
+ uv_req_t* req;
314
312
  uv_tcp_t* handle;
315
313
 
316
- req = (uv_tcp_accept_t*) context;
314
+ req = (uv_req_t*) context;
317
315
  assert(req != NULL);
318
316
  handle = (uv_tcp_t*)req->data;
319
317
  assert(handle != NULL);
@@ -328,6 +326,25 @@ static void CALLBACK post_completion(void* context, BOOLEAN timed_out) {
328
326
  }
329
327
 
330
328
 
329
+ static void CALLBACK post_write_completion(void* context, BOOLEAN timed_out) {
330
+ uv_write_t* req;
331
+ uv_tcp_t* handle;
332
+
333
+ req = (uv_write_t*) context;
334
+ assert(req != NULL);
335
+ handle = (uv_tcp_t*)req->handle;
336
+ assert(handle != NULL);
337
+ assert(!timed_out);
338
+
339
+ if (!PostQueuedCompletionStatus(handle->loop->iocp,
340
+ req->overlapped.InternalHigh,
341
+ 0,
342
+ &req->overlapped)) {
343
+ uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");
344
+ }
345
+ }
346
+
347
+
331
348
  static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) {
332
349
  uv_loop_t* loop = handle->loop;
333
350
  BOOL success;
@@ -354,6 +371,15 @@ static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) {
354
371
  return;
355
372
  }
356
373
 
374
+ /* Make the socket non-inheritable */
375
+ if (!SetHandleInformation((HANDLE) accept_socket, HANDLE_FLAG_INHERIT, 0)) {
376
+ SET_REQ_ERROR(req, GetLastError());
377
+ uv_insert_pending_req(loop, (uv_req_t*)req);
378
+ handle->reqs_pending++;
379
+ closesocket(accept_socket);
380
+ return;
381
+ }
382
+
357
383
  /* Prepare the overlapped structure. */
358
384
  memset(&(req->overlapped), 0, sizeof(req->overlapped));
359
385
  if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
@@ -381,7 +407,7 @@ static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) {
381
407
  if (handle->flags & UV_HANDLE_EMULATE_IOCP &&
382
408
  req->wait_handle == INVALID_HANDLE_VALUE &&
383
409
  !RegisterWaitForSingleObject(&req->wait_handle,
384
- req->overlapped.hEvent, post_completion, (void*) req,
410
+ req->event_handle, post_completion, (void*) req,
385
411
  INFINITE, WT_EXECUTEINWAITTHREAD)) {
386
412
  SET_REQ_ERROR(req, GetLastError());
387
413
  uv_insert_pending_req(loop, (uv_req_t*)req);
@@ -460,7 +486,7 @@ static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) {
460
486
  if (handle->flags & UV_HANDLE_EMULATE_IOCP &&
461
487
  req->wait_handle == INVALID_HANDLE_VALUE &&
462
488
  !RegisterWaitForSingleObject(&req->wait_handle,
463
- req->overlapped.hEvent, post_completion, (void*) req,
489
+ req->event_handle, post_completion, (void*) req,
464
490
  INFINITE, WT_EXECUTEINWAITTHREAD)) {
465
491
  SET_REQ_ERROR(req, GetLastError());
466
492
  uv_insert_pending_req(loop, (uv_req_t*)req);
@@ -481,6 +507,15 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
481
507
 
482
508
  assert(backlog > 0);
483
509
 
510
+ if (handle->flags & UV_HANDLE_LISTENING) {
511
+ handle->connection_cb = cb;
512
+ }
513
+
514
+ if (handle->flags & UV_HANDLE_READING) {
515
+ uv__set_artificial_error(loop, UV_EISCONN);
516
+ return -1;
517
+ }
518
+
484
519
  if (handle->flags & UV_HANDLE_BIND_ERROR) {
485
520
  uv__set_sys_error(loop, handle->bind_error);
486
521
  return -1;
@@ -505,6 +540,7 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
505
540
 
506
541
  handle->flags |= UV_HANDLE_LISTENING;
507
542
  handle->connection_cb = cb;
543
+ INCREASE_ACTIVE_COUNT(loop, handle);
508
544
 
509
545
  simultaneous_accepts = handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT ? 1
510
546
  : uv_simultaneous_server_accepts;
@@ -623,6 +659,7 @@ int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb,
623
659
  handle->flags |= UV_HANDLE_READING;
624
660
  handle->read_cb = read_cb;
625
661
  handle->alloc_cb = alloc_cb;
662
+ INCREASE_ACTIVE_COUNT(loop, handle);
626
663
 
627
664
  /* If reading was stopped and then started again, there could still be a */
628
665
  /* read request pending. */
@@ -683,12 +720,12 @@ int uv__tcp_connect(uv_connect_t* req,
683
720
  if (UV_SUCCEEDED_WITHOUT_IOCP(success)) {
684
721
  /* Process the req without IOCP. */
685
722
  handle->reqs_pending++;
686
- uv_ref(loop);
723
+ REGISTER_HANDLE_REQ(loop, handle, req);
687
724
  uv_insert_pending_req(loop, (uv_req_t*)req);
688
725
  } else if (UV_SUCCEEDED_WITH_IOCP(success)) {
689
726
  /* The req will be processed with IOCP. */
690
727
  handle->reqs_pending++;
691
- uv_ref(loop);
728
+ REGISTER_HANDLE_REQ(loop, handle, req);
692
729
  } else {
693
730
  uv__set_sys_error(loop, WSAGetLastError());
694
731
  return -1;
@@ -744,11 +781,11 @@ int uv__tcp_connect6(uv_connect_t* req,
744
781
 
745
782
  if (UV_SUCCEEDED_WITHOUT_IOCP(success)) {
746
783
  handle->reqs_pending++;
747
- uv_ref(loop);
784
+ REGISTER_HANDLE_REQ(loop, handle, req);
748
785
  uv_insert_pending_req(loop, (uv_req_t*)req);
749
786
  } else if (UV_SUCCEEDED_WITH_IOCP(success)) {
750
787
  handle->reqs_pending++;
751
- uv_ref(loop);
788
+ REGISTER_HANDLE_REQ(loop, handle, req);
752
789
  } else {
753
790
  uv__set_sys_error(loop, WSAGetLastError());
754
791
  return -1;
@@ -837,6 +874,7 @@ int uv_tcp_write(uv_loop_t* loop, uv_write_t* req, uv_tcp_t* handle,
837
874
  uv_fatal_error(GetLastError(), "CreateEvent");
838
875
  }
839
876
  req->overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1);
877
+ req->wait_handle = INVALID_HANDLE_VALUE;
840
878
  }
841
879
 
842
880
  result = WSASend(handle->socket,
@@ -852,20 +890,19 @@ int uv_tcp_write(uv_loop_t* loop, uv_write_t* req, uv_tcp_t* handle,
852
890
  req->queued_bytes = 0;
853
891
  handle->reqs_pending++;
854
892
  handle->write_reqs_pending++;
893
+ REGISTER_HANDLE_REQ(loop, handle, req);
855
894
  uv_insert_pending_req(loop, (uv_req_t*) req);
856
- uv_ref(loop);
857
895
  } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
858
896
  /* Request queued by the kernel. */
859
897
  req->queued_bytes = uv_count_bufs(bufs, bufcnt);
860
898
  handle->reqs_pending++;
861
899
  handle->write_reqs_pending++;
900
+ REGISTER_HANDLE_REQ(loop, handle, req);
862
901
  handle->write_queue_size += req->queued_bytes;
863
- uv_ref(loop);
864
902
  if (handle->flags & UV_HANDLE_EMULATE_IOCP &&
865
- req->wait_handle == INVALID_HANDLE_VALUE &&
866
903
  !RegisterWaitForSingleObject(&req->wait_handle,
867
- req->overlapped.hEvent, post_completion, (void*) req,
868
- INFINITE, WT_EXECUTEINWAITTHREAD)) {
904
+ req->event_handle, post_write_completion, (void*) req,
905
+ INFINITE, WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE)) {
869
906
  SET_REQ_ERROR(req, GetLastError());
870
907
  uv_insert_pending_req(loop, (uv_req_t*)req);
871
908
  }
@@ -893,6 +930,7 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
893
930
  if ((handle->flags & UV_HANDLE_READING) ||
894
931
  !(handle->flags & UV_HANDLE_ZERO_READ)) {
895
932
  handle->flags &= ~UV_HANDLE_READING;
933
+ DECREASE_ACTIVE_COUNT(loop, handle);
896
934
  buf = (handle->flags & UV_HANDLE_ZERO_READ) ?
897
935
  uv_buf_init(NULL, 0) : handle->read_buffer;
898
936
 
@@ -923,8 +961,12 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
923
961
  }
924
962
  } else {
925
963
  /* Connection closed */
926
- handle->flags &= ~UV_HANDLE_READING;
964
+ if (handle->flags & UV_HANDLE_READING) {
965
+ handle->flags &= ~UV_HANDLE_READING;
966
+ DECREASE_ACTIVE_COUNT(loop, handle);
967
+ }
927
968
  handle->flags |= UV_HANDLE_EOF;
969
+
928
970
  uv__set_error(loop, UV_EOF, ERROR_SUCCESS);
929
971
  buf.base = 0;
930
972
  buf.len = 0;
@@ -955,7 +997,9 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
955
997
  } else {
956
998
  /* Connection closed */
957
999
  handle->flags &= ~UV_HANDLE_READING;
1000
+ DECREASE_ACTIVE_COUNT(loop, handle);
958
1001
  handle->flags |= UV_HANDLE_EOF;
1002
+
959
1003
  uv__set_error(loop, UV_EOF, ERROR_SUCCESS);
960
1004
  handle->read_cb((uv_stream_t*)handle, -1, buf);
961
1005
  break;
@@ -967,16 +1011,18 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
967
1011
  uv__set_sys_error(loop, WSAEWOULDBLOCK);
968
1012
  handle->read_cb((uv_stream_t*)handle, 0, buf);
969
1013
  } else {
1014
+ /* Ouch! serious error. */
1015
+ handle->flags &= ~UV_HANDLE_READING;
1016
+ DECREASE_ACTIVE_COUNT(loop, handle);
1017
+
970
1018
  if (err == WSAECONNABORTED) {
971
- /*
972
- * Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with Unix.
973
- */
1019
+ /* Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with */
1020
+ /* Unix. */
974
1021
  uv__set_error(loop, UV_ECONNRESET, err);
975
1022
  } else {
976
- /* Ouch! serious error. */
977
1023
  uv__set_sys_error(loop, err);
978
1024
  }
979
- handle->flags &= ~UV_HANDLE_READING;
1025
+
980
1026
  handle->read_cb((uv_stream_t*)handle, -1, buf);
981
1027
  }
982
1028
  break;
@@ -1002,14 +1048,14 @@ void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle,
1002
1048
  assert(handle->write_queue_size >= req->queued_bytes);
1003
1049
  handle->write_queue_size -= req->queued_bytes;
1004
1050
 
1051
+ UNREGISTER_HANDLE_REQ(loop, handle, req);
1052
+
1005
1053
  if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
1006
1054
  if (req->wait_handle != INVALID_HANDLE_VALUE) {
1007
1055
  UnregisterWait(req->wait_handle);
1008
- req->wait_handle = INVALID_HANDLE_VALUE;
1009
1056
  }
1010
1057
  if (req->event_handle) {
1011
1058
  CloseHandle(req->event_handle);
1012
- req->event_handle = NULL;
1013
1059
  }
1014
1060
  }
1015
1061
 
@@ -1025,7 +1071,6 @@ void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle,
1025
1071
  }
1026
1072
 
1027
1073
  DECREASE_PENDING_REQ_COUNT(handle);
1028
- uv_unref(loop);
1029
1074
  }
1030
1075
 
1031
1076
 
@@ -1042,6 +1087,7 @@ void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle,
1042
1087
  if (req->accept_socket == INVALID_SOCKET) {
1043
1088
  if (handle->flags & UV_HANDLE_LISTENING) {
1044
1089
  handle->flags &= ~UV_HANDLE_LISTENING;
1090
+ DECREASE_ACTIVE_COUNT(loop, handle);
1045
1091
  if (handle->connection_cb) {
1046
1092
  uv__set_sys_error(loop, GET_REQ_SOCK_ERROR(req));
1047
1093
  handle->connection_cb((uv_stream_t*)handle, -1);
@@ -1079,28 +1125,27 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
1079
1125
  uv_connect_t* req) {
1080
1126
  assert(handle->type == UV_TCP);
1081
1127
 
1082
- if (req->cb) {
1083
- if (REQ_SUCCESS(req)) {
1084
- if (setsockopt(handle->socket,
1085
- SOL_SOCKET,
1086
- SO_UPDATE_CONNECT_CONTEXT,
1087
- NULL,
1088
- 0) == 0) {
1089
- uv_connection_init((uv_stream_t*)handle);
1090
- loop->active_tcp_streams++;
1091
- ((uv_connect_cb)req->cb)(req, 0);
1092
- } else {
1093
- uv__set_sys_error(loop, WSAGetLastError());
1094
- ((uv_connect_cb)req->cb)(req, -1);
1095
- }
1128
+ UNREGISTER_HANDLE_REQ(loop, handle, req);
1129
+
1130
+ if (REQ_SUCCESS(req)) {
1131
+ if (setsockopt(handle->socket,
1132
+ SOL_SOCKET,
1133
+ SO_UPDATE_CONNECT_CONTEXT,
1134
+ NULL,
1135
+ 0) == 0) {
1136
+ uv_connection_init((uv_stream_t*)handle);
1137
+ loop->active_tcp_streams++;
1138
+ ((uv_connect_cb)req->cb)(req, 0);
1096
1139
  } else {
1097
- uv__set_sys_error(loop, GET_REQ_SOCK_ERROR(req));
1140
+ uv__set_sys_error(loop, WSAGetLastError());
1098
1141
  ((uv_connect_cb)req->cb)(req, -1);
1099
1142
  }
1143
+ } else {
1144
+ uv__set_sys_error(loop, GET_REQ_SOCK_ERROR(req));
1145
+ ((uv_connect_cb)req->cb)(req, -1);
1100
1146
  }
1101
1147
 
1102
1148
  DECREASE_PENDING_REQ_COUNT(handle);
1103
- uv_unref(loop);
1104
1149
  }
1105
1150
 
1106
1151
 
@@ -1118,21 +1163,28 @@ int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info,
1118
1163
  return -1;
1119
1164
  }
1120
1165
 
1121
- tcp->flags |= UV_HANDLE_BOUND;
1122
- tcp->flags |= UV_HANDLE_SHARED_TCP_SOCKET;
1166
+ if (!SetHandleInformation((HANDLE) socket, HANDLE_FLAG_INHERIT, 0)) {
1167
+ uv__set_sys_error(tcp->loop, GetLastError());
1168
+ closesocket(socket);
1169
+ return -1;
1170
+ }
1171
+
1172
+ if (uv_tcp_set_socket(tcp->loop, tcp, socket, 1) != 0) {
1173
+ closesocket(socket);
1174
+ return -1;
1175
+ }
1123
1176
 
1124
1177
  if (tcp_connection) {
1125
1178
  uv_connection_init((uv_stream_t*)tcp);
1126
1179
  }
1127
1180
 
1181
+ tcp->flags |= UV_HANDLE_BOUND;
1182
+ tcp->flags |= UV_HANDLE_SHARED_TCP_SOCKET;
1183
+
1128
1184
  if (socket_protocol_info->iAddressFamily == AF_INET6) {
1129
1185
  tcp->flags |= UV_HANDLE_IPV6;
1130
1186
  }
1131
1187
 
1132
- if (uv_tcp_set_socket(tcp->loop, tcp, socket, 1) != 0) {
1133
- return -1;
1134
- }
1135
-
1136
1188
  tcp->loop->active_tcp_streams++;
1137
1189
  return 0;
1138
1190
  }
@@ -1172,11 +1224,10 @@ int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) {
1172
1224
  }
1173
1225
 
1174
1226
 
1175
-
1176
1227
  int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid,
1177
1228
  LPWSAPROTOCOL_INFOW protocol_info) {
1178
1229
  if (!(handle->flags & UV_HANDLE_CONNECTION)) {
1179
- /*
1230
+ /*
1180
1231
  * We're about to share the socket with another process. Because
1181
1232
  * this is a listening socket, we assume that the other process will
1182
1233
  * be accepting connections on it. So, before sharing the socket
@@ -1240,42 +1291,109 @@ int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {
1240
1291
  }
1241
1292
 
1242
1293
 
1243
- void uv_tcp_close(uv_tcp_t* tcp) {
1294
+ static int uv_tcp_try_cancel_io(uv_tcp_t* tcp) {
1295
+ SOCKET socket = tcp->socket;
1244
1296
  int non_ifs_lsp;
1297
+
1298
+ /* Check if we have any non-IFS LSPs stacked on top of TCP */
1299
+ non_ifs_lsp = (tcp->flags & UV_HANDLE_IPV6) ? uv_tcp_non_ifs_lsp_ipv6 :
1300
+ uv_tcp_non_ifs_lsp_ipv4;
1301
+
1302
+ /* If there are non-ifs LSPs then try to obtain a base handle for the */
1303
+ /* socket. This will always fail on Windows XP/3k. */
1304
+ if (non_ifs_lsp) {
1305
+ DWORD bytes;
1306
+ if (WSAIoctl(socket,
1307
+ SIO_BASE_HANDLE,
1308
+ NULL,
1309
+ 0,
1310
+ &socket,
1311
+ sizeof socket,
1312
+ &bytes,
1313
+ NULL,
1314
+ NULL) != 0) {
1315
+ /* Failed. We can't do CancelIo. */
1316
+ return -1;
1317
+ }
1318
+ }
1319
+
1320
+ assert(socket != 0 && socket != INVALID_SOCKET);
1321
+
1322
+ if (!CancelIo((HANDLE) socket)) {
1323
+ return -1;
1324
+ }
1325
+
1326
+ /* It worked. */
1327
+ return 0;
1328
+ }
1329
+
1330
+
1331
+ void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) {
1245
1332
  int close_socket = 1;
1246
1333
 
1247
- /*
1248
- * In order for winsock to do a graceful close there must not be
1249
- * any pending reads.
1250
- */
1251
1334
  if (tcp->flags & UV_HANDLE_READ_PENDING) {
1252
- /* Just do shutdown on non-shared sockets, which ensures graceful close. */
1335
+ /* In order for winsock to do a graceful close there must not be any */
1336
+ /* any pending reads, or the socket must be shut down for writing */
1253
1337
  if (!(tcp->flags & UV_HANDLE_SHARED_TCP_SOCKET)) {
1338
+ /* Just do shutdown on non-shared sockets, which ensures graceful close. */
1254
1339
  shutdown(tcp->socket, SD_SEND);
1255
1340
  tcp->flags |= UV_HANDLE_SHUT;
1341
+
1342
+ } else if (uv_tcp_try_cancel_io(tcp) == 0) {
1343
+ /* In case of a shared socket, we try to cancel all outstanding I/O, */
1344
+ /* If that works, don't close the socket yet - wait for the read req to */
1345
+ /* return and close the socket in uv_tcp_endgame. */
1346
+ close_socket = 0;
1347
+
1256
1348
  } else {
1257
- /* Check if we have any non-IFS LSPs stacked on top of TCP */
1258
- non_ifs_lsp = (tcp->flags & UV_HANDLE_IPV6) ? uv_tcp_non_ifs_lsp_ipv6 :
1259
- uv_tcp_non_ifs_lsp_ipv4;
1260
-
1261
- if (!non_ifs_lsp) {
1262
- /*
1263
- * Shared socket with no non-IFS LSPs, request to cancel pending I/O.
1264
- * The socket will be closed inside endgame.
1265
- */
1266
- CancelIo((HANDLE)tcp->socket);
1267
- close_socket = 0;
1349
+ /* When cancelling isn't possible - which could happen when an LSP is */
1350
+ /* present on an old Windows version, we will have to close the socket */
1351
+ /* with a read pending. That is not nice because trailing sent bytes */
1352
+ /* may not make it to the other side. */
1353
+ }
1354
+
1355
+ } else if ((tcp->flags & UV_HANDLE_SHARED_TCP_SOCKET) &&
1356
+ tcp->accept_reqs != NULL) {
1357
+ /* Under normal circumstances closesocket() will ensure that all pending */
1358
+ /* accept reqs are canceled. However, when the socket is shared the */
1359
+ /* presence of another reference to the socket in another process will */
1360
+ /* keep the accept reqs going, so we have to ensure that these are */
1361
+ /* canceled. */
1362
+ if (uv_tcp_try_cancel_io(tcp) != 0) {
1363
+ /* When cancellation is not possible, there is another option: we can */
1364
+ /* close the incoming sockets, which will also cancel the accept */
1365
+ /* operations. However this is not cool because we might inadvertedly */
1366
+ /* close a socket that just accepted a new connection, which will */
1367
+ /* cause the connection to be aborted. */
1368
+ unsigned int i;
1369
+ for (i = 0; i < uv_simultaneous_server_accepts; i++) {
1370
+ uv_tcp_accept_t* req = &tcp->accept_reqs[i];
1371
+ if (req->accept_socket != INVALID_SOCKET &&
1372
+ !HasOverlappedIoCompleted(&req->overlapped)) {
1373
+ closesocket(req->accept_socket);
1374
+ req->accept_socket = INVALID_SOCKET;
1375
+ }
1268
1376
  }
1269
1377
  }
1270
1378
  }
1271
1379
 
1272
- tcp->flags &= ~(UV_HANDLE_READING | UV_HANDLE_LISTENING);
1380
+ if (tcp->flags & UV_HANDLE_READING) {
1381
+ tcp->flags &= ~UV_HANDLE_READING;
1382
+ DECREASE_ACTIVE_COUNT(loop, tcp);
1383
+ }
1384
+
1385
+ if (tcp->flags & UV_HANDLE_LISTENING) {
1386
+ tcp->flags &= ~UV_HANDLE_LISTENING;
1387
+ DECREASE_ACTIVE_COUNT(loop, tcp);
1388
+ }
1273
1389
 
1274
1390
  if (close_socket) {
1275
1391
  closesocket(tcp->socket);
1276
1392
  tcp->flags |= UV_HANDLE_TCP_SOCKET_CLOSED;
1277
1393
  }
1278
1394
 
1395
+ uv__handle_start(tcp);
1396
+
1279
1397
  if (tcp->reqs_pending == 0) {
1280
1398
  uv_want_endgame(tcp->loop, (uv_handle_t*)tcp);
1281
1399
  }