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.
- data/README.markdown +3 -0
- data/Rakefile +38 -0
- data/asyncengine.gemspec +8 -4
- data/ext/asyncengine/ae_call_from_other_thread.c +106 -0
- data/ext/asyncengine/ae_call_from_other_thread.h +12 -0
- data/ext/asyncengine/ae_handle_common.c +193 -48
- data/ext/asyncengine/ae_handle_common.h +40 -13
- data/ext/asyncengine/ae_ip_utils.c +246 -0
- data/ext/asyncengine/ae_ip_utils.h +25 -0
- data/ext/asyncengine/ae_next_tick.c +81 -21
- data/ext/asyncengine/ae_next_tick.h +4 -2
- data/ext/asyncengine/ae_resolver.c +156 -0
- data/ext/asyncengine/ae_resolver.h +10 -0
- data/ext/asyncengine/ae_tcp.c +908 -0
- data/ext/asyncengine/ae_tcp.h +20 -0
- data/ext/asyncengine/ae_timer.c +355 -81
- data/ext/asyncengine/ae_timer.h +11 -4
- data/ext/asyncengine/ae_udp.c +579 -13
- data/ext/asyncengine/ae_udp.h +15 -2
- data/ext/asyncengine/ae_utils.c +192 -0
- data/ext/asyncengine/ae_utils.h +16 -0
- data/ext/asyncengine/asyncengine_ruby.c +469 -26
- data/ext/asyncengine/asyncengine_ruby.h +49 -11
- data/ext/asyncengine/debug.h +68 -0
- data/ext/asyncengine/extconf.rb +26 -2
- data/ext/asyncengine/ip_parser.c +5954 -0
- data/ext/asyncengine/ip_parser.h +16 -0
- data/ext/asyncengine/libuv/AUTHORS +16 -0
- data/ext/asyncengine/libuv/common.gypi +4 -4
- data/ext/asyncengine/libuv/config-mingw.mk +6 -6
- data/ext/asyncengine/libuv/config-unix.mk +13 -13
- data/ext/asyncengine/libuv/gyp_uv +5 -1
- data/ext/asyncengine/libuv/ibc_tests/exec_test.sh +8 -0
- data/ext/asyncengine/libuv/ibc_tests/uv_shutdown_write_issue.c +171 -0
- data/ext/asyncengine/libuv/ibc_tests/uv_tcp_close_while_connecting.c +102 -0
- data/ext/asyncengine/libuv/include/uv-private/ngx-queue.h +3 -1
- data/ext/asyncengine/libuv/include/uv-private/uv-unix.h +103 -50
- data/ext/asyncengine/libuv/include/uv-private/uv-win.h +76 -24
- data/ext/asyncengine/libuv/include/uv.h +353 -88
- data/ext/asyncengine/libuv/src/ares/ares__close_sockets.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares__get_hostent.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares__read_line.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares__timeval.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_cancel.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_data.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_destroy.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_expand_name.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_expand_string.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_fds.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_free_hostent.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_free_string.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_gethostbyaddr.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_gethostbyname.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_getnameinfo.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_getopt.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_getsock.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_init.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_library_init.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_llist.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_mkquery.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_nowarn.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_options.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_parse_a_reply.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_parse_aaaa_reply.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_parse_mx_reply.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_parse_ns_reply.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_parse_ptr_reply.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_parse_srv_reply.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_parse_txt_reply.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_process.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_query.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_search.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_send.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_strcasecmp.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_strdup.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_strerror.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_timeout.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_version.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_writev.o +0 -0
- data/ext/asyncengine/libuv/src/ares/bitncmp.o +0 -0
- data/ext/asyncengine/libuv/src/ares/inet_net_pton.o +0 -0
- data/ext/asyncengine/libuv/src/ares/inet_ntop.o +0 -0
- data/ext/asyncengine/libuv/src/cares.c +225 -0
- data/ext/asyncengine/libuv/src/cares.o +0 -0
- data/ext/asyncengine/libuv/src/fs-poll.c +237 -0
- data/ext/asyncengine/libuv/src/fs-poll.o +0 -0
- data/ext/asyncengine/libuv/src/unix/async.c +78 -17
- data/ext/asyncengine/libuv/src/unix/async.o +0 -0
- data/ext/asyncengine/libuv/src/unix/core.c +305 -213
- data/ext/asyncengine/libuv/src/unix/core.o +0 -0
- data/ext/asyncengine/libuv/src/unix/cygwin.c +1 -1
- data/ext/asyncengine/libuv/src/unix/darwin.c +2 -1
- data/ext/asyncengine/libuv/src/unix/dl.c +36 -44
- data/ext/asyncengine/libuv/src/unix/dl.o +0 -0
- data/ext/asyncengine/libuv/src/unix/eio/eio.o +0 -0
- data/ext/asyncengine/libuv/src/unix/error.c +6 -0
- data/ext/asyncengine/libuv/src/unix/error.o +0 -0
- data/ext/asyncengine/libuv/src/unix/ev/ev.c +8 -4
- data/ext/asyncengine/libuv/src/unix/ev/ev.o +0 -0
- data/ext/asyncengine/libuv/src/unix/freebsd.c +1 -1
- data/ext/asyncengine/libuv/src/unix/fs.c +25 -33
- data/ext/asyncengine/libuv/src/unix/fs.o +0 -0
- data/ext/asyncengine/libuv/src/unix/internal.h +50 -31
- data/ext/asyncengine/libuv/src/unix/kqueue.c +2 -7
- data/ext/asyncengine/libuv/src/unix/linux/core.o +0 -0
- data/ext/asyncengine/libuv/src/unix/linux/inotify.c +12 -14
- data/ext/asyncengine/libuv/src/unix/linux/inotify.o +0 -0
- data/ext/asyncengine/libuv/src/unix/linux/{core.c → linux-core.c} +1 -1
- data/ext/asyncengine/libuv/src/unix/linux/linux-core.o +0 -0
- data/ext/asyncengine/libuv/src/unix/linux/syscalls.c +147 -1
- data/ext/asyncengine/libuv/src/unix/linux/syscalls.h +39 -2
- data/ext/asyncengine/libuv/src/unix/linux/syscalls.o +0 -0
- data/ext/asyncengine/libuv/src/unix/loop-watcher.c +63 -0
- data/ext/asyncengine/libuv/src/unix/loop-watcher.o +0 -0
- data/ext/asyncengine/libuv/src/unix/loop.c +29 -6
- data/ext/asyncengine/libuv/src/unix/loop.o +0 -0
- data/ext/asyncengine/libuv/src/unix/netbsd.c +1 -1
- data/ext/asyncengine/libuv/src/unix/openbsd.c +1 -1
- data/ext/asyncengine/libuv/src/unix/pipe.c +31 -36
- data/ext/asyncengine/libuv/src/unix/pipe.o +0 -0
- data/ext/asyncengine/libuv/src/unix/poll.c +116 -0
- data/ext/asyncengine/libuv/src/unix/poll.o +0 -0
- data/ext/asyncengine/libuv/src/unix/process.c +193 -115
- data/ext/asyncengine/libuv/src/unix/process.o +0 -0
- data/ext/asyncengine/libuv/src/unix/stream.c +146 -153
- data/ext/asyncengine/libuv/src/unix/stream.o +0 -0
- data/ext/asyncengine/libuv/src/unix/sunos.c +45 -36
- data/ext/asyncengine/libuv/src/unix/tcp.c +6 -5
- data/ext/asyncengine/libuv/src/unix/tcp.o +0 -0
- data/ext/asyncengine/libuv/src/unix/thread.c +82 -25
- data/ext/asyncengine/libuv/src/unix/thread.o +0 -0
- data/ext/asyncengine/libuv/src/unix/timer.c +69 -58
- data/ext/asyncengine/libuv/src/unix/timer.o +0 -0
- data/ext/asyncengine/libuv/src/unix/tty.c +3 -3
- data/ext/asyncengine/libuv/src/unix/tty.o +0 -0
- data/ext/asyncengine/libuv/src/unix/udp.c +57 -66
- data/ext/asyncengine/libuv/src/unix/udp.o +0 -0
- data/ext/asyncengine/libuv/src/unix/uv-eio.c +33 -50
- data/ext/asyncengine/libuv/src/unix/uv-eio.o +0 -0
- data/ext/asyncengine/libuv/src/uv-common.c +68 -38
- data/ext/asyncengine/libuv/src/uv-common.h +104 -20
- data/ext/asyncengine/libuv/src/uv-common.o +0 -0
- data/ext/asyncengine/libuv/src/win/async.c +20 -17
- data/ext/asyncengine/libuv/src/win/core.c +44 -31
- data/ext/asyncengine/libuv/src/win/dl.c +40 -36
- data/ext/asyncengine/libuv/src/win/error.c +21 -1
- data/ext/asyncengine/libuv/src/win/fs-event.c +19 -21
- data/ext/asyncengine/libuv/src/win/fs.c +541 -189
- data/ext/asyncengine/libuv/src/win/getaddrinfo.c +56 -63
- data/ext/asyncengine/libuv/src/win/handle-inl.h +145 -0
- data/ext/asyncengine/libuv/src/win/handle.c +26 -101
- data/ext/asyncengine/libuv/src/win/internal.h +92 -107
- data/ext/asyncengine/libuv/src/win/loop-watcher.c +6 -14
- data/ext/asyncengine/libuv/src/win/pipe.c +78 -64
- data/ext/asyncengine/libuv/src/win/poll.c +618 -0
- data/ext/asyncengine/libuv/src/win/process-stdio.c +479 -0
- data/ext/asyncengine/libuv/src/win/process.c +147 -274
- data/ext/asyncengine/libuv/src/win/req-inl.h +225 -0
- data/ext/asyncengine/libuv/src/win/req.c +0 -149
- data/ext/asyncengine/libuv/src/{unix/check.c → win/stream-inl.h} +31 -42
- data/ext/asyncengine/libuv/src/win/stream.c +9 -43
- data/ext/asyncengine/libuv/src/win/tcp.c +200 -82
- data/ext/asyncengine/libuv/src/win/thread.c +42 -2
- data/ext/asyncengine/libuv/src/win/threadpool.c +3 -2
- data/ext/asyncengine/libuv/src/win/timer.c +13 -63
- data/ext/asyncengine/libuv/src/win/tty.c +26 -20
- data/ext/asyncengine/libuv/src/win/udp.c +26 -17
- data/ext/asyncengine/libuv/src/win/util.c +312 -167
- data/ext/asyncengine/libuv/src/win/winapi.c +16 -1
- data/ext/asyncengine/libuv/src/win/winapi.h +33 -9
- data/ext/asyncengine/libuv/src/win/winsock.c +88 -1
- data/ext/asyncengine/libuv/src/win/winsock.h +36 -3
- data/ext/asyncengine/libuv/test/benchmark-ares.c +16 -17
- data/ext/asyncengine/libuv/test/benchmark-fs-stat.c +164 -0
- data/ext/asyncengine/libuv/test/benchmark-list.h +9 -0
- data/ext/asyncengine/libuv/{src/unix/prepare.c → test/benchmark-loop-count.c} +42 -33
- data/ext/asyncengine/libuv/test/benchmark-million-timers.c +65 -0
- data/ext/asyncengine/libuv/test/benchmark-pound.c +1 -1
- data/ext/asyncengine/libuv/test/benchmark-sizes.c +2 -0
- data/ext/asyncengine/libuv/test/benchmark-spawn.c +7 -1
- data/ext/asyncengine/libuv/test/benchmark-udp-packet-storm.c +1 -1
- data/ext/asyncengine/libuv/test/echo-server.c +8 -0
- data/ext/asyncengine/libuv/test/run-tests.c +30 -0
- data/ext/asyncengine/libuv/test/runner-unix.c +6 -26
- data/ext/asyncengine/libuv/test/runner-win.c +5 -63
- data/ext/asyncengine/libuv/test/runner.c +10 -1
- data/ext/asyncengine/libuv/test/task.h +0 -8
- data/ext/asyncengine/libuv/test/test-async.c +43 -141
- data/ext/asyncengine/libuv/test/test-callback-order.c +76 -0
- data/ext/asyncengine/libuv/test/test-counters-init.c +2 -3
- data/ext/asyncengine/libuv/test/test-dlerror.c +17 -8
- data/ext/asyncengine/libuv/test/test-fs-event.c +31 -39
- data/ext/asyncengine/libuv/test/test-fs-poll.c +146 -0
- data/ext/asyncengine/libuv/test/test-fs.c +114 -2
- data/ext/asyncengine/libuv/test/test-gethostbyname.c +8 -8
- data/ext/asyncengine/libuv/test/test-hrtime.c +18 -15
- data/ext/asyncengine/libuv/test/test-ipc.c +8 -2
- data/ext/asyncengine/libuv/test/test-list.h +59 -9
- data/ext/asyncengine/libuv/test/test-loop-handles.c +2 -25
- data/ext/asyncengine/libuv/{src/unix/idle.c → test/test-poll-close.c} +37 -39
- data/ext/asyncengine/libuv/test/test-poll.c +573 -0
- data/ext/asyncengine/libuv/test/test-ref.c +79 -63
- data/ext/asyncengine/libuv/test/test-run-once.c +15 -11
- data/ext/asyncengine/libuv/test/test-semaphore.c +111 -0
- data/ext/asyncengine/libuv/test/test-spawn.c +368 -20
- data/ext/asyncengine/libuv/test/test-stdio-over-pipes.c +25 -35
- data/ext/asyncengine/libuv/test/test-tcp-close-while-connecting.c +80 -0
- data/ext/asyncengine/libuv/test/test-tcp-close.c +1 -1
- data/ext/asyncengine/libuv/test/test-tcp-connect-error-after-write.c +95 -0
- data/ext/asyncengine/libuv/test/test-tcp-connect-timeout.c +85 -0
- data/ext/asyncengine/libuv/test/test-tcp-shutdown-after-write.c +131 -0
- data/ext/asyncengine/libuv/test/test-tcp-write-error.c +2 -2
- data/ext/asyncengine/libuv/test/test-tcp-writealot.c +29 -54
- data/ext/asyncengine/libuv/test/test-timer-again.c +1 -1
- data/ext/asyncengine/libuv/test/test-timer.c +23 -1
- data/ext/asyncengine/libuv/test/test-udp-options.c +1 -1
- data/ext/asyncengine/libuv/test/{test-eio-overflow.c → test-walk-handles.c} +31 -44
- data/ext/asyncengine/libuv/uv.gyp +26 -9
- data/ext/asyncengine/rb_utilities.c +54 -0
- data/ext/asyncengine/rb_utilities.h +63 -0
- data/lib/asyncengine.rb +45 -38
- data/lib/asyncengine/asyncengine_ext.so +0 -0
- data/lib/asyncengine/debug.rb +37 -0
- data/lib/asyncengine/handle.rb +9 -0
- data/lib/asyncengine/tcp.rb +28 -0
- data/lib/asyncengine/timer.rb +18 -28
- data/lib/asyncengine/udp.rb +29 -0
- data/lib/asyncengine/utils.rb +32 -0
- data/lib/asyncengine/uv_error.rb +17 -0
- data/lib/asyncengine/version.rb +9 -1
- data/test/ae_test_helper.rb +62 -0
- data/test/test_basic.rb +169 -0
- data/test/test_call_from_other_thread.rb +55 -0
- data/test/test_error.rb +92 -0
- data/test/test_ip_utils.rb +44 -0
- data/test/test_next_tick.rb +37 -0
- data/test/test_resolver.rb +51 -0
- data/test/test_threads.rb +69 -0
- data/test/test_timer.rb +95 -0
- data/test/test_udp.rb +216 -0
- data/test/test_utils.rb +49 -0
- metadata +84 -57
- data/ext/asyncengine/libuv/mkmf.log +0 -24
- data/ext/asyncengine/libuv/src/unix/cares.c +0 -194
- data/ext/asyncengine/libuv/src/unix/cares.o +0 -0
- data/ext/asyncengine/libuv/src/unix/check.o +0 -0
- data/ext/asyncengine/libuv/src/unix/idle.o +0 -0
- data/ext/asyncengine/libuv/src/unix/prepare.o +0 -0
- data/ext/asyncengine/libuv/src/win/cares.c +0 -290
- data/lib/asyncengine/errors.rb +0 -5
- data/lib/asyncengine/next_tick.rb +0 -24
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
|
2
|
+
*
|
|
3
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
* of this software and associated documentation files (the "Software"), to
|
|
5
|
+
* deal in the Software without restriction, including without limitation the
|
|
6
|
+
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
7
|
+
* sell copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
* furnished to do so, subject to the following conditions:
|
|
9
|
+
*
|
|
10
|
+
* The above copyright notice and this permission notice shall be included in
|
|
11
|
+
* all copies or substantial portions of the Software.
|
|
12
|
+
*
|
|
13
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
18
|
+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
19
|
+
* IN THE SOFTWARE.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
#include <assert.h>
|
|
23
|
+
#include <io.h>
|
|
24
|
+
#include <stdio.h>
|
|
25
|
+
#include <stdlib.h>
|
|
26
|
+
|
|
27
|
+
#include "uv.h"
|
|
28
|
+
#include "internal.h"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
/*
|
|
32
|
+
* The `child_stdio_buffer` buffer has the following layout:
|
|
33
|
+
* int number_of_fds
|
|
34
|
+
* unsigned char crt_flags[number_of_fds]
|
|
35
|
+
* HANDLE os_handle[number_of_fds]
|
|
36
|
+
*/
|
|
37
|
+
#define CHILD_STDIO_SIZE(count) \
|
|
38
|
+
(sizeof(int) + \
|
|
39
|
+
sizeof(unsigned char) * (count) + \
|
|
40
|
+
sizeof(uintptr_t) * (count))
|
|
41
|
+
|
|
42
|
+
#define CHILD_STDIO_COUNT(buffer) \
|
|
43
|
+
*((unsigned int*) (buffer))
|
|
44
|
+
|
|
45
|
+
#define CHILD_STDIO_CRT_FLAGS(buffer, fd) \
|
|
46
|
+
*((unsigned char*) (buffer) + sizeof(int) + fd)
|
|
47
|
+
|
|
48
|
+
#define CHILD_STDIO_HANDLE(buffer, fd) \
|
|
49
|
+
*((HANDLE*) ((unsigned char*) (buffer) + \
|
|
50
|
+
sizeof(int) + \
|
|
51
|
+
sizeof(unsigned char) * \
|
|
52
|
+
CHILD_STDIO_COUNT((buffer)) + \
|
|
53
|
+
sizeof(HANDLE) * (fd)))
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
/* CRT file descriptor mode flags */
|
|
57
|
+
#define FOPEN 0x01
|
|
58
|
+
#define FEOFLAG 0x02
|
|
59
|
+
#define FCRLF 0x04
|
|
60
|
+
#define FPIPE 0x08
|
|
61
|
+
#define FNOINHERIT 0x10
|
|
62
|
+
#define FAPPEND 0x20
|
|
63
|
+
#define FDEV 0x40
|
|
64
|
+
#define FTEXT 0x80
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
/*
|
|
68
|
+
* Clear the HANDLE_FLAG_INHERIT flag from all HANDLEs that were inherited
|
|
69
|
+
* the parent process. Don't check for errors - the stdio handles may not be
|
|
70
|
+
* valid, or may be closed already. There is no guarantee that this function
|
|
71
|
+
* does a perfect job.
|
|
72
|
+
*/
|
|
73
|
+
void uv_disable_stdio_inheritance(void) {
|
|
74
|
+
HANDLE handle;
|
|
75
|
+
STARTUPINFOW si;
|
|
76
|
+
|
|
77
|
+
/* Make the windows stdio handles non-inheritable. */
|
|
78
|
+
handle = GetStdHandle(STD_INPUT_HANDLE);
|
|
79
|
+
if (handle != NULL && handle != INVALID_HANDLE_VALUE)
|
|
80
|
+
SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0);
|
|
81
|
+
|
|
82
|
+
handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
83
|
+
if (handle != NULL && handle != INVALID_HANDLE_VALUE)
|
|
84
|
+
SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0);
|
|
85
|
+
|
|
86
|
+
handle = GetStdHandle(STD_ERROR_HANDLE);
|
|
87
|
+
if (handle != NULL && handle != INVALID_HANDLE_VALUE)
|
|
88
|
+
SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0);
|
|
89
|
+
|
|
90
|
+
/* Make inherited CRT FDs non-inheritable. */
|
|
91
|
+
GetStartupInfoW(&si);
|
|
92
|
+
if (uv__stdio_verify(si.lpReserved2, si.cbReserved2))
|
|
93
|
+
uv__stdio_noinherit(si.lpReserved2);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
static int uv__create_stdio_pipe_pair(uv_loop_t* loop, uv_pipe_t* server_pipe,
|
|
98
|
+
HANDLE* child_pipe_ptr, unsigned int flags) {
|
|
99
|
+
char pipe_name[64];
|
|
100
|
+
SECURITY_ATTRIBUTES sa;
|
|
101
|
+
DWORD server_access = 0;
|
|
102
|
+
DWORD client_access = 0;
|
|
103
|
+
HANDLE child_pipe = INVALID_HANDLE_VALUE;
|
|
104
|
+
|
|
105
|
+
if (flags & UV_READABLE_PIPE) {
|
|
106
|
+
server_access |= PIPE_ACCESS_OUTBOUND;
|
|
107
|
+
client_access |= GENERIC_READ | FILE_WRITE_ATTRIBUTES;
|
|
108
|
+
}
|
|
109
|
+
if (flags & UV_WRITABLE_PIPE) {
|
|
110
|
+
server_access |= PIPE_ACCESS_INBOUND;
|
|
111
|
+
client_access |= GENERIC_WRITE;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* Create server pipe handle. */
|
|
115
|
+
if (uv_stdio_pipe_server(loop,
|
|
116
|
+
server_pipe,
|
|
117
|
+
server_access,
|
|
118
|
+
pipe_name,
|
|
119
|
+
sizeof(pipe_name)) < 0) {
|
|
120
|
+
goto error;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* Create child pipe handle. */
|
|
124
|
+
sa.nLength = sizeof sa;
|
|
125
|
+
sa.lpSecurityDescriptor = NULL;
|
|
126
|
+
sa.bInheritHandle = TRUE;
|
|
127
|
+
|
|
128
|
+
child_pipe = CreateFileA(pipe_name,
|
|
129
|
+
client_access,
|
|
130
|
+
0,
|
|
131
|
+
&sa,
|
|
132
|
+
OPEN_EXISTING,
|
|
133
|
+
server_pipe->ipc ? FILE_FLAG_OVERLAPPED : 0,
|
|
134
|
+
NULL);
|
|
135
|
+
if (child_pipe == INVALID_HANDLE_VALUE) {
|
|
136
|
+
uv__set_sys_error(loop, GetLastError());
|
|
137
|
+
goto error;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
#ifndef NDEBUG
|
|
141
|
+
/* Validate that the pipe was opened in the right mode. */
|
|
142
|
+
{
|
|
143
|
+
DWORD mode;
|
|
144
|
+
BOOL r = GetNamedPipeHandleState(child_pipe,
|
|
145
|
+
&mode,
|
|
146
|
+
NULL,
|
|
147
|
+
NULL,
|
|
148
|
+
NULL,
|
|
149
|
+
NULL,
|
|
150
|
+
0);
|
|
151
|
+
assert(r == TRUE);
|
|
152
|
+
assert(mode == (PIPE_READMODE_BYTE | PIPE_WAIT));
|
|
153
|
+
}
|
|
154
|
+
#endif
|
|
155
|
+
|
|
156
|
+
/* Do a blocking ConnectNamedPipe. This should not block because we have */
|
|
157
|
+
/* both ends of the pipe created. */
|
|
158
|
+
if (!ConnectNamedPipe(server_pipe->handle, NULL)) {
|
|
159
|
+
if (GetLastError() != ERROR_PIPE_CONNECTED) {
|
|
160
|
+
uv__set_sys_error(loop, GetLastError());
|
|
161
|
+
goto error;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
*child_pipe_ptr = child_pipe;
|
|
166
|
+
return 0;
|
|
167
|
+
|
|
168
|
+
error:
|
|
169
|
+
if (server_pipe->handle != INVALID_HANDLE_VALUE) {
|
|
170
|
+
uv_pipe_cleanup(loop, server_pipe);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (child_pipe != INVALID_HANDLE_VALUE) {
|
|
174
|
+
CloseHandle(child_pipe);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return -1;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
static int uv__duplicate_handle(uv_loop_t* loop, HANDLE handle, HANDLE* dup) {
|
|
182
|
+
HANDLE current_process;
|
|
183
|
+
|
|
184
|
+
current_process = GetCurrentProcess();
|
|
185
|
+
|
|
186
|
+
if (!DuplicateHandle(current_process,
|
|
187
|
+
handle,
|
|
188
|
+
current_process,
|
|
189
|
+
dup,
|
|
190
|
+
0,
|
|
191
|
+
TRUE,
|
|
192
|
+
DUPLICATE_SAME_ACCESS)) {
|
|
193
|
+
*dup = INVALID_HANDLE_VALUE;
|
|
194
|
+
uv__set_sys_error(loop, GetLastError());
|
|
195
|
+
return -1;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return 0;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
static int uv__duplicate_fd(uv_loop_t* loop, int fd, HANDLE* dup) {
|
|
203
|
+
HANDLE handle;
|
|
204
|
+
|
|
205
|
+
if (fd == -1) {
|
|
206
|
+
*dup = INVALID_HANDLE_VALUE;
|
|
207
|
+
uv__set_artificial_error(loop, UV_EBADF);
|
|
208
|
+
return -1;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
handle = (HANDLE)_get_osfhandle(fd);
|
|
212
|
+
return uv__duplicate_handle(loop, handle, dup);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
static int uv__create_nul_handle(uv_loop_t* loop, HANDLE* handle_ptr,
|
|
217
|
+
DWORD access) {
|
|
218
|
+
HANDLE handle;
|
|
219
|
+
SECURITY_ATTRIBUTES sa;
|
|
220
|
+
|
|
221
|
+
sa.nLength = sizeof sa;
|
|
222
|
+
sa.lpSecurityDescriptor = NULL;
|
|
223
|
+
sa.bInheritHandle = TRUE;
|
|
224
|
+
|
|
225
|
+
handle = CreateFileW(L"NUL",
|
|
226
|
+
access,
|
|
227
|
+
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
228
|
+
&sa,
|
|
229
|
+
OPEN_EXISTING,
|
|
230
|
+
0,
|
|
231
|
+
NULL);
|
|
232
|
+
if (handle == INVALID_HANDLE_VALUE) {
|
|
233
|
+
uv__set_sys_error(loop, GetLastError());
|
|
234
|
+
return -1;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
*handle_ptr = handle;
|
|
238
|
+
return 0;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
int uv__stdio_create(uv_loop_t* loop, uv_process_options_t* options,
|
|
243
|
+
BYTE** buffer_ptr) {
|
|
244
|
+
BYTE* buffer;
|
|
245
|
+
int count, i;
|
|
246
|
+
|
|
247
|
+
count = options->stdio_count;
|
|
248
|
+
|
|
249
|
+
if (count < 0 || count > 255) {
|
|
250
|
+
/* Only support FDs 0-255 */
|
|
251
|
+
uv__set_artificial_error(loop, UV_ENOTSUP);
|
|
252
|
+
return -1;
|
|
253
|
+
} else if (count < 3) {
|
|
254
|
+
/* There should always be at least 3 stdio handles. */
|
|
255
|
+
count = 3;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/* Allocate the child stdio buffer */
|
|
259
|
+
buffer = malloc(CHILD_STDIO_SIZE(count));
|
|
260
|
+
if (buffer == NULL) {
|
|
261
|
+
uv__set_artificial_error(loop, UV_ENOMEM);
|
|
262
|
+
return -1;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/* Prepopulate the buffer with INVALID_HANDLE_VALUE handles so we can */
|
|
266
|
+
/* clean up on failure. */
|
|
267
|
+
CHILD_STDIO_COUNT(buffer) = count;
|
|
268
|
+
for (i = 0; i < count; i++) {
|
|
269
|
+
CHILD_STDIO_CRT_FLAGS(buffer, i) = 0;
|
|
270
|
+
CHILD_STDIO_HANDLE(buffer, i) = INVALID_HANDLE_VALUE;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
for (i = 0; i < count; i++) {
|
|
274
|
+
uv_stdio_container_t fdopt;
|
|
275
|
+
if (i < options->stdio_count) {
|
|
276
|
+
fdopt = options->stdio[i];
|
|
277
|
+
} else {
|
|
278
|
+
fdopt.flags = UV_IGNORE;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
switch (fdopt.flags & (UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD |
|
|
282
|
+
UV_INHERIT_STREAM)) {
|
|
283
|
+
case UV_IGNORE:
|
|
284
|
+
/* Starting a process with no stdin/stout/stderr can confuse it. */
|
|
285
|
+
/* So no matter what the user specified, we make sure the first */
|
|
286
|
+
/* three FDs are always open in their typical modes, e.g. stdin */
|
|
287
|
+
/* be readable and stdout/err should be writable. For FDs > 2, don't */
|
|
288
|
+
/* do anything - all handles in the stdio buffer are initialized with */
|
|
289
|
+
/* INVALID_HANDLE_VALUE, which should be okay. */
|
|
290
|
+
if (i <= 2) {
|
|
291
|
+
DWORD access = (i == 0) ? FILE_GENERIC_READ :
|
|
292
|
+
FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES;
|
|
293
|
+
if (uv__create_nul_handle(loop,
|
|
294
|
+
&CHILD_STDIO_HANDLE(buffer, i),
|
|
295
|
+
access) < 0) {
|
|
296
|
+
goto error;
|
|
297
|
+
}
|
|
298
|
+
CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV;
|
|
299
|
+
}
|
|
300
|
+
break;
|
|
301
|
+
|
|
302
|
+
case UV_CREATE_PIPE: {
|
|
303
|
+
/* Create a pair of two connected pipe ends; one end is turned into */
|
|
304
|
+
/* an uv_pipe_t for use by the parent. The other one is given to */
|
|
305
|
+
/* the child. */
|
|
306
|
+
uv_pipe_t* parent_pipe = (uv_pipe_t*) fdopt.data.stream;
|
|
307
|
+
HANDLE child_pipe;
|
|
308
|
+
|
|
309
|
+
/* Create a new, connected pipe pair. stdio[i].stream should point */
|
|
310
|
+
/* to an uninitialized, but not connected pipe handle. */
|
|
311
|
+
assert(fdopt.data.stream->type == UV_NAMED_PIPE);
|
|
312
|
+
assert(!(fdopt.data.stream->flags & UV_HANDLE_CONNECTION));
|
|
313
|
+
assert(!(fdopt.data.stream->flags & UV_HANDLE_PIPESERVER));
|
|
314
|
+
|
|
315
|
+
if (uv__create_stdio_pipe_pair(loop,
|
|
316
|
+
parent_pipe,
|
|
317
|
+
&child_pipe,
|
|
318
|
+
fdopt.flags) < 0) {
|
|
319
|
+
goto error;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
CHILD_STDIO_HANDLE(buffer, i) = child_pipe;
|
|
323
|
+
CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FPIPE;
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
case UV_INHERIT_FD: {
|
|
328
|
+
/* Inherit a raw FD. */
|
|
329
|
+
HANDLE child_handle;
|
|
330
|
+
|
|
331
|
+
/* Make an inheritable duplicate of the handle. */
|
|
332
|
+
if (uv__duplicate_fd(loop, fdopt.data.fd, &child_handle) < 0) {
|
|
333
|
+
goto error;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/* Figure out what the type is. */
|
|
337
|
+
switch (GetFileType(child_handle)) {
|
|
338
|
+
case FILE_TYPE_DISK:
|
|
339
|
+
CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN;
|
|
340
|
+
break;
|
|
341
|
+
|
|
342
|
+
case FILE_TYPE_PIPE:
|
|
343
|
+
CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FPIPE;
|
|
344
|
+
|
|
345
|
+
case FILE_TYPE_CHAR:
|
|
346
|
+
case FILE_TYPE_REMOTE:
|
|
347
|
+
CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV;
|
|
348
|
+
break;
|
|
349
|
+
|
|
350
|
+
case FILE_TYPE_UNKNOWN:
|
|
351
|
+
if (GetLastError != 0) {
|
|
352
|
+
uv__set_sys_error(loop, GetLastError());
|
|
353
|
+
CloseHandle(child_handle);
|
|
354
|
+
goto error;
|
|
355
|
+
}
|
|
356
|
+
CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV;
|
|
357
|
+
break;
|
|
358
|
+
|
|
359
|
+
default:
|
|
360
|
+
assert(0);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
CHILD_STDIO_HANDLE(buffer, i) = child_handle;
|
|
364
|
+
break;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
case UV_INHERIT_STREAM: {
|
|
368
|
+
/* Use an existing stream as the stdio handle for the child. */
|
|
369
|
+
HANDLE stream_handle, child_handle;
|
|
370
|
+
unsigned char crt_flags;
|
|
371
|
+
uv_stream_t* stream = fdopt.data.stream;
|
|
372
|
+
|
|
373
|
+
/* Leech the handle out of the stream. */
|
|
374
|
+
if (stream->type == UV_TTY) {
|
|
375
|
+
stream_handle = ((uv_tty_t*) stream)->handle;
|
|
376
|
+
crt_flags = FOPEN | FDEV;
|
|
377
|
+
} else if (stream->type == UV_NAMED_PIPE &&
|
|
378
|
+
stream->flags & UV_HANDLE_CONNECTED) {
|
|
379
|
+
stream_handle = ((uv_pipe_t*) stream)->handle;
|
|
380
|
+
crt_flags = FOPEN | FPIPE;
|
|
381
|
+
} else {
|
|
382
|
+
stream_handle = INVALID_HANDLE_VALUE;
|
|
383
|
+
crt_flags = 0;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
if (stream_handle == NULL ||
|
|
387
|
+
stream_handle == INVALID_HANDLE_VALUE) {
|
|
388
|
+
/* The handle is already closed, or not yet created, or the */
|
|
389
|
+
/* stream type is not supported. */
|
|
390
|
+
uv__set_artificial_error(loop, UV_ENOTSUP);
|
|
391
|
+
goto error;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/* Make an inheritable copy of the handle. */
|
|
395
|
+
if (uv__duplicate_handle(loop,
|
|
396
|
+
stream_handle,
|
|
397
|
+
&child_handle) < 0) {
|
|
398
|
+
goto error;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
CHILD_STDIO_HANDLE(buffer, i) = child_handle;
|
|
402
|
+
CHILD_STDIO_CRT_FLAGS(buffer, i) = crt_flags;
|
|
403
|
+
break;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
default:
|
|
407
|
+
assert(0);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
*buffer_ptr = buffer;
|
|
412
|
+
return 0;
|
|
413
|
+
|
|
414
|
+
error:
|
|
415
|
+
uv__stdio_destroy(buffer);
|
|
416
|
+
return -1;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
void uv__stdio_destroy(BYTE* buffer) {
|
|
421
|
+
int i, count;
|
|
422
|
+
|
|
423
|
+
count = CHILD_STDIO_COUNT(buffer);
|
|
424
|
+
for (i = 0; i < count; i++) {
|
|
425
|
+
HANDLE handle = CHILD_STDIO_HANDLE(buffer, i);
|
|
426
|
+
if (handle != INVALID_HANDLE_VALUE) {
|
|
427
|
+
CloseHandle(handle);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
free(buffer);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
void uv__stdio_noinherit(BYTE* buffer) {
|
|
436
|
+
int i, count;
|
|
437
|
+
|
|
438
|
+
count = CHILD_STDIO_COUNT(buffer);
|
|
439
|
+
for (i = 0; i < count; i++) {
|
|
440
|
+
HANDLE handle = CHILD_STDIO_HANDLE(buffer, i);
|
|
441
|
+
if (handle != INVALID_HANDLE_VALUE) {
|
|
442
|
+
SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
int uv__stdio_verify(BYTE* buffer, WORD size) {
|
|
449
|
+
unsigned int count;
|
|
450
|
+
|
|
451
|
+
/* Check the buffer pointer. */
|
|
452
|
+
if (buffer == NULL)
|
|
453
|
+
return 0;
|
|
454
|
+
|
|
455
|
+
/* Verify that the buffer is at least big enough to hold the count. */
|
|
456
|
+
if (size < CHILD_STDIO_SIZE(0))
|
|
457
|
+
return 0;
|
|
458
|
+
|
|
459
|
+
/* Verify if the count is within range. */
|
|
460
|
+
count = CHILD_STDIO_COUNT(buffer);
|
|
461
|
+
if (count > 256)
|
|
462
|
+
return 0;
|
|
463
|
+
|
|
464
|
+
/* Verify that the buffer size is big enough to hold info for N FDs. */
|
|
465
|
+
if (size < CHILD_STDIO_SIZE(count))
|
|
466
|
+
return 0;
|
|
467
|
+
|
|
468
|
+
return 1;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
WORD uv__stdio_size(BYTE* buffer) {
|
|
473
|
+
return (WORD) CHILD_STDIO_SIZE(CHILD_STDIO_COUNT((buffer)));
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
HANDLE uv__stdio_handle(BYTE* buffer, int fd) {
|
|
478
|
+
return CHILD_STDIO_HANDLE(buffer, fd);
|
|
479
|
+
}
|