foolio 0.0.3

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 (261) hide show
  1. data/.gitignore +22 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE +22 -0
  4. data/README.md +29 -0
  5. data/Rakefile +21 -0
  6. data/examples/timer.rb +20 -0
  7. data/ext/foolio/extconf.rb +34 -0
  8. data/ext/foolio/foolio_ext.c +921 -0
  9. data/ext/foolio/gen.rb +50 -0
  10. data/ext/foolio/make_table.rb +12 -0
  11. data/ext/foolio/templ +243 -0
  12. data/ext/libuv/.gitignore +33 -0
  13. data/ext/libuv/.mailmap +13 -0
  14. data/ext/libuv/.travis.yml +9 -0
  15. data/ext/libuv/AUTHORS +61 -0
  16. data/ext/libuv/LICENSE +44 -0
  17. data/ext/libuv/Makefile +71 -0
  18. data/ext/libuv/README.md +90 -0
  19. data/ext/libuv/common.gypi +178 -0
  20. data/ext/libuv/gyp_uv +73 -0
  21. data/ext/libuv/include/uv-private/eio.h +403 -0
  22. data/ext/libuv/include/uv-private/ev.h +838 -0
  23. data/ext/libuv/include/uv-private/ngx-queue.h +108 -0
  24. data/ext/libuv/include/uv-private/tree.h +768 -0
  25. data/ext/libuv/include/uv-private/uv-unix.h +324 -0
  26. data/ext/libuv/include/uv-private/uv-win.h +517 -0
  27. data/ext/libuv/include/uv.h +1838 -0
  28. data/ext/libuv/src/fs-poll.c +235 -0
  29. data/ext/libuv/src/inet.c +293 -0
  30. data/ext/libuv/src/unix/async.c +148 -0
  31. data/ext/libuv/src/unix/core.c +696 -0
  32. data/ext/libuv/src/unix/cygwin.c +83 -0
  33. data/ext/libuv/src/unix/darwin.c +342 -0
  34. data/ext/libuv/src/unix/dl.c +83 -0
  35. data/ext/libuv/src/unix/eio/Changes +63 -0
  36. data/ext/libuv/src/unix/eio/LICENSE +36 -0
  37. data/ext/libuv/src/unix/eio/Makefile.am +15 -0
  38. data/ext/libuv/src/unix/eio/aclocal.m4 +8957 -0
  39. data/ext/libuv/src/unix/eio/autogen.sh +3 -0
  40. data/ext/libuv/src/unix/eio/config.h.in +86 -0
  41. data/ext/libuv/src/unix/eio/config_cygwin.h +80 -0
  42. data/ext/libuv/src/unix/eio/config_darwin.h +141 -0
  43. data/ext/libuv/src/unix/eio/config_freebsd.h +81 -0
  44. data/ext/libuv/src/unix/eio/config_linux.h +94 -0
  45. data/ext/libuv/src/unix/eio/config_netbsd.h +81 -0
  46. data/ext/libuv/src/unix/eio/config_openbsd.h +137 -0
  47. data/ext/libuv/src/unix/eio/config_sunos.h +84 -0
  48. data/ext/libuv/src/unix/eio/configure.ac +22 -0
  49. data/ext/libuv/src/unix/eio/demo.c +194 -0
  50. data/ext/libuv/src/unix/eio/ecb.h +370 -0
  51. data/ext/libuv/src/unix/eio/eio.3 +3428 -0
  52. data/ext/libuv/src/unix/eio/eio.c +2593 -0
  53. data/ext/libuv/src/unix/eio/eio.pod +969 -0
  54. data/ext/libuv/src/unix/eio/libeio.m4 +195 -0
  55. data/ext/libuv/src/unix/eio/xthread.h +164 -0
  56. data/ext/libuv/src/unix/error.c +105 -0
  57. data/ext/libuv/src/unix/ev/Changes +388 -0
  58. data/ext/libuv/src/unix/ev/LICENSE +36 -0
  59. data/ext/libuv/src/unix/ev/Makefile.am +18 -0
  60. data/ext/libuv/src/unix/ev/Makefile.in +771 -0
  61. data/ext/libuv/src/unix/ev/README +58 -0
  62. data/ext/libuv/src/unix/ev/aclocal.m4 +8957 -0
  63. data/ext/libuv/src/unix/ev/autogen.sh +6 -0
  64. data/ext/libuv/src/unix/ev/config.guess +1526 -0
  65. data/ext/libuv/src/unix/ev/config.h.in +125 -0
  66. data/ext/libuv/src/unix/ev/config.sub +1658 -0
  67. data/ext/libuv/src/unix/ev/config_cygwin.h +123 -0
  68. data/ext/libuv/src/unix/ev/config_darwin.h +122 -0
  69. data/ext/libuv/src/unix/ev/config_freebsd.h +120 -0
  70. data/ext/libuv/src/unix/ev/config_linux.h +141 -0
  71. data/ext/libuv/src/unix/ev/config_netbsd.h +120 -0
  72. data/ext/libuv/src/unix/ev/config_openbsd.h +126 -0
  73. data/ext/libuv/src/unix/ev/config_sunos.h +122 -0
  74. data/ext/libuv/src/unix/ev/configure +13037 -0
  75. data/ext/libuv/src/unix/ev/configure.ac +18 -0
  76. data/ext/libuv/src/unix/ev/depcomp +630 -0
  77. data/ext/libuv/src/unix/ev/ev++.h +816 -0
  78. data/ext/libuv/src/unix/ev/ev.3 +5311 -0
  79. data/ext/libuv/src/unix/ev/ev.c +3925 -0
  80. data/ext/libuv/src/unix/ev/ev.pod +5243 -0
  81. data/ext/libuv/src/unix/ev/ev_epoll.c +266 -0
  82. data/ext/libuv/src/unix/ev/ev_kqueue.c +235 -0
  83. data/ext/libuv/src/unix/ev/ev_poll.c +148 -0
  84. data/ext/libuv/src/unix/ev/ev_port.c +179 -0
  85. data/ext/libuv/src/unix/ev/ev_select.c +310 -0
  86. data/ext/libuv/src/unix/ev/ev_vars.h +203 -0
  87. data/ext/libuv/src/unix/ev/ev_win32.c +153 -0
  88. data/ext/libuv/src/unix/ev/ev_wrap.h +196 -0
  89. data/ext/libuv/src/unix/ev/event.c +402 -0
  90. data/ext/libuv/src/unix/ev/event.h +170 -0
  91. data/ext/libuv/src/unix/ev/install-sh +294 -0
  92. data/ext/libuv/src/unix/ev/libev.m4 +39 -0
  93. data/ext/libuv/src/unix/ev/ltmain.sh +8413 -0
  94. data/ext/libuv/src/unix/ev/missing +336 -0
  95. data/ext/libuv/src/unix/ev/mkinstalldirs +111 -0
  96. data/ext/libuv/src/unix/freebsd.c +326 -0
  97. data/ext/libuv/src/unix/fs.c +739 -0
  98. data/ext/libuv/src/unix/internal.h +188 -0
  99. data/ext/libuv/src/unix/kqueue.c +120 -0
  100. data/ext/libuv/src/unix/linux/inotify.c +239 -0
  101. data/ext/libuv/src/unix/linux/linux-core.c +557 -0
  102. data/ext/libuv/src/unix/linux/syscalls.c +388 -0
  103. data/ext/libuv/src/unix/linux/syscalls.h +124 -0
  104. data/ext/libuv/src/unix/loop-watcher.c +62 -0
  105. data/ext/libuv/src/unix/loop.c +94 -0
  106. data/ext/libuv/src/unix/netbsd.c +108 -0
  107. data/ext/libuv/src/unix/openbsd.c +295 -0
  108. data/ext/libuv/src/unix/pipe.c +259 -0
  109. data/ext/libuv/src/unix/poll.c +114 -0
  110. data/ext/libuv/src/unix/process.c +495 -0
  111. data/ext/libuv/src/unix/signal.c +269 -0
  112. data/ext/libuv/src/unix/stream.c +990 -0
  113. data/ext/libuv/src/unix/sunos.c +481 -0
  114. data/ext/libuv/src/unix/tcp.c +393 -0
  115. data/ext/libuv/src/unix/thread.c +251 -0
  116. data/ext/libuv/src/unix/timer.c +136 -0
  117. data/ext/libuv/src/unix/tty.c +145 -0
  118. data/ext/libuv/src/unix/udp.c +659 -0
  119. data/ext/libuv/src/unix/uv-eio.c +107 -0
  120. data/ext/libuv/src/unix/uv-eio.h +13 -0
  121. data/ext/libuv/src/uv-common.c +380 -0
  122. data/ext/libuv/src/uv-common.h +170 -0
  123. data/ext/libuv/src/win/async.c +100 -0
  124. data/ext/libuv/src/win/atomicops-inl.h +56 -0
  125. data/ext/libuv/src/win/core.c +278 -0
  126. data/ext/libuv/src/win/dl.c +86 -0
  127. data/ext/libuv/src/win/error.c +155 -0
  128. data/ext/libuv/src/win/fs-event.c +510 -0
  129. data/ext/libuv/src/win/fs.c +1948 -0
  130. data/ext/libuv/src/win/getaddrinfo.c +365 -0
  131. data/ext/libuv/src/win/handle-inl.h +149 -0
  132. data/ext/libuv/src/win/handle.c +154 -0
  133. data/ext/libuv/src/win/internal.h +343 -0
  134. data/ext/libuv/src/win/loop-watcher.c +122 -0
  135. data/ext/libuv/src/win/pipe.c +1672 -0
  136. data/ext/libuv/src/win/poll.c +616 -0
  137. data/ext/libuv/src/win/process-stdio.c +500 -0
  138. data/ext/libuv/src/win/process.c +1013 -0
  139. data/ext/libuv/src/win/req-inl.h +220 -0
  140. data/ext/libuv/src/win/req.c +25 -0
  141. data/ext/libuv/src/win/signal.c +57 -0
  142. data/ext/libuv/src/win/stream-inl.h +67 -0
  143. data/ext/libuv/src/win/stream.c +167 -0
  144. data/ext/libuv/src/win/tcp.c +1394 -0
  145. data/ext/libuv/src/win/thread.c +372 -0
  146. data/ext/libuv/src/win/threadpool.c +74 -0
  147. data/ext/libuv/src/win/timer.c +224 -0
  148. data/ext/libuv/src/win/tty.c +1799 -0
  149. data/ext/libuv/src/win/udp.c +716 -0
  150. data/ext/libuv/src/win/util.c +864 -0
  151. data/ext/libuv/src/win/winapi.c +132 -0
  152. data/ext/libuv/src/win/winapi.h +4452 -0
  153. data/ext/libuv/src/win/winsock.c +557 -0
  154. data/ext/libuv/src/win/winsock.h +171 -0
  155. data/ext/libuv/test/benchmark-async-pummel.c +97 -0
  156. data/ext/libuv/test/benchmark-async.c +137 -0
  157. data/ext/libuv/test/benchmark-fs-stat.c +135 -0
  158. data/ext/libuv/test/benchmark-getaddrinfo.c +94 -0
  159. data/ext/libuv/test/benchmark-list.h +127 -0
  160. data/ext/libuv/test/benchmark-loop-count.c +88 -0
  161. data/ext/libuv/test/benchmark-million-timers.c +65 -0
  162. data/ext/libuv/test/benchmark-ping-pongs.c +213 -0
  163. data/ext/libuv/test/benchmark-pound.c +324 -0
  164. data/ext/libuv/test/benchmark-pump.c +462 -0
  165. data/ext/libuv/test/benchmark-sizes.c +44 -0
  166. data/ext/libuv/test/benchmark-spawn.c +162 -0
  167. data/ext/libuv/test/benchmark-tcp-write-batch.c +140 -0
  168. data/ext/libuv/test/benchmark-thread.c +64 -0
  169. data/ext/libuv/test/benchmark-udp-packet-storm.c +247 -0
  170. data/ext/libuv/test/blackhole-server.c +118 -0
  171. data/ext/libuv/test/dns-server.c +321 -0
  172. data/ext/libuv/test/echo-server.c +378 -0
  173. data/ext/libuv/test/fixtures/empty_file +0 -0
  174. data/ext/libuv/test/fixtures/load_error.node +1 -0
  175. data/ext/libuv/test/run-benchmarks.c +64 -0
  176. data/ext/libuv/test/run-tests.c +138 -0
  177. data/ext/libuv/test/runner-unix.c +295 -0
  178. data/ext/libuv/test/runner-unix.h +36 -0
  179. data/ext/libuv/test/runner-win.c +285 -0
  180. data/ext/libuv/test/runner-win.h +42 -0
  181. data/ext/libuv/test/runner.c +355 -0
  182. data/ext/libuv/test/runner.h +159 -0
  183. data/ext/libuv/test/task.h +112 -0
  184. data/ext/libuv/test/test-async.c +118 -0
  185. data/ext/libuv/test/test-callback-order.c +76 -0
  186. data/ext/libuv/test/test-callback-stack.c +203 -0
  187. data/ext/libuv/test/test-connection-fail.c +148 -0
  188. data/ext/libuv/test/test-cwd-and-chdir.c +64 -0
  189. data/ext/libuv/test/test-delayed-accept.c +188 -0
  190. data/ext/libuv/test/test-dlerror.c +58 -0
  191. data/ext/libuv/test/test-error.c +59 -0
  192. data/ext/libuv/test/test-fail-always.c +29 -0
  193. data/ext/libuv/test/test-fs-event.c +474 -0
  194. data/ext/libuv/test/test-fs-poll.c +146 -0
  195. data/ext/libuv/test/test-fs.c +1843 -0
  196. data/ext/libuv/test/test-get-currentexe.c +63 -0
  197. data/ext/libuv/test/test-get-loadavg.c +36 -0
  198. data/ext/libuv/test/test-get-memory.c +38 -0
  199. data/ext/libuv/test/test-getaddrinfo.c +122 -0
  200. data/ext/libuv/test/test-getsockname.c +342 -0
  201. data/ext/libuv/test/test-hrtime.c +54 -0
  202. data/ext/libuv/test/test-idle.c +81 -0
  203. data/ext/libuv/test/test-ipc-send-recv.c +209 -0
  204. data/ext/libuv/test/test-ipc.c +620 -0
  205. data/ext/libuv/test/test-list.h +427 -0
  206. data/ext/libuv/test/test-loop-handles.c +336 -0
  207. data/ext/libuv/test/test-multiple-listen.c +102 -0
  208. data/ext/libuv/test/test-mutexes.c +63 -0
  209. data/ext/libuv/test/test-pass-always.c +28 -0
  210. data/ext/libuv/test/test-ping-pong.c +253 -0
  211. data/ext/libuv/test/test-pipe-bind-error.c +140 -0
  212. data/ext/libuv/test/test-pipe-connect-error.c +96 -0
  213. data/ext/libuv/test/test-platform-output.c +87 -0
  214. data/ext/libuv/test/test-poll-close.c +72 -0
  215. data/ext/libuv/test/test-poll.c +573 -0
  216. data/ext/libuv/test/test-process-title.c +49 -0
  217. data/ext/libuv/test/test-ref.c +338 -0
  218. data/ext/libuv/test/test-run-once.c +48 -0
  219. data/ext/libuv/test/test-semaphore.c +111 -0
  220. data/ext/libuv/test/test-shutdown-close.c +103 -0
  221. data/ext/libuv/test/test-shutdown-eof.c +183 -0
  222. data/ext/libuv/test/test-signal.c +162 -0
  223. data/ext/libuv/test/test-spawn.c +863 -0
  224. data/ext/libuv/test/test-stdio-over-pipes.c +246 -0
  225. data/ext/libuv/test/test-tcp-bind-error.c +191 -0
  226. data/ext/libuv/test/test-tcp-bind6-error.c +154 -0
  227. data/ext/libuv/test/test-tcp-close-while-connecting.c +80 -0
  228. data/ext/libuv/test/test-tcp-close.c +129 -0
  229. data/ext/libuv/test/test-tcp-connect-error-after-write.c +95 -0
  230. data/ext/libuv/test/test-tcp-connect-error.c +70 -0
  231. data/ext/libuv/test/test-tcp-connect-timeout.c +85 -0
  232. data/ext/libuv/test/test-tcp-connect6-error.c +68 -0
  233. data/ext/libuv/test/test-tcp-flags.c +51 -0
  234. data/ext/libuv/test/test-tcp-shutdown-after-write.c +131 -0
  235. data/ext/libuv/test/test-tcp-unexpected-read.c +113 -0
  236. data/ext/libuv/test/test-tcp-write-error.c +168 -0
  237. data/ext/libuv/test/test-tcp-write-to-half-open-connection.c +135 -0
  238. data/ext/libuv/test/test-tcp-writealot.c +170 -0
  239. data/ext/libuv/test/test-thread.c +183 -0
  240. data/ext/libuv/test/test-threadpool.c +57 -0
  241. data/ext/libuv/test/test-timer-again.c +141 -0
  242. data/ext/libuv/test/test-timer.c +152 -0
  243. data/ext/libuv/test/test-tty.c +110 -0
  244. data/ext/libuv/test/test-udp-dgram-too-big.c +86 -0
  245. data/ext/libuv/test/test-udp-ipv6.c +156 -0
  246. data/ext/libuv/test/test-udp-multicast-join.c +139 -0
  247. data/ext/libuv/test/test-udp-multicast-ttl.c +86 -0
  248. data/ext/libuv/test/test-udp-options.c +86 -0
  249. data/ext/libuv/test/test-udp-send-and-recv.c +208 -0
  250. data/ext/libuv/test/test-util.c +97 -0
  251. data/ext/libuv/test/test-walk-handles.c +77 -0
  252. data/ext/libuv/uv.gyp +375 -0
  253. data/ext/libuv/vcbuild.bat +105 -0
  254. data/foolio.gemspec +18 -0
  255. data/lib/foolio.rb +9 -0
  256. data/lib/foolio/handle.rb +27 -0
  257. data/lib/foolio/listener.rb +26 -0
  258. data/lib/foolio/loop.rb +79 -0
  259. data/lib/foolio/stream.rb +109 -0
  260. data/lib/foolio/version.rb +3 -0
  261. metadata +309 -0
