asyncengine 0.0.1.testing1 → 0.0.2.alpha1

Sign up to get free protection for your applications and to get access to all the features.
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
  }