@@ -0,0 +1,148 @@
1
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
3
+ * of this software and associated documentation files (the "Software"), to
4
+ * deal in the Software without restriction, including without limitation the
5
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
6
+ * sell copies of the Software, and to permit persons to whom the Software is
7
+ * furnished to do so, subject to the following conditions:
8
+ *
9
+ * The above copyright notice and this permission notice shall be included in
10
+ * all copies or substantial portions of the Software.
11
+ *
12
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
17
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
18
+ * IN THE SOFTWARE.
19
+ */
20
+
21
+ #include "uv.h"
22
+ #include "internal.h"
23
+
24
+ #include <errno.h>
25
+ #include <assert.h>
26
+ #include <stdlib.h>
27
+ #include <unistd.h>
28
+
29
+ static int uv__async_init(uv_loop_t* loop);
30
+ static void uv__async_io(uv_loop_t* loop, uv__io_t* handle, int events);
31
+
32
+
33
+ __attribute__((always_inline))
34
+ inline static int uv__async_make_pending(volatile sig_atomic_t* ptr) {
35
+ /* Do a cheap read first. */
36
+ if (*ptr)
37
+ return 1;
38
+
39
+ /* Micro-optimization: use atomic memory operations to detect if we've been
40
+ * preempted by another thread and don't have to make an expensive syscall.
41
+ * This speeds up the heavily contended case by about 1-2% and has little
42
+ * if any impact on the non-contended case.
43
+ *
44
+ * Use XCHG instead of the CMPXCHG that __sync_val_compare_and_swap() emits
45
+ * on x86, it's about 4x faster. It probably makes zero difference in the
46
+ * grand scheme of things but I'm OCD enough not to let this one pass.
47
+ */
48
+ #if __i386__ || __x86_64__
49
+ {
50
+ unsigned int val = 1;
51
+ __asm__ __volatile__("xchgl %0, %1" : "+r" (val) : "m" (*ptr));
52
+ return val != 0;
53
+ }
54
+ #elif __GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 1 /* gcc >= 4.1 */
55
+ return __sync_val_compare_and_swap(ptr, 0, 1) != 0;
56
+ #else
57
+ *ptr = 1;
58
+ return 1;
59
+ #endif
60
+ }
61
+
62
+
63
+ int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) {
64
+ if (uv__async_init(loop))
65
+ return uv__set_sys_error(loop, errno);
66
+
67
+ uv__handle_init(loop, (uv_handle_t*)handle, UV_ASYNC);
68
+ handle->async_cb = async_cb;
69
+ handle->pending = 0;
70
+
71
+ ngx_queue_insert_tail(&loop->async_handles, &handle->queue);
72
+ uv__handle_start(handle);
73
+
74
+ return 0;
75
+ }
76
+
77
+
78
+ int uv_async_send(uv_async_t* handle) {
79
+ int r;
80
+
81
+ if (uv__async_make_pending(&handle->pending))
82
+ return 0; /* already pending */
83
+
84
+ do
85
+ r = write(handle->loop->async_pipefd[1], "x", 1);
86
+ while (r == -1 && errno == EINTR);
87
+
88
+ if (r == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
89
+ return uv__set_sys_error(handle->loop, errno);
90
+
91
+ return 0;
92
+ }
93
+
94
+
95
+ void uv__async_close(uv_async_t* handle) {
96
+ ngx_queue_remove(&handle->queue);
97
+ uv__handle_stop(handle);
98
+ }
99
+
100
+
101
+ static int uv__async_init(uv_loop_t* loop) {
102
+ if (loop->async_pipefd[0] != -1)
103
+ return 0;
104
+
105
+ if (uv__make_pipe(loop->async_pipefd, UV__F_NONBLOCK))
106
+ return -1;
107
+
108
+ uv__io_init(&loop->async_watcher,
109
+ uv__async_io,
110
+ loop->async_pipefd[0],
111
+ UV__IO_READ);
112
+ uv__io_start(loop, &loop->async_watcher);
113
+
114
+ return 0;
115
+ }
116
+
117
+
118
+ static void uv__async_io(uv_loop_t* loop, uv__io_t* handle, int events) {
119
+ char buf[1024];
120
+ ngx_queue_t* q;
121
+ uv_async_t* h;
122
+ ssize_t r;
123
+
124
+ while (1) {
125
+ r = read(loop->async_pipefd[0], buf, sizeof(buf));
126
+
127
+ if (r == sizeof(buf))
128
+ continue;
129
+
130
+ if (r != -1)
131
+ break;
132
+
133
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
134
+ break;
135
+
136
+ if (errno == EINTR)
137
+ continue;
138
+
139
+ abort();
140
+ }
141
+
142
+ ngx_queue_foreach(q, &loop->async_handles) {
143
+ h = ngx_queue_data(q, uv_async_t, queue);
144
+ if (!h->pending) continue;
145
+ h->pending = 0;
146
+ h->async_cb(h, 0);
147
+ }
148
+ }
@@ -0,0 +1,696 @@
1
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
3
+ * of this software and associated documentation files (the "Software"), to
4
+ * deal in the Software without restriction, including without limitation the
5
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
6
+ * sell copies of the Software, and to permit persons to whom the Software is
7
+ * furnished to do so, subject to the following conditions:
8
+ *
9
+ * The above copyright notice and this permission notice shall be included in
10
+ * all copies or substantial portions of the Software.
11
+ *
12
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
17
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
18
+ * IN THE SOFTWARE.
19
+ */
20
+
21
+ #include "uv.h"
22
+ #include "internal.h"
23
+
24
+ #include <stddef.h> /* NULL */
25
+ #include <stdio.h> /* printf */
26
+ #include <stdlib.h>
27
+ #include <string.h> /* strerror */
28
+ #include <errno.h>
29
+ #include <assert.h>
30
+ #include <unistd.h>
31
+ #include <sys/types.h>
32
+ #include <sys/stat.h>
33
+ #include <fcntl.h>
34
+ #include <sys/socket.h>
35
+ #include <sys/un.h>
36
+ #include <netinet/in.h>
37
+ #include <arpa/inet.h>
38
+ #include <limits.h> /* PATH_MAX */
39
+ #include <sys/uio.h> /* writev */
40
+
41
+ #ifdef __linux__
42
+ # include <sys/ioctl.h>
43
+ #endif
44
+
45
+ #ifdef __sun
46
+ # include <sys/types.h>
47
+ # include <sys/wait.h>
48
+ #endif
49
+
50
+ #ifdef __APPLE__
51
+ # include <mach-o/dyld.h> /* _NSGetExecutablePath */
52
+ #endif
53
+
54
+ #ifdef __FreeBSD__
55
+ # include <sys/sysctl.h>
56
+ # include <sys/wait.h>
57
+ #endif
58
+
59
+ static uv_loop_t default_loop_struct;
60
+ static uv_loop_t* default_loop_ptr;
61
+
62
+
63
+ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
64
+ handle->close_cb = close_cb;
65
+
66
+ switch (handle->type) {
67
+ case UV_NAMED_PIPE:
68
+ uv__pipe_close((uv_pipe_t*)handle);
69
+ break;
70
+
71
+ case UV_TTY:
72
+ uv__stream_close((uv_stream_t*)handle);
73
+ break;
74
+
75
+ case UV_TCP:
76
+ uv__tcp_close((uv_tcp_t*)handle);
77
+ break;
78
+
79
+ case UV_UDP:
80
+ uv__udp_close((uv_udp_t*)handle);
81
+ break;
82
+
83
+ case UV_PREPARE:
84
+ uv__prepare_close((uv_prepare_t*)handle);
85
+ break;
86
+
87
+ case UV_CHECK:
88
+ uv__check_close((uv_check_t*)handle);
89
+ break;
90
+
91
+ case UV_IDLE:
92
+ uv__idle_close((uv_idle_t*)handle);
93
+ break;
94
+
95
+ case UV_ASYNC:
96
+ uv__async_close((uv_async_t*)handle);
97
+ break;
98
+
99
+ case UV_TIMER:
100
+ uv__timer_close((uv_timer_t*)handle);
101
+ break;
102
+
103
+ case UV_PROCESS:
104
+ uv__process_close((uv_process_t*)handle);
105
+ break;
106
+
107
+ case UV_FS_EVENT:
108
+ uv__fs_event_close((uv_fs_event_t*)handle);
109
+ break;
110
+
111
+ case UV_POLL:
112
+ uv__poll_close((uv_poll_t*)handle);
113
+ break;
114
+
115
+ case UV_FS_POLL:
116
+ uv__fs_poll_close((uv_fs_poll_t*)handle);
117
+ break;
118
+
119
+ case UV_SIGNAL:
120
+ uv__signal_close((uv_signal_t*)handle);
121
+ break;
122
+
123
+ default:
124
+ assert(0);
125
+ }
126
+
127
+ handle->flags |= UV_CLOSING;
128
+
129
+ handle->next_closing = handle->loop->closing_handles;
130
+ handle->loop->closing_handles = handle;
131
+ }
132
+
133
+
134
+ static void uv__finish_close(uv_handle_t* handle) {
135
+ assert(!uv__is_active(handle));
136
+ assert(handle->flags & UV_CLOSING);
137
+ assert(!(handle->flags & UV_CLOSED));
138
+ handle->flags |= UV_CLOSED;
139
+
140
+ switch (handle->type) {
141
+ case UV_PREPARE:
142
+ case UV_CHECK:
143
+ case UV_IDLE:
144
+ case UV_ASYNC:
145
+ case UV_TIMER:
146
+ case UV_PROCESS:
147
+ case UV_FS_EVENT:
148
+ case UV_FS_POLL:
149
+ case UV_POLL:
150
+ case UV_SIGNAL:
151
+ break;
152
+
153
+ case UV_NAMED_PIPE:
154
+ case UV_TCP:
155
+ case UV_TTY:
156
+ assert(!uv__io_active(&((uv_stream_t*)handle)->read_watcher));
157
+ assert(!uv__io_active(&((uv_stream_t*)handle)->write_watcher));
158
+ assert(((uv_stream_t*)handle)->fd == -1);
159
+ uv__stream_destroy((uv_stream_t*)handle);
160
+ break;
161
+
162
+ case UV_UDP:
163
+ uv__udp_finish_close((uv_udp_t*)handle);
164
+ break;
165
+
166
+ default:
167
+ assert(0);
168
+ break;
169
+ }
170
+
171
+ uv__handle_unref(handle);
172
+ ngx_queue_remove(&handle->handle_queue);
173
+
174
+ if (handle->close_cb) {
175
+ handle->close_cb(handle);
176
+ }
177
+ }
178
+
179
+
180
+ static void uv__run_closing_handles(uv_loop_t* loop) {
181
+ uv_handle_t* p;
182
+ uv_handle_t* q;
183
+
184
+ p = loop->closing_handles;
185
+ loop->closing_handles = NULL;
186
+
187
+ while (p) {
188
+ q = p->next_closing;
189
+ uv__finish_close(p);
190
+ p = q;
191
+ }
192
+ }
193
+
194
+
195
+ int uv_is_closing(const uv_handle_t* handle) {
196
+ return handle->flags & (UV_CLOSING | UV_CLOSED);
197
+ }
198
+
199
+
200
+ uv_loop_t* uv_default_loop(void) {
201
+ if (default_loop_ptr)
202
+ return default_loop_ptr;
203
+
204
+ if (uv__loop_init(&default_loop_struct, /* default_loop? */ 1))
205
+ return NULL;
206
+
207
+ return (default_loop_ptr = &default_loop_struct);
208
+ }
209
+
210
+
211
+ uv_loop_t* uv_loop_new(void) {
212
+ uv_loop_t* loop;
213
+
214
+ if ((loop = malloc(sizeof(*loop))) == NULL)
215
+ return NULL;
216
+
217
+ if (uv__loop_init(loop, /* default_loop? */ 0)) {
218
+ free(loop);
219
+ return NULL;
220
+ }
221
+
222
+ return loop;
223
+ }
224
+
225
+
226
+ void uv_loop_delete(uv_loop_t* loop) {
227
+ uv__loop_delete(loop);
228
+ #ifndef NDEBUG
229
+ memset(loop, -1, sizeof *loop);
230
+ #endif
231
+ if (loop == default_loop_ptr)
232
+ default_loop_ptr = NULL;
233
+ else
234
+ free(loop);
235
+ }
236
+
237
+
238
+ static unsigned int uv__poll_timeout(uv_loop_t* loop) {
239
+ if (!uv__has_active_handles(loop) && !uv__has_active_reqs(loop))
240
+ return 0;
241
+
242
+ if (!ngx_queue_empty(&loop->idle_handles))
243
+ return 0;
244
+
245
+ if (loop->closing_handles)
246
+ return 0;
247
+
248
+ return uv__next_timeout(loop);
249
+ }
250
+
251
+
252
+ static void uv__poll(uv_loop_t* loop) {
253
+ void ev__run(EV_P_ ev_tstamp waittime);
254
+ ev_invoke_pending(loop->ev);
255
+ ev__run(loop->ev, uv__poll_timeout(loop) / 1000.);
256
+ ev_invoke_pending(loop->ev);
257
+ }
258
+
259
+
260
+ static int uv__run(uv_loop_t* loop) {
261
+ uv_update_time(loop);
262
+ uv__run_timers(loop);
263
+ uv__run_idle(loop);
264
+ uv__run_prepare(loop);
265
+ uv__poll(loop);
266
+ uv__run_check(loop);
267
+ uv__run_closing_handles(loop);
268
+ return uv__has_active_handles(loop) || uv__has_active_reqs(loop);
269
+ }
270
+
271
+
272
+ int uv_run(uv_loop_t* loop) {
273
+ while (uv__run(loop));
274
+ return 0;
275
+ }
276
+
277
+
278
+ int uv_run_once(uv_loop_t* loop) {
279
+ return uv__run(loop);
280
+ }
281
+
282
+
283
+ void uv_update_time(uv_loop_t* loop) {
284
+ loop->time = uv_hrtime() / 1000000;
285
+ }
286
+
287
+
288
+ int64_t uv_now(uv_loop_t* loop) {
289
+ return loop->time;
290
+ }
291
+
292
+
293
+ int uv_is_active(const uv_handle_t* handle) {
294
+ return uv__is_active(handle);
295
+ }
296
+
297
+
298
+ static int uv_getaddrinfo_done(eio_req* req_) {
299
+ uv_getaddrinfo_t* req = req_->data;
300
+ struct addrinfo *res = req->res;
301
+ #if __sun
302
+ size_t hostlen = strlen(req->hostname);
303
+ #endif
304
+
305
+ req->res = NULL;
306
+
307
+ uv__req_unregister(req->loop, req);
308
+
309
+ /* see initialization in uv_getaddrinfo() */
310
+ if (req->hints)
311
+ free(req->hints);
312
+ else if (req->service)
313
+ free(req->service);
314
+ else if (req->hostname)
315
+ free(req->hostname);
316
+ else
317
+ assert(0);
318
+
319
+ if (req->retcode == 0) {
320
+ /* OK */
321
+ #if EAI_NODATA /* FreeBSD deprecated EAI_NODATA */
322
+ } else if (req->retcode == EAI_NONAME || req->retcode == EAI_NODATA) {
323
+ #else
324
+ } else if (req->retcode == EAI_NONAME) {
325
+ #endif
326
+ uv__set_sys_error(req->loop, ENOENT); /* FIXME compatibility hack */
327
+ #if __sun
328
+ } else if (req->retcode == EAI_MEMORY && hostlen >= MAXHOSTNAMELEN) {
329
+ uv__set_sys_error(req->loop, ENOENT);
330
+ #endif
331
+ } else {
332
+ req->loop->last_err.code = UV_EADDRINFO;
333
+ req->loop->last_err.sys_errno_ = req->retcode;
334
+ }
335
+
336
+ req->cb(req, req->retcode, res);
337
+
338
+ return 0;
339
+ }
340
+
341
+
342
+ static void getaddrinfo_thread_proc(eio_req *req_) {
343
+ uv_getaddrinfo_t* req = req_->data;
344
+
345
+ req->retcode = getaddrinfo(req->hostname,
346
+ req->service,
347
+ req->hints,
348
+ &req->res);
349
+ }
350
+
351
+
352
+ int uv_getaddrinfo(uv_loop_t* loop,
353
+ uv_getaddrinfo_t* req,
354
+ uv_getaddrinfo_cb cb,
355
+ const char* hostname,
356
+ const char* service,
357
+ const struct addrinfo* hints) {
358
+ size_t hostname_len;
359
+ size_t service_len;
360
+ size_t hints_len;
361
+ eio_req* req_;
362
+ size_t len;
363
+ char* buf;
364
+
365
+ if (req == NULL || cb == NULL || (hostname == NULL && service == NULL))
366
+ return uv__set_artificial_error(loop, UV_EINVAL);
367
+
368
+ uv_eio_init(loop);
369
+
370
+ hostname_len = hostname ? strlen(hostname) + 1 : 0;
371
+ service_len = service ? strlen(service) + 1 : 0;
372
+ hints_len = hints ? sizeof(*hints) : 0;
373
+ buf = malloc(hostname_len + service_len + hints_len);
374
+
375
+ if (buf == NULL)
376
+ return uv__set_artificial_error(loop, UV_ENOMEM);
377
+
378
+ uv__req_init(loop, req, UV_GETADDRINFO);
379
+ req->loop = loop;
380
+ req->cb = cb;
381
+ req->res = NULL;
382
+ req->hints = NULL;
383
+ req->service = NULL;
384
+ req->hostname = NULL;
385
+ req->retcode = 0;
386
+
387
+ /* order matters, see uv_getaddrinfo_done() */
388
+ len = 0;
389
+
390
+ if (hints) {
391
+ req->hints = memcpy(buf + len, hints, sizeof(*hints));
392
+ len += sizeof(*hints);
393
+ }
394
+
395
+ if (service) {
396
+ req->service = memcpy(buf + len, service, service_len);
397
+ len += service_len;
398
+ }
399
+
400
+ if (hostname) {
401
+ req->hostname = memcpy(buf + len, hostname, hostname_len);
402
+ len += hostname_len;
403
+ }
404
+
405
+ req_ = eio_custom(getaddrinfo_thread_proc,
406
+ EIO_PRI_DEFAULT,
407
+ uv_getaddrinfo_done,
408
+ req,
409
+ &loop->uv_eio_channel);
410
+
411
+ if (req_)
412
+ return 0;
413
+
414
+ free(buf);
415
+
416
+ return uv__set_artificial_error(loop, UV_ENOMEM);
417
+ }
418
+
419
+
420
+ void uv_freeaddrinfo(struct addrinfo* ai) {
421
+ if (ai)
422
+ freeaddrinfo(ai);
423
+ }
424
+
425
+
426
+ /* Open a socket in non-blocking close-on-exec mode, atomically if possible. */
427
+ int uv__socket(int domain, int type, int protocol) {
428
+ int sockfd;
429
+
430
+ #if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC)
431
+ sockfd = socket(domain, type | SOCK_NONBLOCK | SOCK_CLOEXEC, protocol);
432
+
433
+ if (sockfd != -1)
434
+ goto out;
435
+
436
+ if (errno != EINVAL)
437
+ goto out;
438
+ #endif
439
+
440
+ sockfd = socket(domain, type, protocol);
441
+
442
+ if (sockfd == -1)
443
+ goto out;
444
+
445
+ if (uv__nonblock(sockfd, 1) || uv__cloexec(sockfd, 1)) {
446
+ close(sockfd);
447
+ sockfd = -1;
448
+ }
449
+
450
+ out:
451
+ return sockfd;
452
+ }
453
+
454
+
455
+ int uv__accept(int sockfd) {
456
+ int peerfd;
457
+
458
+ assert(sockfd >= 0);
459
+
460
+ while (1) {
461
+ #if __linux__
462
+ static int no_accept4;
463
+
464
+ if (no_accept4)
465
+ goto skip;
466
+
467
+ peerfd = uv__accept4(sockfd,
468
+ NULL,
469
+ NULL,
470
+ UV__SOCK_NONBLOCK|UV__SOCK_CLOEXEC);
471
+
472
+ if (peerfd != -1)
473
+ break;
474
+
475
+ if (errno == EINTR)
476
+ continue;
477
+
478
+ if (errno != ENOSYS)
479
+ break;
480
+
481
+ no_accept4 = 1;
482
+ skip:
483
+ #endif
484
+
485
+ peerfd = accept(sockfd, NULL, NULL);
486
+
487
+ if (peerfd == -1) {
488
+ if (errno == EINTR)
489
+ continue;
490
+ else
491
+ break;
492
+ }
493
+
494
+ if (uv__cloexec(peerfd, 1) || uv__nonblock(peerfd, 1)) {
495
+ close(peerfd);
496
+ peerfd = -1;
497
+ }
498
+
499
+ break;
500
+ }
501
+
502
+ return peerfd;
503
+ }
504
+
505
+
506
+ #if __linux__
507
+
508
+ int uv__nonblock(int fd, int set) {
509
+ int r;
510
+
511
+ do
512
+ r = ioctl(fd, FIONBIO, &set);
513
+ while (r == -1 && errno == EINTR);
514
+
515
+ return r;
516
+ }
517
+
518
+
519
+ int uv__cloexec(int fd, int set) {
520
+ int r;
521
+
522
+ do
523
+ r = ioctl(fd, set ? FIOCLEX : FIONCLEX);
524
+ while (r == -1 && errno == EINTR);
525
+
526
+ return r;
527
+ }
528
+
529
+ #else /* !__linux__ */
530
+
531
+ int uv__nonblock(int fd, int set) {
532
+ int flags;
533
+ int r;
534
+
535
+ do
536
+ r = fcntl(fd, F_GETFL);
537
+ while (r == -1 && errno == EINTR);
538
+
539
+ if (r == -1)
540
+ return -1;
541
+
542
+ if (set)
543
+ flags = r | O_NONBLOCK;
544
+ else
545
+ flags = r & ~O_NONBLOCK;
546
+
547
+ do
548
+ r = fcntl(fd, F_SETFL, flags);
549
+ while (r == -1 && errno == EINTR);
550
+
551
+ return r;
552
+ }
553
+
554
+
555
+ int uv__cloexec(int fd, int set) {
556
+ int flags;
557
+ int r;
558
+
559
+ do
560
+ r = fcntl(fd, F_GETFD);
561
+ while (r == -1 && errno == EINTR);
562
+
563
+ if (r == -1)
564
+ return -1;
565
+
566
+ if (set)
567
+ flags = r | FD_CLOEXEC;
568
+ else
569
+ flags = r & ~FD_CLOEXEC;
570
+
571
+ do
572
+ r = fcntl(fd, F_SETFD, flags);
573
+ while (r == -1 && errno == EINTR);
574
+
575
+ return r;
576
+ }
577
+
578
+ #endif /* __linux__ */
579
+
580
+
581
+ /* This function is not execve-safe, there is a race window
582
+ * between the call to dup() and fcntl(FD_CLOEXEC).
583
+ */
584
+ int uv__dup(int fd) {
585
+ fd = dup(fd);
586
+
587
+ if (fd == -1)
588
+ return -1;
589
+
590
+ if (uv__cloexec(fd, 1)) {
591
+ SAVE_ERRNO(close(fd));
592
+ return -1;
593
+ }
594
+
595
+ return fd;
596
+ }
597
+
598
+
599
+ /* TODO move to uv-common.c? */
600
+ size_t uv__strlcpy(char* dst, const char* src, size_t size) {
601
+ const char *org;
602
+
603
+ if (size == 0) {
604
+ return 0;
605
+ }
606
+
607
+ org = src;
608
+ while (--size && *src) {
609
+ *dst++ = *src++;
610
+ }
611
+ *dst = '\0';
612
+
613
+ return src - org;
614
+ }
615
+
616
+
617
+ uv_err_t uv_cwd(char* buffer, size_t size) {
618
+ if (!buffer || !size) {
619
+ return uv__new_artificial_error(UV_EINVAL);
620
+ }
621
+
622
+ if (getcwd(buffer, size)) {
623
+ return uv_ok_;
624
+ } else {
625
+ return uv__new_sys_error(errno);
626
+ }
627
+ }
628
+
629
+
630
+ uv_err_t uv_chdir(const char* dir) {
631
+ if (chdir(dir) == 0) {
632
+ return uv_ok_;
633
+ } else {
634
+ return uv__new_sys_error(errno);
635
+ }
636
+ }
637
+
638
+
639
+ void uv_disable_stdio_inheritance(void) {
640
+ int fd;
641
+
642
+ /* Set the CLOEXEC flag on all open descriptors. Unconditionally try the
643
+ * first 16 file descriptors. After that, bail out after the first error.
644
+ */
645
+ for (fd = 0; ; fd++)
646
+ if (uv__cloexec(fd, 1) && fd > 15)
647
+ break;
648
+ }
649
+
650
+
651
+ static void uv__io_set_cb(uv__io_t* handle, uv__io_cb cb) {
652
+ union { void* data; uv__io_cb cb; } u;
653
+ u.cb = cb;
654
+ handle->io_watcher.data = u.data;
655
+ }
656
+
657
+
658
+ static void uv__io_rw(struct ev_loop* ev, ev_io* w, int events) {
659
+ union { void* data; uv__io_cb cb; } u;
660
+ uv_loop_t* loop = ev_userdata(ev);
661
+ uv__io_t* handle = container_of(w, uv__io_t, io_watcher);
662
+ u.data = handle->io_watcher.data;
663
+ u.cb(loop, handle, events & (EV_READ|EV_WRITE|EV_ERROR));
664
+ }
665
+
666
+
667
+ void uv__io_init(uv__io_t* handle, uv__io_cb cb, int fd, int events) {
668
+ ev_io_init(&handle->io_watcher, uv__io_rw, fd, events & (EV_READ|EV_WRITE));
669
+ uv__io_set_cb(handle, cb);
670
+ }
671
+
672
+
673
+ void uv__io_set(uv__io_t* handle, uv__io_cb cb, int fd, int events) {
674
+ ev_io_set(&handle->io_watcher, fd, events);
675
+ uv__io_set_cb(handle, cb);
676
+ }
677
+
678
+
679
+ void uv__io_start(uv_loop_t* loop, uv__io_t* handle) {
680
+ ev_io_start(loop->ev, &handle->io_watcher);
681
+ }
682
+
683
+
684
+ void uv__io_stop(uv_loop_t* loop, uv__io_t* handle) {
685
+ ev_io_stop(loop->ev, &handle->io_watcher);
686
+ }
687
+
688
+
689
+ void uv__io_feed(uv_loop_t* loop, uv__io_t* handle, int event) {
690
+ ev_feed_event(loop->ev, &handle->io_watcher, event);
691
+ }
692
+
693
+
694
+ int uv__io_active(uv__io_t* handle) {
695
+ return ev_is_active(&handle->io_watcher);
696
+ }