summaryrefslogtreecommitdiff
path: root/deps
diff options
context:
space:
mode:
authorFedor Indutny <fedor@indutny.com>2014-08-07 15:03:17 +0400
committerFedor Indutny <fedor@indutny.com>2014-08-07 15:03:17 +0400
commite49429ebd2fe0b7c24e2ee533311dd97f6febd1f (patch)
treed958c7f24638bc13ce3f17211e914828bad2fc85 /deps
parentaa3b4b4d106415b3afbc31df0db2476a04c997f1 (diff)
downloadnode-new-e49429ebd2fe0b7c24e2ee533311dd97f6febd1f.tar.gz
deps: update libuv to v0.11.28
Diffstat (limited to 'deps')
-rw-r--r--deps/uv/.mailmap4
-rw-r--r--deps/uv/AUTHORS9
-rw-r--r--deps/uv/ChangeLog91
-rw-r--r--deps/uv/Makefile.am12
-rw-r--r--deps/uv/Makefile.mingw3
-rw-r--r--deps/uv/README.md7
-rw-r--r--deps/uv/configure.ac2
-rwxr-xr-xdeps/uv/gyp_uv.py12
-rw-r--r--deps/uv/img/banner.pngbin0 -> 44102 bytes
-rw-r--r--deps/uv/img/logos.svg152
-rw-r--r--deps/uv/include/uv-aix.h32
-rw-r--r--deps/uv/include/uv-threadpool.h37
-rw-r--r--deps/uv/include/uv-unix.h13
-rw-r--r--deps/uv/include/uv-version.h2
-rw-r--r--deps/uv/include/uv-win.h22
-rw-r--r--deps/uv/include/uv.h414
-rw-r--r--deps/uv/src/threadpool.c (renamed from deps/uv/src/unix/threadpool.c)77
-rw-r--r--deps/uv/src/unix/aix.c878
-rw-r--r--deps/uv/src/unix/core.c7
-rw-r--r--deps/uv/src/unix/fs.c30
-rw-r--r--deps/uv/src/unix/internal.h15
-rw-r--r--deps/uv/src/unix/loop.c4
-rw-r--r--deps/uv/src/unix/openbsd.c30
-rw-r--r--deps/uv/src/unix/stream.c65
-rw-r--r--deps/uv/src/unix/udp.c213
-rw-r--r--deps/uv/src/uv-common.c33
-rw-r--r--deps/uv/src/uv-common.h15
-rw-r--r--deps/uv/src/win/core.c161
-rw-r--r--deps/uv/src/win/error.c1
-rw-r--r--deps/uv/src/win/fs.c177
-rw-r--r--deps/uv/src/win/getaddrinfo.c63
-rw-r--r--deps/uv/src/win/getnameinfo.c61
-rw-r--r--deps/uv/src/win/internal.h35
-rw-r--r--deps/uv/src/win/pipe.c64
-rw-r--r--deps/uv/src/win/process.c280
-rw-r--r--deps/uv/src/win/req-inl.h16
-rw-r--r--deps/uv/src/win/stream-inl.h11
-rw-r--r--deps/uv/src/win/tcp.c65
-rw-r--r--deps/uv/src/win/threadpool.c81
-rw-r--r--deps/uv/src/win/timer.c50
-rw-r--r--deps/uv/src/win/tty.c4
-rw-r--r--deps/uv/src/win/udp.c27
-rw-r--r--deps/uv/test/run-tests.c5
-rw-r--r--deps/uv/test/test-barrier.c29
-rw-r--r--deps/uv/test/test-fs.c67
-rw-r--r--deps/uv/test/test-getsockname.c3
-rw-r--r--deps/uv/test/test-ipc.c125
-rw-r--r--deps/uv/test/test-list.h19
-rw-r--r--deps/uv/test/test-loop-time.c29
-rw-r--r--deps/uv/test/test-spawn.c151
-rw-r--r--deps/uv/test/test-tcp-close-accept.c5
-rw-r--r--deps/uv/test/test-tcp-try-write.c12
-rw-r--r--deps/uv/test/test-tcp-write-queue-order.c137
-rw-r--r--deps/uv/test/test-udp-multicast-interface.c3
-rw-r--r--deps/uv/test/test-udp-open.c2
-rw-r--r--deps/uv/test/test-udp-send-and-recv.c3
-rw-r--r--deps/uv/test/test-udp-send-immediate.c148
-rw-r--r--deps/uv/test/test-udp-try-send.c133
-rw-r--r--deps/uv/test/test-watcher-cross-stop.c2
-rw-r--r--deps/uv/uv.gyp23
60 files changed, 3243 insertions, 928 deletions
diff --git a/deps/uv/.mailmap b/deps/uv/.mailmap
index 89c1adec4d..2ca07c8381 100644
--- a/deps/uv/.mailmap
+++ b/deps/uv/.mailmap
@@ -1,3 +1,4 @@
+Aaron Bieber <qbit@deftly.net> <deftly@gmail.com>
Alan Gutierrez <alan@prettyrobots.com> <alan@blogometer.com>
Andrius Bentkus <andrius.bentkus@gmail.com> <toxedvirus@gmail.com>
Bert Belder <bertbelder@gmail.com> <info@2bs.nl>
@@ -5,6 +6,7 @@ Bert Belder <bertbelder@gmail.com> <user@ChrUbuntu.(none)>
Brandon Philips <brandon.philips@rackspace.com> <brandon@ifup.org>
Brian White <mscdex@mscdex.net>
Brian White <mscdex@mscdex.net> <mscdex@gmail.com>
+Caleb James DeLisle <cjd@hyperboria.ca> <cjd@cjdns.fr>
Christoph Iserlohn <christoph.iserlohn@innoq.com>
Fedor Indutny <fedor.indutny@gmail.com> <fedor@indutny.com>
Frank Denis <github@pureftpd.org>
@@ -15,6 +17,8 @@ Keno Fischer <kenof@stanford.edu> <kfischer@college.harvard.edu>
Maciej MaƂecki <maciej.malecki@notimplemented.org> <me@mmalecki.com>
Marc Schlaich <marc.schlaich@googlemail.com> <marc.schlaich@gmail.com>
Rasmus Christian Pedersen <ruysch@outlook.com>
+Rasmus Christian Pedersen <ruysch@outlook.com>
+Rasmus Christian Pedersen <ruysch@outlook.com>
Rasmus Christian Pedersen <zerhacken@yahoo.com> <ruysch@outlook.com>
Rasmus Pedersen <ruysch@outlook.com> <zerhacken@yahoo.com>
Robert Mustacchi <rm@joyent.com> <rm@fingolfin.org>
diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS
index e3de576233..19f911f113 100644
--- a/deps/uv/AUTHORS
+++ b/deps/uv/AUTHORS
@@ -146,3 +146,12 @@ HungMingWu <u9089000@gmail.com>
Jay Satiro <raysatiro@yahoo.com>
Leith Bade <leith@leithalweapon.geek.nz>
Peter Atashian <retep998@gmail.com>
+Tim Cooper <tim.cooper@layeh.com>
+Caleb James DeLisle <cjd@hyperboria.ca>
+Jameson Nash <vtjnash@gmail.com>
+Graham Lee <ghmlee@ghmlee.com>
+Andrew Low <Andrew_Low@ca.ibm.com>
+Pavel Platto <hinidu@gmail.com>
+Tony Kelman <tony@kelman.net>
+John Firebaugh <john.firebaugh@gmail.com>
+lilohuang <lilohuang@hotmail.com>
diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog
index 50d39893a2..db13f188c6 100644
--- a/deps/uv/ChangeLog
+++ b/deps/uv/ChangeLog
@@ -1,4 +1,93 @@
-2014.06.28, Version 0.11.26 (Unstable)
+2014.08.08, Version 0.11.28 (Unstable)
+
+Changes since version 0.11.27:
+
+* unix, windows: const-ify handle in uv_udp_getsockname (Rasmus Pedersen)
+
+* windows: use UV_ECANCELED for aborted TCP writes (SaĂșl Ibarra CorretgĂ©)
+
+* windows: add more required environment variables (Jameson Nash)
+
+* windows: sort environment variables before calling CreateProcess (Jameson
+ Nash)
+
+* unix, windows: move uv_loop_close out of assert (John Firebaugh)
+
+* windows: fix buffer overflow on uv__getnameinfo_work() (lilohuang)
+
+* windows: add uv_backend_timeout (Jameson Nash)
+
+* test: disable tcp_close_accept on Windows (SaĂșl Ibarra CorretgĂ©)
+
+* windows: read the PATH env var of the child (Alex Crichton)
+
+* include: avoid using C++ 'template' reserved word (Iñaki Baz Castillo)
+
+* include: fix version number (SaĂșl Ibarra CorretgĂ©)
+
+
+2014.07.32, Version 0.11.27 (Unstable), ffe24f955032d060968ea0289af365006afed55e
+
+Changes since version 0.11.26:
+
+* unix, windows: use the same threadpool implementation (SaĂșl Ibarra CorretgĂ©)
+
+* unix: use struct sockaddr_storage for target UDP addr (SaĂșl Ibarra CorretgĂ©)
+
+* doc: add documentation to uv_udp_start_recv (Andrius Bentkus)
+
+* common: use common uv__count_bufs code (Andrius Bentkus)
+
+* unix, win: add send_queue_size and send_queue_count to uv_udp_t (Andrius
+ Bentkus)
+
+* unix, win: add uv_udp_try_send (Andrius Bentkus)
+
+* unix: return UV_EAGAIN if uv_try_write cannot write any data (SaĂșl Ibarra
+ Corretgé)
+
+* windows: fix compatibility with cygwin pipes (Jameson Nash)
+
+* windows: count queued bytes even if request completed immediately (SaĂșl
+ Ibarra Corretgé)
+
+* windows: disable CRT debug handler on MinGW32 (SaĂșl Ibarra CorretgĂ©)
+
+* windows: map ERROR_INVALID_DRIVE to UV_ENOENT (SaĂșl Ibarra CorretgĂ©)
+
+* unix: try to write immediately in uv_udp_send (SaĂșl Ibarra CorretgĂ©)
+
+* unix: remove incorrect assert (SaĂșl Ibarra CorretgĂ©)
+
+* openbsd: avoid requiring privileges for uv_resident_set_memory (Aaron Bieber)
+
+* unix: guarantee write queue cb execution order in streams (Andrius Bentkus)
+
+* img: add logo files (SaĂșl Ibarra CorretgĂ©)
+
+* aix: improve AIX compatibility (Andrew Low)
+
+* windows: return bind error immediately when implicitly binding (SaĂșl Ibarra
+ Corretgé)
+
+* windows: don't use atexit for cleaning up the threadpool (SaĂșl Ibarra
+ Corretgé)
+
+* windows: destroy work queue elements when colsing a loop (SaĂșl Ibarra
+ Corretgé)
+
+* unix, windows: add uv_fs_mkdtemp (Pavel Platto)
+
+* build: handle platforms without multiprocessing.synchronize (SaĂșl Ibarra
+ Corretgé)
+
+* windows: change GENERIC_ALL to GENERIC_WRITE in fs__create_junction (Tony
+ Kelman)
+
+* windows: relay TCP bind errors via ipc (Alexis Campailla)
+
+
+2014.06.28, Version 0.11.26 (Unstable), 115281a1058c4034d5c5ccedacb667fe3f6327ea
Changes since version 0.11.25:
diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am
index ebcd8db2e2..861b632bbf 100644
--- a/deps/uv/Makefile.am
+++ b/deps/uv/Makefile.am
@@ -17,7 +17,7 @@ ACLOCAL_AMFLAGS = -I m4
AM_CPPFLAGS = -I$(top_srcdir)/include \
-I$(top_srcdir)/src
-include_HEADERS=include/uv.h include/uv-errno.h include/uv-version.h
+include_HEADERS=include/uv.h include/uv-errno.h include/uv-threadpool.h include/uv-version.h
CLEANFILES =
@@ -28,6 +28,7 @@ libuv_la_SOURCES = src/fs-poll.c \
src/heap-inl.h \
src/inet.c \
src/queue.h \
+ src/threadpool.c \
src/uv-common.c \
src/uv-common.h \
src/version.c
@@ -67,7 +68,6 @@ libuv_la_SOURCES += src/win/async.c \
src/win/stream-inl.h \
src/win/tcp.c \
src/win/thread.c \
- src/win/threadpool.c \
src/win/timer.c \
src/win/tty.c \
src/win/udp.c \
@@ -99,7 +99,6 @@ libuv_la_SOURCES += src/unix/async.c \
src/unix/stream.c \
src/unix/tcp.c \
src/unix/thread.c \
- src/unix/threadpool.c \
src/unix/timer.c \
src/unix/tty.c \
src/unix/udp.c
@@ -197,6 +196,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-tcp-write-to-half-open-connection.c \
test/test-tcp-writealot.c \
test/test-tcp-try-write.c \
+ test/test-tcp-write-queue-order.c \
test/test-thread.c \
test/test-threadpool-cancel.c \
test/test-threadpool.c \
@@ -215,6 +215,8 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-udp-open.c \
test/test-udp-options.c \
test/test-udp-send-and-recv.c \
+ test/test-udp-send-immediate.c \
+ test/test-udp-try-send.c \
test/test-walk-handles.c \
test/test-watcher-cross-stop.c
test_run_tests_LDADD = libuv.la
@@ -228,7 +230,7 @@ test_run_tests_SOURCES += test/runner-unix.c \
endif
if AIX
-test_run_tests_CFLAGS += -D_ALL_SOURCE -D_XOPEN_SOURCE=500
+test_run_tests_CFLAGS += -D_ALL_SOURCE -D_XOPEN_SOURCE=500 -D_LINUX_SOURCE_COMPAT
endif
if SUNOS
@@ -237,7 +239,7 @@ endif
if AIX
-libuv_la_CFLAGS += -D_ALL_SOURCE -D_XOPEN_SOURCE=500
+libuv_la_CFLAGS += -D_ALL_SOURCE -D_XOPEN_SOURCE=500 -D_LINUX_SOURCE_COMPAT
libuv_la_SOURCES += src/unix/aix.c
endif
diff --git a/deps/uv/Makefile.mingw b/deps/uv/Makefile.mingw
index a0b7cc941f..156f15dab1 100644
--- a/deps/uv/Makefile.mingw
+++ b/deps/uv/Makefile.mingw
@@ -26,6 +26,7 @@ CFLAGS += -Wall \
INCLUDES = include/stdint-msvc2008.h \
include/tree.h \
include/uv-errno.h \
+ include/uv-threadpool.h \
include/uv-version.h \
include/uv-win.h \
include/uv.h \
@@ -42,6 +43,7 @@ INCLUDES = include/stdint-msvc2008.h \
OBJS = src/fs-poll.o \
src/inet.o \
+ src/threadpool.o \
src/uv-common.o \
src/version.o \
src/win/async.o \
@@ -63,7 +65,6 @@ OBJS = src/fs-poll.o \
src/win/stream.o \
src/win/tcp.o \
src/win/thread.o \
- src/win/threadpool.o \
src/win/timer.o \
src/win/tty.o \
src/win/udp.o \
diff --git a/deps/uv/README.md b/deps/uv/README.md
index e0e73591d5..364cf695c4 100644
--- a/deps/uv/README.md
+++ b/deps/uv/README.md
@@ -1,10 +1,12 @@
-# libuv
+![libuv][libuv_banner]
+
+## Overview
libuv is a multi-platform support library with a focus on asynchronous I/O. It
was primarily developed for use by [Node.js](http://nodejs.org), but it's also
used by Mozilla's [Rust language](http://www.rust-lang.org/),
[Luvit](http://luvit.io/), [Julia](http://julialang.org/),
-[pyuv](https://crate.io/packages/pyuv/), and [others](https://github.com/joyent/libuv/wiki/Projects-that-use-libuv).
+[pyuv](https://github.com/saghul/pyuv), and [others](https://github.com/joyent/libuv/wiki/Projects-that-use-libuv).
## Feature highlights
@@ -141,3 +143,4 @@ See the [guidelines for contributing][].
[Python]: https://www.python.org/downloads/
[Visual Studio Express 2010]: http://www.microsoft.com/visualstudio/eng/products/visual-studio-2010-express
[guidelines for contributing]: https://github.com/joyent/libuv/blob/master/CONTRIBUTING.md
+[libuv_banner]: https://raw.githubusercontent.com/joyent/libuv/master/img/banner.png
diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac
index 0423c8cea8..ac789524b5 100644
--- a/deps/uv/configure.ac
+++ b/deps/uv/configure.ac
@@ -13,7 +13,7 @@
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
AC_PREREQ(2.57)
-AC_INIT([libuv], [0.11.26], [https://github.com/joyent/libuv/issues])
+AC_INIT([libuv], [0.11.28], [https://github.com/joyent/libuv/issues])
AC_CONFIG_MACRO_DIR([m4])
m4_include([m4/libuv-extra-automake-flags.m4])
m4_include([m4/as_case.m4])
diff --git a/deps/uv/gyp_uv.py b/deps/uv/gyp_uv.py
index f0c59d0786..f5afc6da2d 100755
--- a/deps/uv/gyp_uv.py
+++ b/deps/uv/gyp_uv.py
@@ -6,6 +6,13 @@ import os
import subprocess
import sys
+try:
+ import multiprocessing.synchronize
+ gyp_parallel_support = True
+except ImportError:
+ gyp_parallel_support = False
+
+
CC = os.environ.get('CC', 'cc')
script_dir = os.path.dirname(__file__)
uv_root = os.path.normpath(script_dir)
@@ -94,6 +101,11 @@ if __name__ == '__main__':
if not any(a.startswith('-Dcomponent=') for a in args):
args.append('-Dcomponent=static_library')
+ # Some platforms (OpenBSD for example) don't have multiprocessing.synchronize
+ # so gyp must be run with --no-parallel
+ if not gyp_parallel_support:
+ args.append('--no-parallel')
+
gyp_args = list(args)
print gyp_args
run_gyp(gyp_args)
diff --git a/deps/uv/img/banner.png b/deps/uv/img/banner.png
new file mode 100644
index 0000000000..7187daa2e5
--- /dev/null
+++ b/deps/uv/img/banner.png
Binary files differ
diff --git a/deps/uv/img/logos.svg b/deps/uv/img/logos.svg
new file mode 100644
index 0000000000..d6185f8b19
--- /dev/null
+++ b/deps/uv/img/logos.svg
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="792pt"
+ height="612pt"
+ id="svg3069"
+ version="1.1"
+ inkscape:version="0.48.4 r9939"
+ sodipodi:docname="New document 3">
+ <defs
+ id="defs3071">
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath70">
+ <path
+ inkscape:connector-curvature="0"
+ d="M 0,5952.81 0,0 l 8418.9,0 0,5952.81 -8418.9,0 z"
+ id="path72" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath70-6">
+ <path
+ inkscape:connector-curvature="0"
+ d="M 0,5952.81 0,0 l 8418.9,0 0,5952.81 -8418.9,0 z"
+ id="path72-5" />
+ </clipPath>
+ </defs>
+ <sodipodi:namedview
+ inkscape:document-units="in"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.43415836"
+ inkscape:cx="508.42646"
+ inkscape:cy="359.27024"
+ inkscape:current-layer="layer1"
+ id="namedview3073"
+ showgrid="false"
+ inkscape:window-width="1010"
+ inkscape:window-height="702"
+ inkscape:window-x="441"
+ inkscape:window-y="267"
+ inkscape:window-maximized="0" />
+ <metadata
+ id="metadata3075">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <g
+ transform="matrix(0.2288071,0,0,-0.2288071,130.84779,1169.4436)"
+ id="g66">
+ <g
+ id="g68"
+ clip-path="url(#clipPath70)">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 3274.33,2372.2 c -42.27,-8.61 -87.28,-37.29 -122.12,-43.75 -77.01,-14.25 -122.4,-0.53 -81.76,16.27 59.03,24.45 253.75,30.55 274.1,175.05 20.36,144.5 6.1,209.66 -4.07,246.29 -4.87,17.57 -15.81,43.49 -25.9,65.76 -2.85,15.73 -6.59,29.07 -9.86,38.57 -1.82,4.29 -3.65,9.81 -5.46,16.78 0,0 -2.54,17.81 5.6,35.1 7.2,15.34 31.95,48.62 33.62,80.79 0.03,1.95 0.11,3.9 0.08,5.85 -0.1,2.18 -0.28,4.33 -0.63,6.48 l -0.18,1.9 c -3.17,18.05 -13.53,30.62 -27.6,39.98 -9.06,6.02 -21.4,7.92 -28.17,16.51 5.4,17.01 22.63,23.06 29.82,36.95 4.48,12.34 0.82,25.3 -5.99,37.08 -13.13,14.72 -38.92,27.49 -62.07,36.15 -28.97,10.87 -58.44,19.45 -78.35,35.06 -21.03,11.19 -35.17,32.83 -22.26,61.45 3.35,7.44 4.85,14.93 4.75,22.04 l -0.09,2.09 c -0.03,1.45 -0.23,2.76 -0.41,4.1 -0.15,1.04 -0.32,2.06 -0.55,3.08 l -0.47,1.77 -0.56,2.02 c -5.3,17.86 -33.44,22.88 -43.47,23.78 -22.72,2.04 -37.4,8.2 -49.46,12.01 9.7,-5.04 19.46,-11.78 31.9,-16.79 7.87,-3.21 19.17,-5.12 28.68,-8.29 l 0.09,0.02 c 0,0 17.55,-3.56 22.38,-15.78 4.84,-12.2 2.03,-22.9 0,-29.75 l -0.74,-1.99 c -1.75,-5.35 -3.72,-10.51 -4.13,-15.84 -1.65,-21.04 11.26,-32 18.12,-49.6 12.35,-11.73 29.93,-23.88 54.32,-34.88 21.92,-9.9 48.15,-15.89 64.4,-25.7 9.41,-5.68 26.55,-19.41 26.16,-29.4 -0.3,-7.65 -14.43,-18.09 -20.12,-25.7 -4.07,-5.42 -6.09,-12.62 -9.73,-17.74 -3.17,-5 -7.24,-8.22 -11.92,-8.22 -6.1,0 -20.01,-2.36 -10.86,-3.04 9.16,-0.68 32.91,-11.87 32.91,-11.87 l -0.02,-0.03 c 32.1,-13.28 53.67,-37.88 41.87,-72.96 -9.88,-29.39 -32.61,-53.97 -34.2,-86.3 -1.7,-34.4 14.07,-62.72 16.09,-90 3.41,-45.9 -3.18,-77.51 -12.06,-112.01 -4.17,-16.14 -6.39,-32.04 -10.06,-47.74 -15.68,-66.87 -56.09,-95.84 -110.68,-126.73 -23.67,-13.39 -49.07,-38.07 -74.45,-45.9 -4.09,-1.26 -10.39,0.66 -14.11,0 -23.38,-4.22 -44.42,-15.81 -68.41,-20.19 -22.59,-4.17 -46.27,-2.17 -73.08,-8.96 -13.6,-4.85 -31.03,-12.11 -41.21,-16.43 -15.74,-7.17 -31.16,-14.63 -46.55,-22.15 l -51.11,-29.2 c 0,0 -28.48,-16.49 3.06,-4.28 25.38,9.83 112.62,53.25 76.08,27.75 -25.2,-12.66 -38.87,-30.64 -61.16,-45.98 0,0 -74.99,-37.19 -86.24,-47.57 -12.37,-11.42 -27.49,-5.1 -37.41,-16.3 -11.65,-13.13 -25.94,-21.01 -36.13,-24.41 -10.17,-3.42 -21.7,-25.78 -37.31,-37.31 -15.61,-11.54 -49.52,-8.15 -79.38,-21.04 -29.85,-12.89 -60.79,-13.06 -60.79,-13.06 -2.96,-0.28 -5.83,-0.46 -8.58,-0.53 -1.18,-0.03 -2.27,-0.02 -3.4,-0.02 -17.46,-0.09 -30.81,3.32 -41.04,7.08 -12.47,4.58 -17.05,2.28 -14.25,0.76 2.8,-1.51 10.92,-9.11 10.92,-9.11 -34.83,0.04 -44.33,23.18 -60.37,40.37 7.29,1.04 28.08,-4.04 17.52,2.08 -20.85,9.97 -61.01,10.69 -61.8,34.67 -0.6,18.81 8.06,14.69 8.06,14.69 14.61,-25.44 59.69,-27.93 92.57,-27.57 61.24,0.74 102.68,34.32 142.82,53.32 13.01,7.82 28.21,18.1 28.21,18.1 l -0.08,-0.3 c 12.67,8.25 25.48,16.25 36.31,26.22 18.9,17.37 31.67,40.04 48.31,59.27 1.93,3.27 5.99,7.26 10.81,11.28 4.69,4.4 9.73,8.5 15.34,12.09 l 0.21,-0.45 2.18,1.46 -0.39,0.82 c 40.39,22.9 78.03,48.25 109.79,79.02 l 0.21,0.36 c 4.56,4.13 28.46,30.81 40,43.76 13.61,18.15 23.42,41.08 29.11,64.18 2.05,8.36 0.75,18.51 4.01,27.56 5.07,14.03 17.81,26.51 26.17,40.39 8.65,14.43 14.37,30.14 20.12,45.9 25.17,69.17 54.28,124.25 108.66,161.6 26.2,18.01 58.02,29.63 76.46,56.95 -13.39,-13.59 -30.82,-23.5 -51.87,-30.09 -59.79,-19.7 -98.68,-70.15 -118.23,-102.2 -15.01,-26.98 -26.61,-57.04 -35.14,-89.93 -2.83,40.54 -12.84,72.15 -26.17,102.84 -11.85,27.29 -22.33,56.15 -44.27,73.46 0,0 -0.84,-0.06 -4.25,1.99 -3.39,2.02 56.57,3.53 56.57,3.53 10.49,-0.38 21.17,-1.89 31.99,-3.29 2.03,0.22 4.51,0.1 7.56,-0.43 32.96,-5.82 67.21,6.45 88.55,21.98 11.08,8.06 30.34,14.52 46.32,18.89 0.26,0.69 1.82,1.47 5.81,2.23 0,0 24.42,7.63 50.37,14.76 17.58,4.81 30.38,8.5 39.27,12.89 5.15,3.28 10.05,7.22 13.85,11.91 7.61,9.39 7.76,20.66 14.1,36.73 6.31,16.03 15.96,28.49 16.1,42.24 0.45,45.08 -42.25,80.98 -88.54,56.95 45.58,11.75 77.9,-10.49 72.44,-53.28 -6.74,-52.87 -86.39,-92.05 -134.83,-112.01 -19.2,-7.91 -41.68,-17.9 -64.38,-20.19 -32.74,-3.32 -62.41,3.67 -90.56,1.84 -36.1,-2.38 -60.11,-21.47 -90.55,-23.89 -26.16,-2.07 -22.61,15.61 -45.31,17.62 -4.7,2.68 -18.98,0 -33.18,0.74 -39.25,-10.37 -64.5,7.57 -96.58,22.04 -23.14,10.45 -47.82,19.96 -72.44,22.04 -61.81,5.24 -99.39,-3.35 -149.91,2.01 -14.25,1.51 -43.81,3.31 -57.85,8.57 -43.71,16.35 -77.17,10.42 -124.65,11.1 -34.54,0.5 -66.59,2.31 -88.15,-1.47 -5.88,-1.06 -11.84,-2.57 -18.12,-3.67 -46.27,-8.09 -116.76,-12.28 -114.69,-53.26 3.44,2.35 2.48,8.74 8.04,9.18 -0.2,-7.53 -0.39,-15.05 2.01,-20.21 -26.91,0.7 -42.78,19.28 -42.25,40.41 0.9,35.93 58.71,50.95 98.59,60.61 39.98,9.64 81.5,20.94 110.69,25.7 -69.91,-10.27 -143.86,-16.88 -197.22,-42.25 -0.75,2.76 -1.23,5.42 -1.55,7.98 -4.22,19.4 -13.43,49.15 -19.91,78.07 -7.46,33.24 4.06,91.59 4.06,91.59 l 0.29,-0.34 c 4.81,29.66 10.94,42.88 16.88,60.61 12.65,37.82 53.52,49.69 82.13,53.28 -24.12,-17.04 -39.54,-38.17 -49.29,-66.46 -1.2,-10.04 -2.14,-19.46 -2.84,-27.77 21.65,67.41 82.07,92.64 82.07,92.64 l 19.34,20.86 -0.25,-0.95 c 33.36,32.26 77.42,57.26 133.43,58.83 28.22,0.79 62.32,-6.64 62.23,-34.32 -0.04,-15.65 -12.28,-28.93 -28.97,-36.27 4.91,-0.97 9.4,-0.29 13.47,1.39 l 17.34,19.41 c 5.74,14.18 5.23,32.1 -4.44,42.9 25.52,21.82 65.26,-2.65 62.36,-31.6 7.47,6.3 12.03,18.2 6.89,27.64 34.34,20.18 53.56,-28.74 88.11,-17.31 -3.25,9.79 -19.89,7.81 -24.95,15.97 45.17,6.46 84.78,-9.42 130.08,-5.82 2.84,-2.47 5.91,-4.93 9.19,-7.36 -84.73,-9.38 -15.9,-9.33 -15.9,-9.33 10.85,0.99 36.92,2.81 47.06,1.01 16.58,-3 27.29,1.04 41.95,6.77 0.35,-0.64 1.82,-0.58 2.71,1.08 7.6,3 16.35,6.31 27.47,9.31 4.31,0.61 8.64,1.72 12.84,3.09 l 1.81,0.37 0.26,0.29 c 5.8,2.02 11.27,4.44 15.96,6.71 42.69,20.52 78.1,68.84 114.56,94.19 60.42,41.99 117.63,-9.88 159.69,-43.54 l -0.27,-0.39 c 10.55,-7.2 24.46,-16.08 39.61,-25.35 39.58,-17.23 91.79,-32.28 119.67,-59.84 22.31,-22.04 29.9,-50.42 39.49,-79.88 8.96,-27.47 26.34,-51.77 36.12,-82.6 1.88,1.58 2.99,3.96 3.63,6.8 -0.27,2.63 -0.7,5.41 0.08,7.13 l 0.53,-0.48 c -0.11,5.38 -1.3,11.69 -3.14,18.33 -8.29,16.88 -22.78,36.11 -21,51.15 0,0 51.42,-26.57 109.76,-52.96 20.09,-9.09 38.48,-24.08 54.53,-41.21 l 4.69,0.1 c -0.55,-1.2 -0.5,-2.93 -0.33,-4.76 28.36,-31.78 48.46,-69.63 55.45,-91.51 1.44,-4.49 3.07,-9.04 4.83,-13.57 l 0.01,-0.05 c 2.2,-5.71 4.57,-11.35 7.02,-16.78 l 0.05,0.08 c 1.03,-1.85 1.68,-3.66 2.37,-5.49 8.42,-18.22 16.69,-33.01 18.99,-37.06 7.41,-9.21 13.39,-21.04 19.78,-31.05 2.22,-24.89 3.41,-50.09 3.41,-75.56 0,-199.46 -69.36,-382.69 -185.2,-527 -6.7,-0.78 -15.83,-2.33 -27.9,-4.8 z m -52.92,-82.53 c -40.52,-13.23 -81.83,-38.11 -108.21,-40.61 -79.4,-7.5 -93.63,27.79 -30.19,33.61 23.94,2.2 59.29,4.91 87.52,18.29 41.64,19.78 84.29,38.98 112.76,53.23 -19.47,-22.6 -40.15,-44.11 -61.88,-64.52 z m -865.53,-3.85 c -6.73,-2.26 -6.73,1.07 -6.73,1.07 0,0 -12.2,17.42 -14.09,33.64 -1.91,16.07 2.23,30.38 6.26,32.5 4.07,2.2 4.95,-7.16 8.26,-18.88 3.33,-11.84 19.78,-36.13 19.78,-36.13 2.34,-5 -6.65,-9.95 -13.48,-12.2 z m 42.43,-7.43 c -7.73,-2.57 -7.72,1.26 -7.72,1.26 0,0 -13.94,19.78 -16.06,38.24 -2.14,18.26 2.66,34.52 7.3,36.95 4.67,2.51 5.67,-8.16 9.42,-21.52 3.76,-13.43 22.6,-41.09 22.6,-41.09 2.67,-5.68 -7.71,-11.25 -15.54,-13.84 z m 14.34,51.42 c -2.66,23.12 3.53,43.78 9.47,46.91 5.98,3.19 7.21,-10.35 11.96,-27.27 4.76,-17.04 28.77,-52.08 28.77,-52.08 3.4,-7.18 -9.92,-14.29 -19.94,-17.55 -9.92,-3.24 -9.89,1.54 -9.89,1.54 0,0 -17.72,25.08 -20.37,48.45 z m 344.3,264.59 c 4.16,3.72 8.54,-4.1 16.65,-12.97 8.18,-8.98 36.92,-23.11 36.92,-23.11 4.63,-3.42 -4.59,-11.97 -12.08,-17.13 -7.47,-5.16 -8.66,-2.13 -8.66,-2.13 0,0 -21.16,9.99 -29.17,23.65 -7.97,13.46 -7.84,27.91 -3.66,31.69 z m -68.15,-36.32 c 5.11,4.79 10.57,-5.35 20.77,-16.86 10.31,-11.78 46.52,-30.52 46.52,-30.52 5.9,-4.44 -5.63,-15.55 -14.96,-22.21 -9.36,-6.66 -10.92,-2.72 -10.92,-2.72 0,0 -26.46,13.4 -36.55,31.17 -9.99,17.53 -10,36.37 -4.86,41.14 z m -60.8,-81.74 c -9,18.83 -8.22,38.34 -3.02,43.06 5.25,4.73 10.2,-6.14 19.69,-18.82 9.63,-12.88 44.35,-34.41 44.35,-34.41 5.56,-5 -6.19,-15.86 -15.65,-22.26 -9.41,-6.35 -10.8,-2.21 -10.8,-2.21 0,0 -25.38,15.51 -34.57,34.64 z m -55.66,-46.52 c -7.53,19.87 -5.51,39.81 -0.21,44.23 5.4,4.43 9.44,-7.08 17.74,-20.66 8.43,-13.86 40.51,-38.43 40.51,-38.43 5.09,-5.51 -6.92,-15.77 -16.52,-21.57 -9.48,-5.72 -10.46,-1.32 -10.46,-1.32 0,0 -23.45,17.66 -31.06,37.75 z m -75.01,-121.98 c -9.98,-3.02 -9.89,1.61 -9.89,1.61 0,0 -16.92,24.38 -18.9,46.94 -1.96,22.39 4.85,42.34 10.86,45.31 6.07,3.02 6.94,-10.05 11.14,-26.43 4.3,-16.56 27.21,-50.59 27.21,-50.59 3.18,-6.96 -10.3,-13.73 -20.42,-16.84 z m 20.3,78.13 c -4.88,22.44 -0.13,43.46 5.88,47.35 6.06,3.95 8.61,-9.17 15.12,-25.14 6.57,-16.04 35.41,-47.57 35.41,-47.57 4.31,-6.67 -9.23,-15.5 -19.66,-20.14 -10.27,-4.55 -10.72,0.28 -10.72,0.28 0,0 -21.1,22.52 -26.03,45.22 z m 271.98,527.71 c 0,0 5.87,-0.99 3.22,-9.29 -2.64,-8.28 -3.15,-33.94 4.88,-45 8.07,-11.09 -5.53,-6.88 -16.15,4.32 -10.63,11.15 -18.15,31.7 -15.86,45.66 0,0 -0.61,5.87 23.91,4.31 z m -37.52,-67.96 c 12.88,-14.37 -6.84,-10.53 -23.34,3.63 -16.48,14.11 -29.99,41.66 -28.75,61.54 0,0 -1.69,8.15 32.94,9.54 0,0 8.42,-0.53 5.81,-12.53 -2.47,-11.98 0.45,-47.93 13.34,-62.18 z m -87.89,-74.93 c 75.07,-4.92 128.89,21.11 167.01,47.73 10.04,7 23.31,24.05 40.27,12.85 -7.23,-14.98 -26.39,-24.85 -42.26,-33.04 -27.81,-14.37 -52.47,-26.94 -84.52,-34.9 54.02,8.26 92.4,30.76 132.81,51.42 4.95,-10.38 10.51,-31.21 14.16,-48.84 l 0.52,0.05 c 0,0 3.67,-9.88 2.58,-19.53 0.15,-4.6 -0.78,-8.56 -4.07,-10.74 -1.11,-1.42 -2.44,-2.73 -4.11,-3.82 -14.75,-9.67 -58.52,-31.04 -93.63,-33.58 -1.16,-0.07 -2.27,-0.22 -3.42,-0.33 l -2.59,-0.73 -0.07,0.48 c -31.84,-3.69 -52.44,-16.81 -11.72,-10.12 40.74,6.72 128,21.57 96.21,9.62 l 0.11,0.02 c -39.69,-15.51 -91.77,-30.69 -142.89,-25.71 -33.03,3.2 -67.2,19.4 -96.58,34.89 -29.34,15.45 -57.18,35.77 -88.54,42.22 -23.87,4.94 -43.59,-1.94 -64.39,-5.5 -13.85,-2.34 -33.15,-7.95 -41.54,0.7 -3.54,4.19 -0.72,8.49 -0.72,8.49 7.94,19.62 31.07,31.19 50.3,36.72 60.36,17.37 118.83,-14.55 177.08,-18.35 z m 17.01,65.76 c 12.62,-18.31 -9.29,-10.98 -26.04,7.72 -16.76,18.69 -28.07,52.35 -23.77,75.03 0,0 -0.73,9.53 38.96,5.89 0,0 9.52,-1.89 4.9,-15.19 -4.73,-13.42 -6.64,-55.1 5.95,-73.45 z m -79.92,8.72 c 12.44,-20.82 -10.82,-11.69 -27.75,9.78 -16.94,21.37 -27.09,59.1 -20.93,83.8 0,0 -0.14,10.62 42.73,4.68 0,0 10.14,-2.56 4.23,-17.09 -5.93,-14.48 -10.72,-60.33 1.72,-81.17 z m -82.62,11.5 c 12.72,-21.08 -10.85,-12.08 -28.06,9.58 -17.23,21.59 -27.69,59.9 -21.58,85.21 0,0 -0.23,10.74 43.13,5.29 0,0 10.28,-2.5 4.37,-17.35 -5.89,-14.84 -10.51,-61.7 2.14,-82.73 z m -75.72,-23.8 c 15.61,-27.27 -11.73,-15.72 -32.57,12.24 -20.82,27.97 -34.79,77.68 -29.28,110.62 0,0 -0.8,14.07 48.83,7.3 0,0 11.92,-3.09 6.02,-22.58 -5.92,-19.36 -8.62,-80.28 7,-107.58 z m -80.38,20.29 c 15.56,-23.8 -11.82,-14.71 -32.58,9.48 -20.74,24.17 -34.4,68.31 -28.65,98.18 0,0 -0.78,12.63 49.05,8.82 0,0 11.91,-2.29 5.83,-19.98 -6.03,-17.69 -9.15,-72.64 6.35,-96.5 z m -85.14,27.74 c 10.98,-20.46 -10.36,-11.36 -25.48,9.78 -15.12,21.03 -23.44,58.05 -17.05,82.25 0,0 0.14,10.39 39.73,4.3 0,0 9.4,-2.58 3.46,-16.71 -5.88,-14.2 -11.63,-59.14 -0.66,-79.62 z m -64.93,17.69 c 10.31,-16.32 -8.4,-9.23 -22.34,7.51 -13.92,16.76 -22.72,46.32 -18.28,65.79 0,0 -0.36,8.33 33.87,3.93 0,0 8.22,-1.94 3.71,-13.4 -4.32,-11.4 -7.32,-47.51 3.04,-63.83 z m -68.19,-11.78 c 12.6,-18.31 -9.3,-10.98 -26.05,7.74 -16.75,18.69 -28.06,52.34 -23.76,75.03 0,0 -0.74,9.51 38.95,5.89 0,0 9.52,-1.89 4.9,-15.21 -4.74,-13.41 -6.63,-55.07 5.96,-73.45 z m -55.02,4.85 c 12.88,-14.35 -6.83,-10.55 -23.32,3.6 -16.5,14.13 -30.01,41.69 -28.77,61.56 0,0 -1.68,8.15 32.94,9.54 0,0 8.42,-0.53 5.83,-12.55 -2.48,-11.98 0.43,-47.93 13.32,-62.15 z m 755.27,-755.37 c -38.14,-13.18 -105.91,-46.26 -160.35,-73.94 -13.01,-0.6 -26.11,-0.94 -39.29,-0.94 -465.3,0 -842.48,377.19 -842.48,842.49 0,360.48 226.45,668 544.82,788.29 1.61,-1.49 3.31,-2.93 5.11,-4.33 3.61,-2.81 9.58,-4.3 12.67,-8 4.11,-4.94 2.4,-14.97 4.19,-21.16 5.55,-19.11 17.35,-36.65 37,-50.99 2.87,-2.12 8.35,-3.14 10.85,-5.95 5.47,-6.21 3.88,-16.65 8.01,-23.83 4.35,-7.55 11.76,-16.67 20.9,-23.69 5.01,-3.86 12.5,-5.92 17.18,-10.52 3.79,-3.71 4.84,-10.39 7.55,-15.95 7.34,-15.01 26.73,-32.41 36.04,-48.12 1.23,-2.07 2.19,-4.27 3,-6.51 3.88,-7.99 13.26,-24.92 26.05,-32.75 0,0 1.33,-23.51 24.78,-50.31 -47.5,2.56 -93.32,29.42 -128.56,2.74 -10.17,11.1 -42.79,19.8 -56.75,4.23 -10.31,17.92 -64.99,29.36 -75.62,1.04 -77.73,34.87 -171.54,-14.85 -201.69,-64.76 -5.6,-2.67 -10.83,-5.48 -15.77,-8.37 -21.28,6.4 -50.1,8.67 -81.29,-13.82 -30.74,-22.18 -62.88,-121.66 -57.35,-190.53 0.6,-7.38 14.59,-24.8 19.62,-59.7 5,-34.62 8.81,-45.99 8.81,-45.99 -6.84,-11.93 -15,-17.26 -16.11,-31.22 -2.41,-30.21 23.42,-46.63 47.62,-62.1 8.61,-4.01 18.36,-6.89 28.94,-7.27 6.39,-10.12 31.01,-44.33 71.72,-44.33 1,0 2.03,0.07 3.03,0.13 15.54,-13.07 31.75,-16.58 20.56,-0.47 -0.92,1.33 -1.71,2.82 -2.45,4.35 7.48,-4.43 16.54,-8.77 24.61,-9.56 0.16,-0.01 3.96,-0.97 7.13,-0.97 1.12,0 4.46,0 5.64,2.57 1.17,2.58 -1.21,5.35 -1.99,6.23 -3.26,3.76 -6.93,13.54 -9.69,22.65 2.98,-5.46 6.23,-10.66 9.87,-15.13 19.37,-23.78 46.47,-35.02 31.34,-11.36 -4.86,7.58 -7.63,17.91 -8.98,28.88 7.5,-9.25 20.42,-19.99 41.43,-24.29 17.36,-16.51 38.94,-23.26 26.01,-5.71 -3.3,4.49 -5.46,10.27 -6.75,16.59 10.47,-12.55 28.17,-28.68 49.88,-28.68 l 1.58,0.04 0.44,0.02 c 14.89,-10.07 27.36,-11.75 16.22,2.77 -4.83,6.32 -7.46,15.08 -8.64,24.34 9.84,-20.08 28.82,-47.69 61.49,-56.57 0.24,-0.09 5.87,-1.65 10.52,-1.65 3.63,0 5.91,0.93 7,2.92 1.58,2.85 -0.5,6.17 -1.18,7.26 -2.11,3.38 -4.07,7.59 -5.77,11.74 14.67,-8.6 25.51,-9.33 14.1,4.68 -5.9,7.22 -9.05,17.42 -10.34,27.95 7.97,-21.31 24.22,-51.23 56.3,-70.83 0.24,-0.11 6.01,-2.84 12.42,-2.84 3.09,0 5.84,0.65 8.23,1.85 2.04,1.05 3.38,2.77 3.93,4.98 1.67,6.68 -4.67,16.16 -5.24,16.93 -2.64,5.2 -7.48,16.18 -9.86,25.78 l 0.24,-0.19 c 23.19,-18.71 53.29,-27.37 34.72,-8.72 -11.27,11.35 -15.62,30.79 -16,46.67 6.77,-19.01 23.24,-51.94 57.35,-58.45 0.23,-0.02 5.52,-1.04 9.42,-1.04 2.17,0 4.78,0.25 5.69,2.33 0.4,0.88 0.56,2.3 -0.99,4.04 -2.55,2.86 -6.18,11.52 -8.1,18.52 1.62,-1.24 3.19,-2.55 4.89,-3.63 16.54,-10.85 36.06,-16.54 38.61,-13.02 5.29,-4.34 13.57,-10.03 24.82,-14.99 1.05,-2.39 2.09,-4.82 2.93,-7.24 0,0 5.25,-14.59 7.27,-22.48 -26.76,6.93 -72.56,20.35 -106.65,12.83 -26.92,-5.92 -97.1,-44.72 -80.12,-71.99 1.13,-1.82 2.58,-3.09 4.24,-4.11 l 1.05,-0.4 c 6.7,-3.57 18.52,-5.67 30.95,-5.57 l 4.52,0.13 c 7.22,0.39 26.15,3.12 32.56,5.2 18.77,6.1 35.53,2.43 35.53,2.43 l -0.24,-0.17 c 13.34,-1.55 27.41,-6.24 41.94,-13.66 15.61,-7.94 36.85,-21.06 42.26,-27.53 9.76,-11.73 -5.19,-39.21 -10.76,-56.13 -0.27,-1 -0.61,-2.04 -0.93,-3.08 l -0.4,-1.4 -0.05,0.03 c -0.79,-2.37 -1.76,-4.86 -2.8,-7.4 -0.95,1.19 -1.79,2.34 -2.43,3.42 -5.34,8.98 -8.21,16.84 -10.97,13.23 -2.76,-3.62 -2.89,-17.96 2.36,-31.49 0.54,-1.4 1.2,-2.73 1.91,-4.06 -6.05,-11.06 -13.38,-22.64 -21.11,-33.75 -6.02,5.7 -12.11,12.11 -15.05,17.23 -6.87,11.76 -10.53,22.09 -14.04,17.35 -3.54,-4.72 -3.64,-23.77 3.09,-41.67 2.2,-5.83 5.55,-11.11 9.07,-15.73 -5.34,-6.74 -10.55,-12.95 -15.3,-18.23 -2.13,-2.34 -4.65,-4.99 -7.32,-7.74 -7.34,7.56 -16.63,17.94 -20.38,25.45 -6.54,13.12 -9.91,24.3 -13.63,19.54 -3.71,-4.8 -4.43,-24.95 1.75,-44.43 2.55,-7.98 6.93,-15.27 11.27,-21.19 -7.96,-7.58 -16.6,-15.59 -25.47,-23.67 -5.38,7.14 -10.69,14.98 -13.12,20.98 -5.83,14.19 -8.6,26.23 -12.54,21.61 -3.88,-4.63 -5.58,-25.57 -0.35,-46.44 1.29,-5.15 3.26,-10.09 5.5,-14.67 -8.79,-7.86 -17.3,-15.38 -25.11,-22.19 -2.29,4.97 -4.2,9.69 -5.26,13.58 -4.58,16.9 -6.3,30.85 -10.81,26.57 -4.51,-4.18 -8.35,-26.68 -5.05,-50.59 0.31,-2.3 0.76,-4.57 1.27,-6.85 l -2.2,-1.89 c -5.11,-4.41 -10.66,-9.72 -16.39,-15.56 -1.43,4.49 -2.54,8.7 -3.12,12.19 -2.91,17.61 -3.35,31.7 -7.98,28.33 -4.6,-3.31 -10.11,-25.03 -9,-49.33 0.17,-3.82 0.63,-7.68 1.27,-11.45 -6.74,-7.6 -13.41,-15.44 -19.69,-23.09 -3.64,9.35 -6.93,19.01 -8.2,26 -3.33,18.42 -4.03,33.23 -8.74,29.6 -4.31,-3.29 -9.05,-23.01 -8.53,-45.96 -4.7,-3.44 -10.79,-19.44 -10.99,-37.57 -0.09,-6.17 1.01,-12.49 2.51,-18.2 -3.05,-4.3 -8.38,-7.28 -12.11,-12.52 -19.24,-26.91 -11.39,-58.98 30.18,-66.11 12.74,-39.25 45.04,-58.31 94.58,-58.76 6.65,-0.06 13.6,2.26 20.12,1.85 7.36,-0.49 13.42,-3.48 20.13,-3.69 36.11,-1.1 55.04,10.39 82.49,18.39 20.47,5.94 41.6,7.84 54.34,12.84 19.51,7.65 28.78,28.62 44.26,38.56 5.77,3.7 16.64,5.44 26.17,11.01 8.04,4.73 15,13.32 22.13,16.53 6.23,2.82 16.6,2.26 24.14,5.51 12.64,5.48 26.6,17.31 42.27,25.73 32.81,17.55 59.51,30.53 94.57,45.89 16.75,7.34 34.47,24.6 44.27,25.71 11.62,1.34 25.15,-8.36 34.21,-7.34 18.46,-21.95 24.89,-52.62 24.12,-92.06 1.09,-0.11 0.29,-9.78 0.29,-9.78 0,0 6.45,-84.66 -125.77,-130.38 z M 2319.1,3773.92 c 13.83,-3.85 29.29,-11.71 14.56,-35.21 -9.06,9.68 -12.13,22.44 -14.56,35.21 z m 26.38,-30.96 c 4.42,7.74 0.02,11.68 2.36,16.37 39.74,-5.12 43.17,-33.03 26,-72.62 -26.49,8.95 -33.54,26.66 -38.58,44.64 4.25,4.61 7.55,6.9 10.22,11.61 z m 43.39,-7.87 c 36.99,-16.3 42.8,-57.19 17.22,-110.53 -8.74,5.74 -15.55,12.62 -20.46,20.22 -3.89,6.03 -9.35,15.9 -8.18,24.01 0.82,5.58 5.24,13.07 7.5,19.31 6.47,17.93 8.99,34.11 3.92,46.99 z m 177.23,-155.25 c -0.64,1.95 0.67,1.89 2.28,3.33 55.29,-11.22 59.69,-65.17 35.95,-105.83 -11.26,-19.25 -22.27,-29.38 -39.55,-24.01 -14.3,4.46 -16.25,15.95 -23.14,23.85 28.17,41.04 27.62,71.27 24.46,102.66 z m -63.91,40.61 c -0.24,5.01 -1.15,10.58 0.87,15.52 4.77,-0.4 13.12,-1.61 19.95,-5.23 31.05,-16.4 43.9,-75.07 25.85,-109.56 -7.75,-14.78 -15.59,-21.96 -30.09,-17.81 -23.4,6.72 -30.19,33.21 -39.62,44.17 25.51,27.2 24.04,51.08 23.04,72.91 z m -74.76,73.65 1.52,0.74 c 60.84,-21.44 95.74,-61.97 40.45,-136.4 -21.08,10.57 -32.94,24.68 -38.43,40.68 -3.23,9.38 -5.72,10.51 -3.53,22.15 4.69,25.14 6.27,52.87 -0.01,72.83 z m 236.11,-312.56 c -2.27,-1.01 -3.87,-1.76 -3.87,-1.76 -7.39,-3.78 -15.16,-6.03 -22.54,-7.31 -45.74,9.82 -59.56,61.95 -59.56,61.95 42.74,18.79 66.89,72.89 51.68,102.65 0.43,1.11 1.42,0.93 2.42,0.7 19.37,-8.54 39.75,-22.88 49.66,-38.41 18.83,-29.45 24.41,-73.75 8.73,-109.34 -6.98,-1.61 -11.46,-3.21 -17.08,-5.19 -0.95,-0.25 -1.94,-0.54 -2.92,-0.88 l -5.22,-1.92 -0.53,-0.21 -0.82,-0.27 0.05,-0.01 z m 73.78,36.96 c -3.13,-2.66 -6.21,-5.27 -9.06,-7.69 -2.62,-5.02 -10.66,-11.66 -20.93,-16.01 8.15,24.72 9.13,50.99 9.7,70.45 16.84,-8.75 28.08,-20.77 34.57,-34.43 -2.08,-1.8 -4.21,-3.66 -6.4,-5.55 -2.88,5.37 -6.87,10.23 -12.09,14.35 2.36,-6.86 3.71,-13.9 4.21,-21.12 z m -92.4,328 c 412.7,0 756.05,-296.74 828.41,-688.48 -7.89,5.56 -16.59,10.5 -26.45,14.61 -20.63,92.05 -65.01,150.17 -156.18,183.4 -30.56,11.13 -59.51,24.02 -89.66,37.15 1.74,97.97 -112.11,95.91 -183.06,146.34 -30.86,21.99 -65.84,62.56 -101.14,70.06 -68.27,14.52 -110.27,-33.06 -150.59,-66.3 -9.89,10.8 -24.72,21.35 -46.23,30.94 0,0 -38.48,54.88 -56.43,65.21 -1.19,0.68 -1.98,1.3 -2.5,1.92 -9.92,4.65 -22.34,7.27 -31.12,13.07 -8.67,5.7 -10.31,19.19 -18.99,25.7 -4.25,3.19 -10.84,6.65 -16.6,8.96 -6.96,2.79 -18.88,2.27 -25.88,6.1 -8.63,4.73 -9.32,20.11 -15.57,27.74 -6.89,8.43 -15.75,15.32 -30.08,20.14 -5.81,1.93 -14.59,2.06 -19.84,4.87 -5.86,3.17 -7.29,13.09 -11.83,19.17 -10.55,14.18 -28.36,25.18 -48.68,32.36 -4.37,1.54 -10.25,1.54 -13.45,3.69 -3.77,2.51 -4.21,8.78 -6.49,13.58 70.85,19.35 145.38,29.77 222.36,29.77 z m 836.59,-742.56 c -8.56,14.67 -16.48,28.78 -19.38,41.21 5.81,-3.84 10.91,-8.12 15.58,-12.68 1.44,-9.45 2.67,-18.97 3.8,-28.53 z m -836.59,785.09 c -91.12,0 -179,-13.85 -261.73,-39.43 -0.93,1.64 -1.92,3.24 -3.23,4.52 -7.64,7.44 -16.71,13.1 -35.56,8.27 -6.68,8.65 -15.49,15.6 -29.86,18.55 l -0.45,-0.77 c 1.82,-17.15 4.28,-34.48 17.33,-46.35 l -0.19,-2.08 C 1997.3,3605.11 1759.91,3282.33 1759.91,2904 c 0,-488.79 396.23,-885.02 885.01,-885.02 488.78,0 885.04,396.23 885.04,885.02 0,488.81 -396.26,885.03 -885.04,885.03 z M 2195.1,3323.54 c 0,0 -34.81,-7.93 -44.29,-69.48 0,0 -1.65,-31.07 8.08,-24.19 -8.2,37.31 27.27,54.21 35.41,58.01 11.45,5.09 20.91,3.38 21.63,-6.34 0.78,-10.49 -11.21,-15.13 -14.8,-25.94 12.73,7.18 41.2,24 38.24,45.9 -2.18,16.1 -17.34,30.4 -44.27,22.04 z m 457.68,-37.78 c -59.82,35.02 -214.44,28.94 -250.75,31.75 -35.74,2.72 -53.6,-42.72 -53.6,-42.72 -0.47,-9.62 7.4,1.41 7.4,1.41 23.35,42.08 43.88,34.38 43.88,34.38 73.99,-21.61 87.17,-130.29 90.25,-155.48 3.06,-25 9.38,-8.72 9.38,-8.72 7.19,62.54 -38.41,138.76 -48,148.55 -9.58,9.73 -0.43,15.23 30.13,6.68 92.03,-25.84 100.65,-173.22 106.2,-191.09 5.54,-17.8 9,-0.68 9,-0.68 -12.45,135.51 -63.96,168.92 -77.69,187.56 -5.7,7.73 40.82,8.9 61.31,-4.43 115.64,-74.71 102.66,-217.79 113.07,-197.37 10.55,20.85 -29.1,150.34 -84.81,194.41 -11.15,8.79 38.66,-6.58 57.02,-23.49 87,-80.41 97.7,-167.53 104.39,-192.7 6.57,-25 9.78,-16.53 9.78,-16.53 1.21,85.15 -66.26,193.01 -126.96,228.47 z m 167.67,59.29 c 12.83,6.96 27.96,52.1 59.04,33.35 23.1,-13.93 34.1,-17.46 34.1,-17.46 0,0 -16.13,-4.53 -23.47,-16.63 -7.34,-12.1 -16.14,-21.41 -41.81,-17.62 -26.95,4.02 -31.88,-0.21 -45.46,-2.42 0,0 4.76,13.79 17.6,20.78 z m -49.59,-36.2 c 19.79,-4.3 38.04,-11.99 56.34,-23.86 20.27,-13.17 42.21,-37.36 72.44,-34.91 9.64,0.77 27.16,10.1 34.21,14.7 8.82,5.75 29.74,19.45 24.15,40.39 -2.48,9.3 -13.54,10.78 -20.13,18.37 -9.13,10.56 -8.78,20.93 -16.09,33.05 15.93,-3.2 25.06,-12.64 42.24,-14.7 -27.07,24.28 -58.26,44.78 -96.58,58.78 2.88,1.63 4.71,8.31 14.09,11.01 8.45,2.44 35.7,-1.72 18.11,1.85 -17.66,4.94 -28.62,-0.09 -40.23,-7.36 -26.68,-16.67 -48.41,-54.95 -76.48,-71.6 -12.18,-7.27 -24.09,-5.6 -34.22,-18.39 6.56,-13.1 13.21,-5.39 22.15,-7.33 z m 209.28,23.88 c -6.66,-3.87 4.19,-7.38 6.03,-9.19 7.67,-7.55 24.8,-21.4 30.18,-33.05 11,-23.83 7.62,-60.3 -12.08,-73.48 -13.27,-8.86 -78.22,-33.08 -106.63,-33.05 -79.93,0.11 -88.04,87.86 -136.84,117.54 0.87,-8.4 7,-25.99 13.98,-35.11 27.44,-35.83 53.66,-109.66 130.81,-97.33 27.26,4.36 78.26,23.19 98.72,35.98 22.22,13.85 38.72,67.03 16.08,96.46 -10.14,13.18 -34.41,29.88 -40.25,31.23"
+ style="fill:#403c3d;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path76" />
+ </g>
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ d="m 376.40655,56.024215 0,23.8525 24.42625,0 0,-23.8525 -24.42625,0 z m 0.09,131.692505 24.24875,0 0,-96.436255 -24.24875,0 0,96.436255 z m 305.7425,-96.436255 -35.3525,96.436255 -18.88,0 -35.5375,-96.436255 25.3575,0 19.61875,59.602505 19.43625,-59.602505 25.3575,0 z m -97.74375,96.436255 -23.5075,0 0,-8.885 c -6.29375,6.66375 -14.31625,9.995 -24.06125,9.995 -9.505,0 -17.09375,-2.83625 -22.76875,-8.51375 -6.54125,-6.53875 -9.80875,-15.67 -9.80875,-27.39375 l 0,-61.638755 24.2475,0 0,58.306255 c 0,6.04875 1.70625,10.61625 5.12125,13.6975 2.80625,2.5925 6.34375,3.8875 10.61125,3.8875 4.39,0 7.99,-1.295 10.79625,-3.8875 3.4125,-3.08125 5.12125,-7.64875 5.12125,-13.6975 l 0,-58.306255 24.24875,0 0,96.436255 z m -114.8675,-48.31 c 0,-8.51375 -0.67125,-14.6225 -2.0125,-18.32375 -2.44125,-6.17 -7.1375,-9.255 -14.09,-9.255 -6.95625,0 -11.6525,3.085 -14.09125,9.255 -1.34125,3.70125 -2.0125,9.81 -2.0125,18.32375 0,8.515 0.67125,14.62375 2.0125,18.32375 2.43875,6.295 7.135,9.44125 14.09125,9.44125 6.9525,0 11.64875,-3.14625 14.09,-9.44125 1.34125,-3.7 2.0125,-9.80875 2.0125,-18.32375 z m 24.24875,0 c 0,9.8725 -0.43375,17.2775 -1.29625,22.2125 -1.35875,8.02125 -4.1975,14.19125 -8.51375,18.5075 -5.80375,5.805 -13.63625,8.7 -23.50875,8.7 -9.8725,0 -17.8925,-3.3925 -24.06125,-10.18 l 0,9.07 -23.3225,0 0,-131.788755 24.2475,0 0,43.86875 c 5.77875,-6.415 13.53,-9.625 23.24625,-9.625 9.83875,0 17.64875,2.9 23.42875,8.7 4.305,4.318755 7.1325,10.488755 8.48625,18.508755 0.8625,4.93625 1.29375,12.28 1.29375,22.02625 z m -130.04375,48.31 -13.69625,0 c -9.255,0 -16.4125,-2.8975 -21.47125,-8.69875 -4.4425,-5.05875 -6.6625,-11.35125 -6.6625,-18.88 l 0,-104.210005 24.2475,0 0,102.730005 c 0,5.80125 2.8075,8.69875 8.42375,8.69875 l 9.15875,0 0,20.36"
+ style="fill:#403c3d;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path74" />
+ <g
+ transform="matrix(0.23169071,0,0,-0.23371708,-280.79355,1099.9435)"
+ id="g66-4">
+ <g
+ id="g68-1"
+ clip-path="url(#clipPath70-6)">
+ <g
+ id="g3197"
+ transform="translate(-350.10267,-350.10267)">
+ <path
+ id="path76-6"
+ style="fill:#e9e9e9;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 3504.81,2908.41 c 0,-483.58 -391.32,-875.6 -874.02,-875.6 -482.71,0 -874,392.02 -874,875.6 0,483.61 391.29,875.63 874,875.63 482.7,0 874.02,-392.02 874.02,-875.63"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path78"
+ style="fill:#403c3d;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 3482.08,2908.41 c 0,-471 -381.13,-852.83 -851.29,-852.83 -470.16,0 -851.27,381.83 -851.27,852.83 0,471.02 381.11,852.85 851.27,852.85 470.16,0 851.29,-381.83 851.29,-852.85"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path80"
+ style="fill:#adda1a;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 3473.33,3029.95 c -6.42,7.53 -13.81,14.41 -22.76,20.33 3.77,-16.2 15.99,-35.21 27.12,-54.62 -1.18,11.52 -2.73,22.91 -4.36,34.29 z M 3070.25,2284 c -63.63,-5.85 -49.36,-41.32 30.29,-33.77 29.21,2.77 76.64,33.01 121.13,44.56 22.41,21.66 43.74,44.44 63.68,68.43 -27,-14.62 -77.9,-37.33 -127.3,-60.84 -28.31,-13.46 -63.77,-16.17 -87.8,-18.38 z m 409,691.11 c -9.21,11.12 -16.63,28.08 -26.56,40.46 -2.32,4.07 -10.61,18.92 -19.05,37.24 -0.7,1.84 -1.35,3.66 -2.39,5.51 l -0.05,-0.07 c -2.45,5.45 -4.83,11.12 -7.04,16.85 l -0.01,0.06 c -1.76,4.55 -3.39,9.12 -4.84,13.64 -7.01,21.99 -27.18,60.03 -55.62,91.97 -0.17,1.83 -0.23,3.57 0.33,4.78 l -4.7,-0.11 c -16.1,17.22 -34.56,32.28 -54.71,41.42 -58.53,26.53 -110.11,53.23 -110.11,53.23 -1.79,-15.12 12.75,-34.44 21.07,-51.41 1.85,-6.68 3.04,-13.01 3.15,-18.42 l -0.53,0.48 c -0.79,-1.72 -0.36,-4.51 -0.09,-7.16 -0.63,-2.86 -1.75,-5.25 -3.64,-6.83 -9.8,30.98 -27.24,55.39 -36.22,83.01 -9.63,29.6 -17.24,58.12 -39.62,80.27 -27.97,27.69 -80.34,42.83 -120.05,60.13 -15.2,9.33 -29.15,18.25 -39.73,25.48 l 0.27,0.4 c -42.2,33.83 -99.59,85.95 -160.2,43.76 -36.58,-25.48 -72.09,-74.05 -114.92,-94.66 -4.7,-2.29 -10.18,-4.72 -16.01,-6.75 l -0.25,-0.29 -1.82,-0.38 c -4.22,-1.37 -8.56,-2.48 -12.88,-3.09 -11.15,-3.02 -19.94,-6.36 -27.56,-9.36 -0.89,-1.67 -2.36,-1.72 -2.72,-1.08 -14.7,-5.76 -25.44,-9.82 -42.09,-6.82 -10.16,1.82 -36.31,-0.01 -47.19,-1.01 0,0 -69.05,-0.05 15.93,9.37 -3.27,2.46 -6.36,4.92 -9.21,7.4 -45.43,-3.61 -85.18,12.35 -130.49,5.85 5.09,-8.21 21.77,-6.21 25.04,-16.05 -34.67,-11.48 -53.95,37.68 -88.39,17.4 5.15,-9.48 0.58,-21.45 -6.91,-27.78 2.9,29.09 -36.96,53.69 -62.56,31.76 9.7,-10.86 10.2,-28.86 4.46,-43.12 l -17.4,-19.5 c -4.08,-1.69 -8.59,-2.37 -13.51,-1.4 16.74,7.37 29.01,20.73 29.06,36.46 0.09,27.81 -34.12,35.28 -62.43,34.49 -56.18,-1.59 -100.39,-26.71 -133.84,-59.13 l 0.24,0.95 -19.4,-20.96 c 0,0 -60.6,-25.35 -82.33,-93.09 0.7,8.35 1.64,17.81 2.85,27.9 9.79,28.43 25.25,49.66 49.44,66.79 -28.7,-3.61 -69.69,-15.54 -82.38,-53.55 -5.96,-17.81 -12.11,-31.1 -16.94,-60.9 l -0.29,0.34 c 0,0 -11.55,-58.65 -4.07,-92.05 6.5,-29.06 15.74,-58.97 19.98,-78.46 0.31,-2.57 0.8,-5.25 1.55,-8.02 53.53,25.5 127.71,32.14 197.84,42.47 -29.28,-4.79 -70.93,-16.14 -111.03,-25.84 -40.01,-9.7 -98.01,-24.8 -98.91,-60.92 -0.53,-21.23 15.39,-39.9 42.38,-40.6 -2.4,5.18 -2.21,12.74 -2.01,20.32 -5.57,-0.46 -4.61,-6.86 -8.07,-9.23 -2.07,41.18 68.63,45.39 115.05,53.52 6.31,1.1 12.28,2.63 18.18,3.7 21.63,3.79 53.78,1.97 88.43,1.46 47.63,-0.67 81.2,5.28 125.04,-11.15 14.08,-5.29 43.74,-7.09 58.03,-8.62 50.68,-5.38 88.38,3.26 150.38,-2.01 24.7,-2.09 49.47,-11.64 72.68,-22.15 32.18,-14.54 57.5,-32.58 96.88,-22.16 14.24,-0.73 28.56,1.95 33.28,-0.73 22.77,-2.03 19.21,-19.81 45.45,-17.71 30.54,2.43 54.62,21.61 90.84,24.01 28.24,1.84 57.99,-5.19 90.84,-1.86 22.77,2.31 45.33,12.35 64.59,20.29 48.59,20.07 128.49,59.45 135.25,112.57 5.48,43.01 -26.95,65.35 -72.67,53.55 46.44,24.15 89.27,-11.93 88.81,-57.23 -0.13,-13.82 -9.81,-26.35 -16.14,-42.45 -6.37,-16.16 -6.51,-27.48 -14.14,-36.9 -3.81,-4.74 -8.73,-8.7 -13.9,-11.99 -8.91,-4.41 -21.76,-8.11 -39.39,-12.95 -26.03,-7.17 -50.53,-14.82 -50.53,-14.82 -4,-0.78 -5.56,-1.56 -5.83,-2.26 -16.03,-4.39 -35.35,-10.88 -46.46,-18.98 -21.4,-15.61 -55.77,-27.94 -88.83,-22.1 -3.06,0.55 -5.56,0.66 -7.59,0.44 -10.86,1.42 -21.56,2.92 -32.09,3.3 0,0 -60.14,-1.51 -56.74,-3.53 3.41,-2.07 4.26,-2.02 4.26,-2.02 22.01,-17.39 32.52,-46.38 44.41,-73.8 13.37,-30.85 23.4,-62.63 26.25,-103.36 8.55,33.04 20.19,63.26 35.25,90.38 19.61,32.19 58.62,82.91 118.6,102.69 21.12,6.63 38.61,16.58 52.03,30.26 -18.49,-27.47 -50.41,-39.13 -76.7,-57.24 -54.55,-37.54 -83.75,-92.88 -109,-162.4 -5.76,-15.84 -11.5,-31.64 -20.18,-46.15 -8.38,-13.93 -21.17,-26.48 -26.25,-40.58 -3.28,-9.09 -1.97,-19.3 -4.03,-27.7 -5.7,-23.21 -15.54,-46.26 -29.19,-64.5 -11.59,-13.02 -35.57,-39.82 -40.13,-43.98 l -0.22,-0.36 c -31.85,-30.92 -69.62,-56.39 -110.13,-79.41 l 0.39,-0.82 -2.18,-1.47 -0.22,0.45 c -5.62,-3.61 -10.68,-7.72 -15.38,-12.15 -4.84,-4.03 -8.91,-8.05 -10.85,-11.33 -16.68,-19.34 -29.5,-42.11 -48.46,-59.56 -10.87,-10.02 -23.71,-18.07 -36.43,-26.37 l 0.09,0.31 c 0,0 -15.25,-10.33 -28.3,-18.19 -40.26,-19.09 -81.84,-52.85 -143.27,-53.58 -32.98,-0.36 -78.22,2.15 -92.87,27.71 0,0 -8.68,4.13 -8.07,-14.77 0.78,-24.11 41.07,-24.82 61.99,-34.85 10.59,-6.14 -10.26,-1.04 -17.57,-2.08 16.08,-17.27 25.62,-40.53 60.55,-40.57 0,0 -8.15,7.62 -10.95,9.16 -2.81,1.52 1.78,3.83 14.29,-0.78 10.26,-3.78 23.65,-7.19 41.17,-7.09 1.13,0 2.23,-0.02 3.41,0 2.76,0.08 5.63,0.26 8.61,0.54 0,0 31.03,0.17 60.97,13.12 29.96,12.96 63.98,9.55 79.64,21.14 15.66,11.58 27.23,34.07 37.43,37.5 10.22,3.42 24.55,11.33 36.24,24.55 9.96,11.24 25.12,4.89 37.52,16.37 11.29,10.44 86.52,47.81 86.52,47.81 22.36,15.41 36.07,33.48 61.35,46.2 36.66,25.62 -50.85,-18.01 -76.31,-27.89 -31.65,-12.26 -3.07,4.31 -3.07,4.31 l 51.26,29.33 c 15.44,7.57 30.91,15.07 46.7,22.26 10.21,4.35 27.69,11.65 41.34,16.53 26.89,6.81 50.65,4.82 73.31,8.99 24.06,4.41 45.17,16.05 68.63,20.3 3.73,0.66 10.05,-1.26 14.14,0 25.47,7.85 50.95,32.67 74.69,46.13 54.76,31.04 95.31,60.15 111.03,127.36 3.69,15.78 5.91,31.75 10.09,47.96 8.91,34.68 15.52,66.46 12.1,112.58 -2.02,27.41 -17.84,55.88 -16.14,90.44 1.6,32.49 24.4,57.21 34.31,86.74 11.84,35.26 -9.8,59.99 -42,73.32 l 0.02,0.03 c 0,0 -23.83,11.25 -33.01,11.93 -9.19,0.69 4.77,3.06 10.89,3.06 4.7,0 8.77,3.24 11.96,8.26 3.64,5.15 5.68,12.38 9.75,17.83 5.72,7.65 19.89,18.14 20.19,25.82 0.39,10.04 -16.8,23.84 -26.25,29.55 -16.3,9.86 -42.61,15.88 -64.59,25.84 -24.47,11.05 -42.11,23.26 -54.5,35.05 -6.87,17.68 -19.82,28.7 -18.17,49.84 0.41,5.36 2.38,10.54 4.14,15.93 l 0.74,1.99 c 2.04,6.89 4.85,17.63 0,29.9 -4.84,12.28 -22.46,15.85 -22.46,15.85 l -0.07,-0.01 c -9.55,3.18 -20.88,5.11 -28.78,8.33 -12.47,5.03 -22.27,11.8 -32.01,16.88 12.11,-3.84 26.84,-10.03 49.63,-12.08 10.06,-0.89 38.28,-5.95 43.6,-23.9 l 0.56,-2.02 0.47,-1.79 c 0.23,-1.02 0.4,-2.05 0.56,-3.09 0.18,-1.35 0.38,-2.66 0.41,-4.12 l 0.09,-2.09 c 0.1,-7.16 -1.4,-14.68 -4.77,-22.16 -12.95,-28.75 1.23,-50.51 22.34,-61.76 19.97,-15.69 49.52,-24.31 78.59,-35.23 23.22,-8.71 49.09,-21.54 62.26,-36.33 6.84,-11.84 10.51,-24.87 6.01,-37.26 -7.2,-13.97 -24.49,-20.05 -29.91,-37.14 6.8,-8.64 19.17,-10.55 28.26,-16.59 14.11,-9.41 24.5,-22.04 27.69,-40.18 l 0.18,-1.91 c 0.34,-2.16 0.53,-4.32 0.63,-6.51 0.03,-1.96 -0.05,-3.92 -0.08,-5.88 -1.68,-32.34 -26.5,-65.77 -33.73,-81.2 -8.16,-17.37 -5.61,-35.28 -5.61,-35.28 1.81,-7 3.64,-12.54 5.48,-16.85 3.27,-9.56 7.03,-22.96 9.88,-38.76 10.13,-22.39 21.09,-48.44 25.98,-66.09 10.22,-36.81 24.51,-102.3 4.09,-247.53 -20.41,-145.21 -215.75,-151.34 -274.96,-175.91 -40.77,-16.9 4.76,-30.67 82.01,-16.35 34.95,6.5 80.11,35.32 122.51,43.97 17.97,3.67 29.54,5.36 36.09,5.44 114.98,145.4 183.81,329.08 183.81,528.99 0,22.48 -1.13,44.67 -2.83,66.7"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path82"
+ style="fill:#f4f4f4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 2527.18,3484.46 c 28.26,41.24 27.7,71.63 24.53,103.17 -0.63,1.96 0.68,1.9 2.29,3.34 55.47,-11.28 59.88,-65.49 36.07,-106.35 -11.3,-19.34 -22.34,-29.53 -39.67,-24.13 -14.35,4.48 -16.31,16.03 -23.22,23.97 z m -22.94,26.32 c -23.48,6.74 -30.28,33.38 -39.75,44.39 25.59,27.33 24.12,51.34 23.12,73.26 -0.25,5.04 -1.16,10.64 0.87,15.61 4.78,-0.4 13.16,-1.62 20.01,-5.26 31.15,-16.48 44.04,-75.44 25.93,-110.1 -7.77,-14.86 -15.64,-22.08 -30.18,-17.9 z m -49.53,55.34 c -21.15,10.63 -33.04,24.8 -38.55,40.89 -3.24,9.42 -5.73,10.56 -3.54,22.26 4.71,25.26 6.29,53.13 -0.01,73.19 l 1.52,0.74 c 61.04,-21.54 96.06,-62.27 40.58,-137.08 z m 160.36,-21.48 c 0.43,1.12 1.42,0.94 2.43,0.7 19.43,-8.58 39.87,-22.99 49.81,-38.59 18.89,-29.6 24.49,-74.11 8.75,-109.89 -6.99,-1.61 -11.49,-3.22 -17.12,-5.22 -0.96,-0.25 -1.96,-0.53 -2.93,-0.88 l -5.24,-1.92 -0.53,-0.22 -0.83,-0.27 0.06,-0.02 c -2.29,-1 -3.88,-1.76 -3.88,-1.76 -7.42,-3.8 -15.21,-6.06 -22.62,-7.34 -45.89,9.86 -59.74,62.26 -59.74,62.26 42.87,18.87 67.1,73.24 51.84,103.15 z m 88.05,-72.17 c 16.89,-8.8 28.17,-20.87 34.68,-34.6 -2.09,-1.82 -4.23,-3.69 -6.42,-5.58 -2.89,5.4 -6.88,10.28 -12.13,14.42 2.37,-6.9 3.73,-13.96 4.23,-21.22 -3.14,-2.68 -6.23,-5.31 -9.09,-7.73 -2.63,-5.05 -10.69,-11.72 -20.99,-16.09 8.17,24.85 9.15,51.24 9.72,70.8 z m -311.91,160.11 c -8.77,5.76 -15.6,12.68 -20.53,20.31 -3.9,6.06 -9.38,15.98 -8.2,24.13 0.81,5.61 5.25,13.13 7.51,19.41 6.49,18.02 9.03,34.28 3.94,47.21 37.11,-16.36 42.93,-57.47 17.28,-111.06 z m -71.06,107.31 c 4.27,4.64 7.57,6.94 10.26,11.67 4.42,7.78 0.01,11.73 2.36,16.45 39.87,-5.15 43.3,-33.2 26.09,-72.98 -26.57,9 -33.65,26.79 -38.71,44.86 z m -16.21,42.78 c 13.88,-3.86 29.39,-11.76 14.6,-35.37 -9.08,9.72 -12.16,22.55 -14.6,35.37"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path84"
+ style="fill:#f6836c;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 2529.01,2752.37 c -23.94,4.97 -43.72,-1.93 -64.59,-5.52 -13.88,-2.35 -33.24,-7.99 -41.67,0.71 -3.55,4.21 -0.72,8.52 -0.72,8.52 7.97,19.73 31.16,31.35 50.46,36.91 60.55,17.46 119.21,-14.63 177.64,-18.45 75.3,-4.94 129.29,21.21 167.54,47.98 10.06,7.04 23.37,24.16 40.39,12.92 -7.25,-15.06 -26.47,-24.97 -42.4,-33.22 -27.89,-14.43 -52.63,-27.06 -84.78,-35.07 54.18,8.3 92.69,30.91 133.23,51.69 4.96,-10.44 10.54,-31.37 14.21,-49.1 l 0.51,0.06 c 0,0 3.69,-9.93 2.6,-19.63 0.14,-4.63 -0.79,-8.61 -4.09,-10.8 -1.11,-1.42 -2.45,-2.74 -4.12,-3.84 -14.8,-9.71 -58.71,-31.2 -93.93,-33.75 -1.16,-0.06 -2.28,-0.21 -3.43,-0.33 l -2.59,-0.73 -0.08,0.49 c -31.94,-3.71 -52.6,-16.9 -11.76,-10.17 40.88,6.75 128.41,21.66 96.52,9.67 l 0.11,0.01 c -39.82,-15.58 -92.06,-30.84 -143.33,-25.84 -33.14,3.22 -67.42,19.51 -96.89,35.07 -29.44,15.53 -57.36,35.95 -88.83,42.42"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path86"
+ style="fill:#f4f4f4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 2326.23,2354.71 c 4.08,2.22 4.97,-7.19 8.29,-18.98 3.33,-11.89 19.84,-36.31 19.84,-36.31 2.35,-5.03 -6.67,-9.99 -13.52,-12.26 -6.76,-2.27 -6.76,1.09 -6.76,1.09 0,0 -12.23,17.5 -14.12,33.81 -1.92,16.13 2.23,30.52 6.27,32.65 z m 40.64,1.81 c 4.69,2.53 5.68,-8.19 9.45,-21.63 3.78,-13.49 22.67,-41.28 22.67,-41.28 2.68,-5.7 -7.73,-11.3 -15.59,-13.92 -7.76,-2.56 -7.75,1.26 -7.75,1.26 0,0 -13.98,19.89 -16.1,38.44 -2.15,18.35 2.67,34.69 7.32,37.13 z m 40.42,22 c 6,3.2 7.23,-10.4 12,-27.41 4.77,-17.13 28.86,-52.33 28.86,-52.33 3.41,-7.23 -9.95,-14.37 -20.01,-17.65 -9.95,-3.25 -9.92,1.56 -9.92,1.56 0,0 -17.78,25.2 -20.43,48.68 -2.68,23.23 3.53,44 9.5,47.15 z m 57.45,25.09 c 6.09,3.05 6.97,-10.1 11.18,-26.55 4.31,-16.64 27.29,-50.85 27.29,-50.85 3.2,-6.99 -10.33,-13.79 -20.48,-16.91 -10.02,-3.04 -9.92,1.62 -9.92,1.62 0,0 -16.98,24.48 -18.95,47.17 -1.98,22.49 4.86,42.54 10.88,45.52 z m 44.26,31.78 c 6.07,3.98 8.64,-9.21 15.17,-25.27 6.58,-16.12 35.51,-47.78 35.51,-47.78 4.33,-6.72 -9.26,-15.58 -19.72,-20.26 -10.3,-4.57 -10.76,0.29 -10.76,0.29 0,0 -21.15,22.63 -26.1,45.45 -4.9,22.54 -0.14,43.66 5.9,47.57 z m 48.77,40.94 c 5.41,4.47 9.46,-7.11 17.8,-20.77 8.45,-13.93 40.63,-38.61 40.63,-38.61 5.1,-5.54 -6.94,-15.85 -16.57,-21.68 -9.51,-5.74 -10.49,-1.34 -10.49,-1.34 0,0 -23.53,17.77 -31.17,37.94 -7.55,19.98 -5.51,40.01 -0.2,44.46 z m 185.39,120.94 c 4.18,3.75 8.57,-4.11 16.71,-13.01 8.21,-9.05 37.03,-23.24 37.03,-23.24 4.66,-3.43 -4.6,-12.04 -12.11,-17.22 -7.5,-5.19 -8.69,-2.14 -8.69,-2.14 0,0 -21.23,10.05 -29.26,23.76 -7.99,13.54 -7.86,28.06 -3.68,31.85 z m -83.83,-151.23 c -9.45,-6.38 -10.83,-2.22 -10.83,-2.22 0,0 -25.47,15.59 -34.69,34.81 -9.02,18.94 -8.25,38.54 -3.03,43.27 5.27,4.75 10.24,-6.17 19.76,-18.9 9.66,-12.94 44.48,-34.59 44.48,-34.59 5.58,-5.02 -6.2,-15.95 -15.69,-22.37 z m 15.48,114.75 c 5.12,4.8 10.6,-5.38 20.83,-16.95 10.35,-11.84 46.67,-30.68 46.67,-30.68 5.91,-4.46 -5.65,-15.61 -15.02,-22.3 -9.37,-6.71 -10.94,-2.75 -10.94,-2.75 0,0 -26.56,13.47 -36.67,31.33 -10.02,17.62 -10.04,36.54 -4.87,41.35 z m 101.12,357.36 c 0,0 5.89,-0.99 3.23,-9.33 -2.65,-8.32 -3.16,-34.13 4.89,-45.23 8.1,-11.15 -5.54,-6.92 -16.19,4.34 -10.67,11.21 -18.21,31.85 -15.91,45.89 0,0 -0.61,5.9 23.98,4.33 z m -37.63,-68.3 c 12.91,-14.43 -6.86,-10.58 -23.41,3.64 -16.55,14.19 -30.1,41.88 -28.85,61.86 0,0 -1.69,8.18 33.05,9.59 0,0 8.44,-0.55 5.83,-12.61 -2.48,-12.03 0.45,-48.16 13.38,-62.48 z m -71.11,-9.21 c 12.65,-18.42 -9.32,-11.03 -26.12,7.75 -16.81,18.79 -28.16,52.61 -23.84,75.41 0,0 -0.74,9.57 39.08,5.91 0,0 9.54,-1.9 4.91,-15.26 -4.74,-13.49 -6.65,-55.37 5.97,-73.81 z m -108.01,18.58 c -16.99,21.48 -27.18,59.39 -21,84.23 0,0 -0.14,10.67 42.87,4.7 0,0 10.17,-2.58 4.24,-17.17 -5.94,-14.56 -10.76,-60.64 1.73,-81.59 12.48,-20.92 -10.85,-11.75 -27.84,9.83 z m -83.19,11.35 c -17.28,21.7 -27.77,60.21 -21.65,85.66 0,0 -0.23,10.79 43.27,5.3 0,0 10.31,-2.5 4.38,-17.43 -5.91,-14.92 -10.54,-62 2.15,-83.15 12.76,-21.18 -10.88,-12.13 -28.15,9.62 z m -80.49,-21.24 c -20.89,28.13 -34.89,78.07 -29.36,111.18 0,0 -0.81,14.15 48.98,7.34 0,0 11.95,-3.12 6.04,-22.7 -5.94,-19.46 -8.65,-80.67 7.02,-108.11 15.66,-27.4 -11.77,-15.8 -32.68,12.29 z m -80.64,17.63 c -20.8,24.29 -34.51,68.64 -28.73,98.66 0,0 -0.78,12.7 49.2,8.87 0,0 11.96,-2.3 5.84,-20.09 -6.04,-17.77 -9.17,-73 6.38,-96.98 15.61,-23.92 -11.86,-14.78 -32.69,9.54 z m -78.28,28.17 c -15.16,21.15 -23.52,58.34 -17.11,82.67 0,0 0.15,10.43 39.86,4.32 0,0 9.42,-2.59 3.47,-16.79 -5.9,-14.27 -11.67,-59.43 -0.66,-80.02 11.02,-20.57 -10.39,-11.43 -25.56,9.82 z m -61.99,15.5 c -13.96,16.84 -22.79,46.55 -18.34,66.13 0,0 -0.35,8.36 33.98,3.94 0,0 8.25,-1.95 3.73,-13.46 -4.34,-11.46 -7.34,-47.75 3.05,-64.16 10.34,-16.4 -8.43,-9.27 -22.42,7.55 z m -72.12,-11.61 c -16.8,18.79 -28.15,52.6 -23.84,75.42 0,0 -0.74,9.55 39.08,5.91 0,0 9.55,-1.9 4.91,-15.28 -4.74,-13.48 -6.65,-55.36 5.98,-73.82 12.64,-18.41 -9.33,-11.03 -26.13,7.77 z m -52.45,0.72 c -16.56,14.2 -30.11,41.9 -28.86,61.87 0,0 -1.69,8.18 33.03,9.58 0,0 8.46,-0.53 5.86,-12.6 -2.5,-12.04 0.43,-48.17 13.36,-62.48 12.91,-14.42 -6.86,-10.6 -23.39,3.63"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path88"
+ style="fill:#f4f4f4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 2806.87,3351.66 c 12.87,7 28.05,52.37 59.22,33.53 23.17,-14 34.21,-17.55 34.21,-17.55 0,0 -16.18,-4.55 -23.54,-16.71 -7.37,-12.16 -16.19,-21.52 -41.94,-17.7 -27.04,4.02 -31.99,-0.22 -45.6,-2.44 0,0 4.76,13.86 17.65,20.87"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path90"
+ style="fill:#403c3d;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 2731.38,3432.29 c -2.89,5.4 -6.88,10.28 -12.13,14.42 2.37,-6.9 3.73,-13.96 4.23,-21.22 -3.14,-2.68 -6.23,-5.31 -9.09,-7.73 -2.63,-5.05 -10.69,-11.72 -20.99,-16.09 8.17,24.85 9.15,51.24 9.72,70.8 16.89,-8.8 28.17,-20.87 34.68,-34.6 -2.09,-1.82 -4.23,-3.69 -6.42,-5.58 z m -55.32,-35.43 c -6.99,-1.61 -11.49,-3.22 -17.12,-5.22 -0.96,-0.25 -1.96,-0.53 -2.93,-0.88 l -5.24,-1.92 -0.53,-0.22 -0.83,-0.27 0.06,-0.02 c -2.29,-1 -3.88,-1.76 -3.88,-1.76 -7.42,-3.8 -15.21,-6.06 -22.62,-7.34 -45.89,9.86 -59.74,62.26 -59.74,62.26 42.87,18.87 67.1,73.24 51.84,103.15 0.43,1.12 1.42,0.94 2.43,0.7 19.43,-8.58 39.87,-22.99 49.81,-38.59 18.89,-29.6 24.49,-74.11 8.75,-109.89 z m -125.66,63.63 c -14.35,4.48 -16.31,16.03 -23.22,23.97 28.26,41.24 27.7,71.63 24.53,103.17 -0.63,1.96 0.68,1.9 2.29,3.34 55.47,-11.28 59.88,-65.49 36.07,-106.35 -11.3,-19.34 -22.34,-29.53 -39.67,-24.13 z m -46.16,50.29 c -23.48,6.74 -30.28,33.38 -39.75,44.39 25.59,27.33 24.12,51.34 23.12,73.26 -0.25,5.04 -1.16,10.64 0.87,15.61 4.78,-0.4 13.16,-1.62 20.01,-5.26 31.15,-16.48 44.04,-75.44 25.93,-110.1 -7.77,-14.86 -15.64,-22.08 -30.18,-17.9 z m -49.53,55.34 c -21.15,10.63 -33.04,24.8 -38.55,40.89 -3.24,9.42 -5.73,10.56 -3.54,22.26 4.71,25.26 6.29,53.13 -0.01,73.19 l 1.52,0.74 c 61.04,-21.54 96.06,-62.27 40.58,-137.08 z m -400.52,-594.93 c 0,0 8.46,-0.53 5.86,-12.6 -2.5,-12.04 0.43,-48.17 13.36,-62.48 12.91,-14.42 -6.86,-10.6 -23.39,3.63 -16.56,14.2 -30.11,41.9 -28.86,61.87 0,0 -1.69,8.18 33.03,9.58 z m 24.44,3.25 c 0,0 -0.74,9.55 39.08,5.91 0,0 9.55,-1.9 4.91,-15.28 -4.74,-13.48 -6.65,-55.36 5.98,-73.82 12.64,-18.41 -9.33,-11.03 -26.13,7.77 -16.8,18.79 -28.15,52.6 -23.84,75.42 z m 77.62,2.32 c 0,0 -0.35,8.36 33.98,3.94 0,0 8.25,-1.95 3.73,-13.46 -4.34,-11.46 -7.34,-47.75 3.05,-64.16 10.34,-16.4 -8.43,-9.27 -22.42,7.55 -13.96,16.84 -22.79,46.55 -18.34,66.13 z m 63.22,1.04 c 0,0 0.15,10.43 39.86,4.32 0,0 9.42,-2.59 3.47,-16.79 -5.9,-14.27 -11.67,-59.43 -0.66,-80.02 11.02,-20.57 -10.39,-11.43 -25.56,9.82 -15.16,21.15 -23.52,58.34 -17.11,82.67 z m 66.66,-12.18 c 0,0 -0.78,12.7 49.2,8.87 0,0 11.96,-2.3 5.84,-20.09 -6.04,-17.77 -9.17,-73 6.38,-96.98 15.61,-23.92 -11.86,-14.78 -32.69,9.54 -20.8,24.29 -34.51,68.64 -28.73,98.66 z m 80.01,-5.11 c 0,0 -0.81,14.15 48.98,7.34 0,0 11.95,-3.12 6.04,-22.7 -5.94,-19.46 -8.65,-80.67 7.02,-108.11 15.66,-27.4 -11.77,-15.8 -32.68,12.29 -20.89,28.13 -34.89,78.07 -29.36,111.18 z m 88.2,-4.28 c 0,0 -0.23,10.79 43.27,5.3 0,0 10.31,-2.5 4.38,-17.43 -5.91,-14.92 -10.54,-62 2.15,-83.15 12.76,-21.18 -10.88,-12.13 -28.15,9.62 -17.28,21.7 -27.77,60.21 -21.65,85.66 z m 83.84,-12.78 c 0,0 -0.14,10.67 42.87,4.7 0,0 10.17,-2.58 4.24,-17.17 -5.94,-14.56 -10.76,-60.64 1.73,-81.59 12.48,-20.92 -10.85,-11.75 -27.84,9.83 -16.99,21.48 -27.18,59.39 -21,84.23 z m 79.05,-19.65 c 0,0 -0.74,9.57 39.08,5.91 0,0 9.54,-1.9 4.91,-15.26 -4.74,-13.49 -6.65,-55.37 5.97,-73.81 12.65,-18.42 -9.32,-11.03 -26.12,7.75 -16.81,18.79 -28.16,52.61 -23.84,75.41 z m 101.86,1.14 c 0,0 8.44,-0.55 5.83,-12.61 -2.48,-12.03 0.45,-48.16 13.38,-62.48 12.91,-14.43 -6.86,-10.58 -23.41,3.64 -16.55,14.19 -30.1,41.88 -28.85,61.86 0,0 -1.69,8.18 33.05,9.59 z m 98.58,-102.42 c 10.06,7.04 23.37,24.16 40.39,12.92 -7.25,-15.06 -26.47,-24.97 -42.4,-33.22 -27.89,-14.43 -52.63,-27.06 -84.78,-35.07 54.18,8.3 92.69,30.91 133.23,51.69 4.96,-10.44 10.54,-31.37 14.21,-49.1 l 0.51,0.06 c 0,0 3.69,-9.93 2.6,-19.63 0.14,-4.63 -0.79,-8.61 -4.09,-10.8 -1.11,-1.42 -2.45,-2.74 -4.12,-3.84 -14.8,-9.71 -58.71,-31.2 -93.93,-33.75 -1.16,-0.06 -2.28,-0.21 -3.43,-0.33 l -2.59,-0.73 -0.08,0.49 c -31.94,-3.71 -52.6,-16.9 -11.76,-10.17 40.88,6.75 128.41,21.66 96.52,9.67 l 0.11,0.01 c -39.82,-15.58 -92.06,-30.84 -143.33,-25.84 -33.14,3.22 -67.42,19.51 -96.89,35.07 -29.44,15.53 -57.36,35.95 -88.83,42.42 -23.94,4.97 -43.72,-1.93 -64.59,-5.52 -13.88,-2.35 -33.24,-7.99 -41.67,0.71 -3.55,4.21 -0.72,8.52 -0.72,8.52 7.97,19.73 31.16,31.35 50.46,36.91 60.55,17.46 119.21,-14.63 177.64,-18.45 75.3,-4.94 129.29,21.21 167.54,47.98 z m -41.74,95.63 c 0,0 5.89,-0.99 3.23,-9.33 -2.65,-8.32 -3.16,-34.13 4.89,-45.23 8.1,-11.15 -5.54,-6.92 -16.19,4.34 -10.67,11.21 -18.21,31.85 -15.91,45.89 0,0 -0.61,5.9 23.98,4.33 z m 8.86,-374.35 c -7.5,-5.19 -8.69,-2.14 -8.69,-2.14 0,0 -21.23,10.05 -29.26,23.76 -7.99,13.54 -7.86,28.06 -3.68,31.85 4.18,3.75 8.57,-4.11 16.71,-13.01 8.21,-9.05 37.03,-23.24 37.03,-23.24 4.66,-3.43 -4.6,-12.04 -12.11,-17.22 z m -57.5,-52.94 c -9.37,-6.71 -10.94,-2.75 -10.94,-2.75 0,0 -26.56,13.47 -36.67,31.33 -10.02,17.62 -10.04,36.54 -4.87,41.35 5.12,4.8 10.6,-5.38 20.83,-16.95 10.35,-11.84 46.67,-30.68 46.67,-30.68 5.91,-4.46 -5.65,-15.61 -15.02,-22.3 z m -67.96,-44.82 c -9.45,-6.38 -10.83,-2.22 -10.83,-2.22 0,0 -25.47,15.59 -34.69,34.81 -9.02,18.94 -8.25,38.54 -3.03,43.27 5.27,4.75 10.24,-6.17 19.76,-18.9 9.66,-12.94 44.48,-34.59 44.48,-34.59 5.58,-5.02 -6.2,-15.95 -15.69,-22.37 z m -59.7,-50.77 c -9.51,-5.74 -10.49,-1.34 -10.49,-1.34 0,0 -23.53,17.77 -31.17,37.94 -7.55,19.98 -5.51,40.01 -0.2,44.46 5.41,4.47 9.46,-7.11 17.8,-20.77 8.45,-13.93 40.63,-38.61 40.63,-38.61 5.1,-5.54 -6.94,-15.85 -16.57,-21.68 z m -59.67,-53.19 c -10.3,-4.57 -10.76,0.29 -10.76,0.29 0,0 -21.15,22.63 -26.1,45.45 -4.9,22.54 -0.14,43.66 5.9,47.57 6.07,3.98 8.64,-9.21 15.17,-25.27 6.58,-16.12 35.51,-47.78 35.51,-47.78 4.33,-6.72 -9.26,-15.58 -19.72,-20.26 z m -57.23,-32.78 c -10.02,-3.04 -9.92,1.62 -9.92,1.62 0,0 -16.98,24.48 -18.95,47.17 -1.98,22.49 4.86,42.54 10.88,45.52 6.09,3.05 6.97,-10.1 11.18,-26.55 4.31,-16.64 27.29,-50.85 27.29,-50.85 3.2,-6.99 -10.33,-13.79 -20.48,-16.91 z m -54.59,-28.17 c -9.95,-3.25 -9.92,1.56 -9.92,1.56 0,0 -17.78,25.2 -20.43,48.68 -2.68,23.23 3.53,44 9.5,47.15 6,3.2 7.23,-10.4 12,-27.41 4.77,-17.13 28.86,-52.33 28.86,-52.33 3.41,-7.23 -9.95,-14.37 -20.01,-17.65 z m -44.74,-1.44 c -7.76,-2.56 -7.75,1.26 -7.75,1.26 0,0 -13.98,19.89 -16.1,38.44 -2.15,18.35 2.67,34.69 7.32,37.13 4.69,2.53 5.68,-8.19 9.45,-21.63 3.78,-13.49 22.67,-41.28 22.67,-41.28 2.68,-5.7 -7.73,-11.3 -15.59,-13.92 z m -42.56,7.47 c -6.76,-2.27 -6.76,1.09 -6.76,1.09 0,0 -12.23,17.5 -14.12,33.81 -1.92,16.13 2.23,30.52 6.27,32.65 4.08,2.22 4.97,-7.19 8.29,-18.98 3.33,-11.89 19.84,-36.31 19.84,-36.31 2.35,-5.03 -6.67,-9.99 -13.52,-12.26 z m 50.37,1345.42 c -8.77,5.76 -15.6,12.68 -20.53,20.31 -3.9,6.06 -9.38,15.98 -8.2,24.13 0.81,5.61 5.25,13.13 7.51,19.41 6.49,18.02 9.03,34.28 3.94,47.21 37.11,-16.36 42.93,-57.47 17.28,-111.06 z m -71.06,107.31 c 4.27,4.64 7.57,6.94 10.26,11.67 4.42,7.78 0.01,11.73 2.36,16.45 39.87,-5.15 43.3,-33.2 26.09,-72.98 -26.57,9 -33.65,26.79 -38.71,44.86 z m -16.21,42.78 c 13.88,-3.86 29.39,-11.76 14.6,-35.37 -9.08,9.72 -12.16,22.55 -14.6,35.37 z m 1173.75,-787.01 c -11.13,19.41 -23.35,38.42 -27.12,54.62 8.95,-5.92 16.34,-12.8 22.76,-20.33 -1.34,9.41 -2.92,18.74 -4.57,28.06 -9.71,7.73 -20.63,14.52 -33.49,19.89 -20.69,92.5 -65.21,150.91 -156.67,184.3 -30.66,11.19 -59.7,24.15 -89.94,37.34 1.75,98.46 -112.47,96.39 -183.64,147.07 -30.95,22.1 -66.05,62.87 -101.46,70.41 -68.48,14.6 -110.62,-33.23 -151.06,-66.63 -9.93,10.85 -24.8,21.45 -46.38,31.1 0,0 -38.6,55.15 -56.6,65.52 -1.19,0.69 -2,1.32 -2.52,1.93 -9.94,4.68 -22.41,7.31 -31.21,13.14 -8.7,5.73 -10.35,19.28 -19.05,25.84 -4.26,3.2 -10.87,6.67 -16.65,8.99 -6.98,2.81 -18.94,2.29 -25.97,6.14 -8.65,4.75 -9.34,20.2 -15.61,27.87 -6.91,8.47 -15.8,15.4 -30.18,20.24 -5.83,1.94 -14.63,2.07 -19.9,4.9 -5.88,3.18 -7.32,13.15 -11.87,19.26 -10.58,14.26 -28.45,25.31 -48.83,32.52 -4.39,1.55 -10.28,1.55 -13.49,3.71 -4.03,2.7 -4.19,9.73 -6.94,14.64 -4.25,7.58 -9.92,15.28 -19.06,19.99 -3.91,2.04 -9.92,1.85 -13.75,4.03 -4.5,2.58 -5.71,8.88 -9.5,12.57 -7.66,7.48 -16.76,13.16 -35.67,8.31 -6.7,8.69 -15.55,15.67 -29.96,18.64 l -0.44,-0.77 c 1.82,-17.24 4.29,-34.66 17.38,-46.59 -3.32,-19.81 5.98,-34.36 21.01,-46.08 3.62,-2.83 9.62,-4.32 12.72,-8.05 4.11,-4.96 2.41,-15.04 4.2,-21.26 5.56,-19.2 17.41,-36.84 37.11,-51.25 2.88,-2.12 8.38,-3.14 10.88,-5.97 5.5,-6.25 3.9,-16.74 8.05,-23.95 4.36,-7.59 11.79,-16.75 20.96,-23.81 5.03,-3.88 12.53,-5.95 17.23,-10.57 3.81,-3.73 4.86,-10.44 7.58,-16.02 7.35,-15.1 26.81,-32.59 36.15,-48.37 1.23,-2.08 2.2,-4.3 3.01,-6.54 3.89,-8.03 13.3,-25.05 26.13,-32.91 0,0 1.34,-23.63 24.86,-50.57 -47.65,2.58 -93.62,29.56 -128.96,2.76 -10.2,11.15 -42.93,19.9 -56.94,4.25 -10.33,18.01 -65.18,29.5 -75.85,1.04 -77.98,35.05 -172.08,-14.92 -202.33,-65.08 -5.61,-2.68 -10.86,-5.51 -15.82,-8.41 -21.34,6.43 -50.25,8.71 -81.54,-13.89 -30.84,-22.29 -63.08,-122.26 -57.53,-191.48 0.6,-7.41 14.64,-24.92 19.68,-59.99 5.02,-34.8 8.83,-46.22 8.83,-46.22 -6.86,-11.99 -15.04,-17.35 -16.15,-31.38 -2.42,-30.36 23.49,-46.85 47.76,-62.4 8.65,-4.04 18.42,-6.93 29.04,-7.32 6.41,-10.15 31.11,-44.55 71.94,-44.55 1.01,0 2.04,0.07 3.04,0.13 15.59,-13.13 31.86,-16.66 20.63,-0.47 -0.93,1.33 -1.72,2.83 -2.46,4.38 7.51,-4.47 16.59,-8.82 24.69,-9.61 0.16,-0.02 3.98,-0.98 7.14,-0.98 1.14,0 4.48,0 5.66,2.57 1.18,2.6 -1.2,5.38 -1.99,6.28 -3.27,3.77 -6.95,13.59 -9.72,22.76 3,-5.5 6.25,-10.71 9.9,-15.21 19.43,-23.89 46.63,-35.2 31.44,-11.41 -4.87,7.61 -7.65,17.99 -9.01,29.01 7.53,-9.28 20.49,-20.09 41.56,-24.4 17.42,-16.59 39.07,-23.38 26.1,-5.74 -3.32,4.51 -5.48,10.33 -6.77,16.68 10.5,-12.62 28.26,-28.83 50.03,-28.83 l 1.59,0.03 0.44,0.02 c 14.94,-10.11 27.45,-11.8 16.27,2.79 -4.84,6.36 -7.48,15.16 -8.67,24.45 9.87,-20.16 28.91,-47.92 61.69,-56.83 0.24,-0.1 5.89,-1.65 10.55,-1.65 3.63,0 5.93,0.93 7.02,2.92 1.59,2.87 -0.5,6.19 -1.19,7.28 -2.11,3.41 -4.08,7.64 -5.78,11.82 14.71,-8.64 25.59,-9.38 14.13,4.7 -5.91,7.26 -9.06,17.5 -10.36,28.08 8,-21.41 24.29,-51.48 56.48,-71.19 0.23,-0.11 6.03,-2.83 12.45,-2.83 3.1,0 5.87,0.64 8.26,1.84 2.05,1.07 3.39,2.8 3.94,5 1.68,6.71 -4.68,16.25 -5.25,17.03 -2.65,5.22 -7.5,16.25 -9.89,25.91 l 0.24,-0.2 c 23.26,-18.8 53.46,-27.51 34.83,-8.75 -11.31,11.4 -15.67,30.94 -16.06,46.89 6.8,-19.1 23.32,-52.18 57.54,-58.74 0.23,-0.02 5.53,-1.04 9.45,-1.04 2.17,0 4.79,0.24 5.71,2.34 0.39,0.88 0.55,2.32 -1,4.06 -2.56,2.89 -6.19,11.58 -8.12,18.61 1.62,-1.24 3.2,-2.56 4.89,-3.65 16.6,-10.91 36.19,-16.61 38.75,-13.08 5.3,-4.36 13.61,-10.09 24.89,-15.06 1.06,-2.42 2.1,-4.84 2.95,-7.27 0,0 5.26,-14.67 7.29,-22.61 -26.85,6.97 -72.8,20.47 -106.99,12.91 -27.01,-5.96 -97.4,-44.95 -80.38,-72.36 1.14,-1.83 2.59,-3.1 4.26,-4.14 l 1.05,-0.4 c 6.73,-3.59 18.58,-5.69 31.05,-5.59 l 4.53,0.13 c 7.25,0.4 26.23,3.13 32.67,5.22 18.82,6.13 35.64,2.45 35.64,2.45 l -0.25,-0.17 c 13.38,-1.57 27.5,-6.27 42.08,-13.73 15.66,-7.98 36.97,-21.16 42.4,-27.67 9.78,-11.78 -5.21,-39.4 -10.8,-56.41 -0.27,-1 -0.61,-2.05 -0.94,-3.09 l -0.39,-1.41 -0.06,0.04 c -0.79,-2.39 -1.76,-4.89 -2.81,-7.45 -0.95,1.2 -1.8,2.36 -2.43,3.44 -5.35,9.03 -8.24,16.93 -11,13.3 -2.77,-3.64 -2.9,-18.05 2.36,-31.66 0.54,-1.4 1.2,-2.73 1.91,-4.06 -6.06,-11.12 -13.42,-22.77 -21.18,-33.92 -6.03,5.72 -12.13,12.17 -15.09,17.31 -6.89,11.83 -10.56,22.21 -14.08,17.43 -3.56,-4.74 -3.65,-23.89 3.1,-41.86 2.2,-5.87 5.57,-11.18 9.09,-15.82 -5.35,-6.76 -10.57,-13.01 -15.34,-18.31 -2.14,-2.37 -4.66,-5.02 -7.34,-7.8 -7.36,7.62 -16.68,18.03 -20.45,25.58 -6.56,13.19 -9.94,24.43 -13.67,19.64 -3.72,-4.82 -4.45,-25.07 1.76,-44.65 2.55,-8.02 6.95,-15.34 11.3,-21.3 -7.98,-7.6 -16.65,-15.65 -25.55,-23.79 -5.4,7.18 -10.72,15.06 -13.16,21.1 -5.85,14.26 -8.62,26.35 -12.58,21.72 -3.89,-4.67 -5.6,-25.71 -0.35,-46.68 1.29,-5.17 3.26,-10.14 5.51,-14.74 -8.82,-7.89 -17.35,-15.45 -25.18,-22.31 -2.3,5.01 -4.22,9.75 -5.28,13.66 -4.6,16.98 -6.32,31 -10.84,26.71 -4.53,-4.2 -8.38,-26.82 -5.07,-50.86 0.31,-2.3 0.76,-4.59 1.27,-6.88 l -2.21,-1.9 c -5.11,-4.43 -10.68,-9.77 -16.44,-15.64 -1.43,4.52 -2.54,8.74 -3.13,12.25 -2.91,17.7 -3.36,31.85 -7.99,28.47 -4.62,-3.32 -10.15,-25.15 -9.04,-49.57 0.17,-3.84 0.64,-7.72 1.27,-11.52 -6.76,-7.62 -13.45,-15.51 -19.75,-23.18 -3.65,9.38 -6.95,19.1 -8.23,26.11 -3.34,18.53 -4.03,33.4 -8.76,29.75 -4.33,-3.29 -9.08,-23.12 -8.56,-46.19 -4.71,-3.45 -10.82,-19.53 -11.02,-37.76 -0.09,-6.2 1.01,-12.55 2.51,-18.29 -3.05,-4.31 -8.4,-7.29 -12.14,-12.57 -19.3,-27.05 -11.43,-59.27 30.28,-66.44 12.78,-39.46 45.17,-58.61 94.87,-59.05 6.68,-0.07 13.64,2.27 20.18,1.86 7.38,-0.5 13.46,-3.5 20.2,-3.71 36.22,-1.09 55.22,10.43 82.74,18.48 20.55,5.96 41.74,7.89 54.52,12.9 19.57,7.68 28.87,28.77 44.4,38.76 5.78,3.71 16.69,5.46 26.25,11.06 8.07,4.75 15.05,13.39 22.2,16.6 6.24,2.85 16.65,2.28 24.22,5.55 12.67,5.51 26.68,17.4 42.4,25.86 32.91,17.63 59.7,30.68 94.87,46.11 16.8,7.38 34.58,24.72 44.41,25.84 11.65,1.35 25.22,-8.4 34.31,-7.37 18.52,-22.06 24.98,-52.89 24.2,-92.52 1.1,-0.11 0.29,-9.83 0.29,-9.83 0,0 6.47,-85.09 -126.17,-131.03 -41.25,-14.28 -117.07,-51.81 -173.39,-80.72 218.91,6.81 416.91,96.33 564.01,238.52 -44.49,-11.55 -91.92,-41.79 -121.13,-44.56 -79.65,-7.55 -93.92,27.92 -30.29,33.77 24.03,2.21 59.49,4.92 87.8,18.38 49.4,23.51 100.3,46.22 127.3,60.84 4.41,5.31 8.63,10.78 12.92,16.2 -6.55,-0.08 -18.12,-1.77 -36.09,-5.44 -42.4,-8.65 -87.56,-37.47 -122.51,-43.97 -77.25,-14.32 -122.78,-0.55 -82.01,16.35 59.21,24.57 254.55,30.7 274.96,175.91 20.42,145.23 6.13,210.72 -4.09,247.53 -4.89,17.65 -15.85,43.7 -25.98,66.09 -2.85,15.8 -6.61,29.2 -9.88,38.76 -1.84,4.31 -3.67,9.85 -5.48,16.85 0,0 -2.55,17.91 5.61,35.28 7.23,15.43 32.05,48.86 33.73,81.2 0.03,1.96 0.11,3.92 0.08,5.88 -0.1,2.19 -0.29,4.35 -0.63,6.51 l -0.18,1.91 c -3.19,18.14 -13.58,30.77 -27.69,40.18 -9.09,6.04 -21.46,7.95 -28.26,16.59 5.42,17.09 22.71,23.17 29.91,37.14 4.5,12.39 0.83,25.42 -6.01,37.26 -13.17,14.79 -39.04,27.62 -62.26,36.33 -29.07,10.92 -58.62,19.54 -78.59,35.23 -21.11,11.25 -35.29,33.01 -22.34,61.76 3.37,7.48 4.87,15 4.77,22.16 l -0.09,2.09 c -0.03,1.46 -0.23,2.77 -0.41,4.12 -0.16,1.04 -0.33,2.07 -0.56,3.09 l -0.47,1.79 -0.56,2.02 c -5.32,17.95 -33.54,23.01 -43.6,23.9 -22.79,2.05 -37.52,8.24 -49.63,12.08 9.74,-5.08 19.54,-11.85 32.01,-16.88 7.9,-3.22 19.23,-5.15 28.78,-8.33 l 0.07,0.01 c 0,0 17.62,-3.57 22.46,-15.85 4.85,-12.27 2.04,-23.01 0,-29.9 l -0.74,-1.99 c -1.76,-5.39 -3.73,-10.57 -4.14,-15.93 -1.65,-21.14 11.3,-32.16 18.17,-49.84 12.39,-11.79 30.03,-24 54.5,-35.05 21.98,-9.96 48.29,-15.98 64.59,-25.84 9.45,-5.71 26.64,-19.51 26.25,-29.55 -0.3,-7.68 -14.47,-18.17 -20.19,-25.82 -4.07,-5.45 -6.11,-12.68 -9.75,-17.83 -3.19,-5.02 -7.26,-8.26 -11.96,-8.26 -6.12,0 -20.08,-2.37 -10.89,-3.06 9.18,-0.68 33.01,-11.93 33.01,-11.93 l -0.02,-0.03 c 32.2,-13.33 53.84,-38.06 42,-73.32 -9.91,-29.53 -32.71,-54.25 -34.31,-86.74 -1.7,-34.56 14.12,-63.03 16.14,-90.44 3.42,-46.12 -3.19,-77.9 -12.1,-112.58 -4.18,-16.21 -6.4,-32.18 -10.09,-47.96 -15.72,-67.21 -56.27,-96.32 -111.03,-127.36 -23.74,-13.46 -49.22,-38.28 -74.69,-46.13 -4.09,-1.26 -10.41,0.66 -14.14,0 -23.46,-4.25 -44.57,-15.89 -68.63,-20.3 -22.66,-4.17 -46.42,-2.18 -73.31,-8.99 -13.65,-4.88 -31.13,-12.18 -41.34,-16.53 -15.79,-7.19 -31.26,-14.69 -46.7,-22.26 L 2782.7,2380 c 0,0 -28.58,-16.57 3.07,-4.31 25.46,9.88 112.97,53.51 76.31,27.89 -25.28,-12.72 -38.99,-30.79 -61.35,-46.2 0,0 -75.23,-37.37 -86.52,-47.81 -12.4,-11.48 -27.56,-5.13 -37.52,-16.37 -11.69,-13.22 -26.02,-21.13 -36.24,-24.55 -10.2,-3.43 -21.77,-25.92 -37.43,-37.5 -15.66,-11.59 -49.68,-8.18 -79.64,-21.14 -29.94,-12.95 -60.97,-13.12 -60.97,-13.12 -2.98,-0.28 -5.85,-0.46 -8.61,-0.54 -1.18,-0.02 -2.28,0 -3.41,0 -17.52,-0.1 -30.91,3.31 -41.17,7.09 -12.51,4.61 -17.1,2.3 -14.29,0.78 2.8,-1.54 10.95,-9.16 10.95,-9.16 -34.93,0.04 -44.47,23.3 -60.55,40.57 7.31,1.04 28.16,-4.06 17.57,2.08 -20.92,10.03 -61.21,10.74 -61.99,34.85 -0.61,18.9 8.07,14.77 8.07,14.77 14.65,-25.56 59.89,-28.07 92.87,-27.71 61.43,0.73 103.01,34.49 143.27,53.58 13.05,7.86 28.3,18.19 28.3,18.19 l -0.09,-0.31 c 12.72,8.3 25.56,16.35 36.43,26.37 18.96,17.45 31.78,40.22 48.46,59.56 1.94,3.28 6.01,7.3 10.85,11.33 4.7,4.43 9.76,8.54 15.38,12.15 l 0.22,-0.45 2.18,1.47 -0.39,0.82 c 40.51,23.02 78.28,48.49 110.13,79.41 l 0.22,0.36 c 4.56,4.16 28.54,30.96 40.13,43.98 13.65,18.24 23.49,41.29 29.19,64.5 2.06,8.4 0.75,18.61 4.03,27.7 5.08,14.1 17.87,26.65 26.25,40.58 8.68,14.51 14.42,30.31 20.18,46.15 25.25,69.52 54.45,124.86 109,162.4 26.29,18.11 58.21,29.77 76.7,57.24 -13.42,-13.68 -30.91,-23.63 -52.03,-30.26 -59.98,-19.78 -98.99,-70.5 -118.6,-102.69 -15.06,-27.12 -26.7,-57.34 -35.25,-90.38 -2.85,40.73 -12.88,72.51 -26.25,103.36 -11.89,27.42 -22.4,56.41 -44.41,73.8 0,0 -0.85,-0.05 -4.26,2.02 -3.4,2.02 56.74,3.53 56.74,3.53 10.53,-0.38 21.23,-1.88 32.09,-3.3 2.03,0.22 4.53,0.11 7.59,-0.44 33.06,-5.84 67.43,6.49 88.83,22.1 11.11,8.1 30.43,14.59 46.46,18.98 0.27,0.7 1.83,1.48 5.83,2.26 0,0 24.5,7.65 50.53,14.82 17.63,4.84 30.48,8.54 39.39,12.95 5.17,3.29 10.09,7.25 13.9,11.99 7.63,9.42 7.77,20.74 14.14,36.9 6.33,16.1 16.01,28.63 16.14,42.45 0.46,45.3 -42.37,81.38 -88.81,57.23 45.72,11.8 78.15,-10.54 72.67,-53.55 -6.76,-53.12 -86.66,-92.5 -135.25,-112.57 -19.26,-7.94 -41.82,-17.98 -64.59,-20.29 -32.85,-3.33 -62.6,3.7 -90.84,1.86 -36.22,-2.4 -60.3,-21.58 -90.84,-24.01 -26.24,-2.1 -22.68,15.68 -45.45,17.71 -4.72,2.68 -19.04,0 -33.28,0.73 -39.38,-10.42 -64.7,7.62 -96.88,22.16 -23.21,10.51 -47.98,20.06 -72.68,22.15 -62,5.27 -99.7,-3.37 -150.38,2.01 -14.29,1.53 -43.95,3.33 -58.03,8.62 -43.84,16.43 -77.41,10.48 -125.04,11.15 -34.65,0.51 -66.8,2.33 -88.43,-1.46 -5.9,-1.07 -11.87,-2.6 -18.18,-3.7 -46.42,-8.13 -117.12,-12.34 -115.05,-53.52 3.46,2.37 2.5,8.77 8.07,9.23 -0.2,-7.58 -0.39,-15.14 2.01,-20.32 -26.99,0.7 -42.91,19.37 -42.38,40.6 0.9,36.12 58.9,51.22 98.91,60.92 40.1,9.7 81.75,21.05 111.03,25.84 -70.13,-10.33 -144.31,-16.97 -197.84,-42.47 -0.75,2.77 -1.24,5.45 -1.55,8.02 -4.24,19.49 -13.48,49.4 -19.98,78.46 -7.48,33.4 4.07,92.05 4.07,92.05 l 0.29,-0.34 c 4.83,29.8 10.98,43.09 16.94,60.9 12.69,38.01 53.68,49.94 82.38,53.55 -24.19,-17.13 -39.65,-38.36 -49.44,-66.79 -1.21,-10.09 -2.15,-19.55 -2.85,-27.9 21.73,67.74 82.33,93.09 82.33,93.09 l 19.4,20.96 -0.24,-0.95 c 33.45,32.42 77.66,57.54 133.84,59.13 28.31,0.79 62.52,-6.68 62.43,-34.49 -0.05,-15.73 -12.32,-29.09 -29.06,-36.46 4.92,-0.97 9.43,-0.29 13.51,1.4 l 17.4,19.5 c 5.74,14.26 5.24,32.26 -4.46,43.12 25.6,21.93 65.46,-2.67 62.56,-31.76 7.49,6.33 12.06,18.3 6.91,27.78 34.44,20.28 53.72,-28.88 88.39,-17.4 -3.27,9.84 -19.95,7.84 -25.04,16.05 45.31,6.5 85.06,-9.46 130.49,-5.85 2.85,-2.48 5.94,-4.94 9.21,-7.4 -84.98,-9.42 -15.93,-9.37 -15.93,-9.37 10.88,1 37.03,2.83 47.19,1.01 16.65,-3 27.39,1.06 42.09,6.82 0.36,-0.64 1.83,-0.59 2.72,1.08 7.62,3 16.41,6.34 27.56,9.36 4.32,0.61 8.66,1.72 12.88,3.09 l 1.82,0.38 0.25,0.29 c 5.83,2.03 11.31,4.46 16.01,6.75 42.83,20.61 78.34,69.18 114.92,94.66 60.61,42.19 118,-9.93 160.2,-43.76 l -0.27,-0.4 c 10.58,-7.23 24.53,-16.15 39.73,-25.48 39.71,-17.3 92.08,-32.44 120.05,-60.13 22.38,-22.15 29.99,-50.67 39.62,-80.27 8.98,-27.62 26.42,-52.03 36.22,-83.01 1.89,1.58 3.01,3.97 3.64,6.83 -0.27,2.65 -0.7,5.44 0.09,7.16 l 0.53,-0.48 c -0.11,5.41 -1.3,11.74 -3.15,18.42 -8.32,16.97 -22.86,36.29 -21.07,51.41 0,0 51.58,-26.7 110.11,-53.23 20.15,-9.14 38.61,-24.2 54.71,-41.42 l 4.7,0.11 c -0.56,-1.21 -0.5,-2.95 -0.33,-4.78 28.44,-31.94 48.61,-69.98 55.62,-91.97 1.45,-4.52 3.08,-9.09 4.84,-13.64 l 0.01,-0.06 c 2.21,-5.73 4.59,-11.4 7.04,-16.85 l 0.05,0.07 c 1.04,-1.85 1.69,-3.67 2.39,-5.51 8.44,-18.32 16.73,-33.17 19.05,-37.24 9.93,-12.38 17.35,-29.34 26.56,-40.46 -0.53,6.85 -0.88,13.75 -1.56,20.55 z m -826.19,277.09 c 87.27,-80.81 98.01,-168.37 104.71,-193.66 6.6,-25.12 9.82,-16.62 9.82,-16.62 1.21,85.58 -66.47,193.97 -127.36,229.62 -60,35.19 -215.11,29.07 -251.54,31.9 -35.85,2.74 -53.77,-42.93 -53.77,-42.93 -0.46,-9.67 7.43,1.42 7.43,1.42 23.42,42.28 44.01,34.55 44.01,34.55 74.22,-21.72 87.45,-130.94 90.54,-156.26 3.07,-25.11 9.41,-8.76 9.41,-8.76 7.21,62.85 -38.53,139.45 -48.15,149.3 -9.61,9.76 -0.43,15.3 30.23,6.7 92.32,-25.96 100.96,-174.08 106.52,-192.04 5.57,-17.89 9.03,-0.68 9.03,-0.68 -12.48,136.19 -64.16,169.77 -77.93,188.5 -5.72,7.77 40.96,8.94 61.5,-4.45 116.01,-75.08 102.99,-218.89 113.43,-198.36 10.58,20.95 -29.19,151.09 -85.08,195.37 -11.18,8.84 38.79,-6.6 57.2,-23.6 z m 214.59,112.44 c 23.17,-14 34.21,-17.55 34.21,-17.55 0,0 -16.18,-4.55 -23.54,-16.71 -7.37,-12.16 -16.19,-21.52 -41.94,-17.7 -27.04,4.02 -31.99,-0.22 -45.6,-2.44 0,0 4.76,13.86 17.65,20.87 12.87,7 28.05,52.37 59.22,33.53 z m 2.05,33.45 c 8.47,2.44 35.81,-1.73 18.17,1.85 -17.72,4.96 -28.72,-0.09 -40.36,-7.4 -26.76,-16.75 -48.56,-55.22 -76.72,-71.95 -12.22,-7.31 -24.17,-5.63 -34.33,-18.48 6.58,-13.17 13.26,-5.42 22.22,-7.38 19.86,-4.32 38.16,-12.04 56.52,-23.96 20.33,-13.25 42.35,-37.56 72.67,-35.09 9.67,0.77 27.24,10.15 34.32,14.77 8.84,5.77 29.83,19.54 24.22,40.6 -2.49,9.33 -13.59,10.83 -20.2,18.46 -9.15,10.61 -8.8,21.03 -16.13,33.21 15.98,-3.22 25.13,-12.71 42.37,-14.77 -27.15,24.39 -58.44,45 -96.88,59.07 2.88,1.64 4.72,8.35 14.13,11.07 z M 2223.96,3307.9 c -2.19,16.18 -17.4,30.55 -44.41,22.16 0,0 -34.92,-7.98 -44.43,-69.84 0,0 -1.66,-31.21 8.1,-24.31 -8.22,37.5 27.37,54.49 35.53,58.3 11.48,5.13 20.97,3.4 21.69,-6.37 0.79,-10.54 -11.24,-15.2 -14.84,-26.07 12.77,7.22 41.33,24.13 38.36,46.13 z m 668.31,-133.09 c 27.34,4.37 78.51,23.3 99.04,36.15 22.28,13.93 38.84,67.36 16.13,96.94 -10.17,13.24 -34.52,30.03 -40.38,31.38 -6.68,-3.88 4.2,-7.41 6.05,-9.22 7.7,-7.6 24.88,-21.51 30.28,-33.22 11.03,-23.95 7.65,-60.6 -12.12,-73.85 -13.32,-8.9 -78.47,-33.25 -106.97,-33.21 -80.17,0.11 -88.31,88.29 -137.27,118.12 0.87,-8.43 7.02,-26.13 14.02,-35.28 27.53,-36 53.83,-110.21 131.22,-97.81"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path92"
+ style="fill:#5d802f;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 2433.33,2370.61 c 0.44,-4.18 2.32,-8.2 3.64,-12.03 0.27,19.49 1.09,47.95 21.49,59.93 3.2,1.86 6.38,2.84 9.52,2.84 8.01,0 13.14,-5.65 16.36,-12.02 -0.35,15.85 1.93,31.07 12.45,38.27 5.18,3.59 10,5.32 14.61,5.32 13.21,0 18.54,-13.65 21.4,-20.98 0.47,-1.15 0.86,-2.18 1.27,-3.11 5.43,-12.42 19.9,-37.76 26.67,-43.33 2.68,2.13 6.03,4.9 7.08,6.42 -0.37,0.5 -0.99,1.17 -1.78,2.1 -42.06,48.68 -29.05,81.43 -10.7,100.35 1.31,1.51 4.77,4.85 9.87,4.85 6.26,0 11.15,-4.56 14.53,-13.49 5.33,-14.1 26.51,-41.61 30.55,-44.43 l 0.99,-0.49 c 2.07,-1.05 4.66,-2.36 6.14,-2.36 l 1.2,0.74 c 1.32,1.41 2.02,2.65 2.41,3.58 -8.82,10.66 -39.16,50.51 -27.93,82.65 1.66,4.78 6.74,19.34 18.65,19.34 10.99,0 18.37,-13.19 20.89,-18.44 6.44,-8.21 23.48,-28.51 32.54,-33.85 2.24,-1.27 4.78,-1.95 7.56,-1.95 4.48,0 8.36,1.68 10.27,2.81 -10.65,8.04 -31.32,39.91 -24.68,67.59 2.94,12.3 13.27,17.81 22.2,17.81 4.37,0 8.25,-1.27 10.93,-3.61 1.01,-0.87 3.11,-3.14 5.94,-6.27 7.87,-8.61 26.27,-28.86 37.27,-32.77 2.14,-0.75 4.09,-1.15 5.87,-1.15 4.13,0 6.86,2.09 9.5,4.82 -0.73,0.56 -1.66,1.22 -2.86,2.02 -4.97,3.36 -29.76,28.79 -19.55,60.6 3.72,11.63 12.01,12.88 15.4,12.88 7.95,0 15.18,-5.84 18.19,-9.31 5.35,-6.09 26.76,-24.07 32.16,-24.45 4.01,0.71 2.25,2.71 8.31,10.37 5,11.5 -10.48,12.08 -25.14,16.79 -8.01,2.57 -25.83,21.87 -41.9,14.16 -16.06,-7.69 -172.23,-113.68 -103.34,-29.72 28.99,35.32 66.68,50.35 63.89,59.45 -4.26,13.83 -48.2,14.69 -60.75,23.8 -6.53,4.73 -12.16,-5.39 -16.07,-14.7 -39.01,-152.94 -175.78,-233.82 -188.79,-242.48 0,0 -35.95,-22.04 -26.53,-21.68 9.43,0.34 27.02,3.64 30.27,-26.87"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path94"
+ style="fill:#5d802f;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 2747.21,2810.08 c -62.51,-19.99 -119.08,-11.38 -119.08,-11.38 -22.18,0.52 -23.98,27.54 -27.27,49.98 -3.36,23 22.07,-23.5 53.19,-30.48 29.63,-6.74 40.8,-4.57 37.8,18.39 -3.21,24.06 27.8,-3.65 46.52,-7.14 0,0 2.3,-1.48 12,-0.96 9.68,0.53 27.48,-6.91 -3.16,-18.41"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/deps/uv/include/uv-aix.h b/deps/uv/include/uv-aix.h
new file mode 100644
index 0000000000..7dc992fa6d
--- /dev/null
+++ b/deps/uv/include/uv-aix.h
@@ -0,0 +1,32 @@
+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef UV_AIX_H
+#define UV_AIX_H
+
+#define UV_PLATFORM_LOOP_FIELDS \
+ int fs_fd; \
+
+#define UV_PLATFORM_FS_EVENT_FIELDS \
+ uv__io_t event_watcher; \
+ char *dir_filename; \
+
+#endif /* UV_AIX_H */
diff --git a/deps/uv/include/uv-threadpool.h b/deps/uv/include/uv-threadpool.h
new file mode 100644
index 0000000000..9708ebdd53
--- /dev/null
+++ b/deps/uv/include/uv-threadpool.h
@@ -0,0 +1,37 @@
+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+/*
+ * This file is private to libuv. It provides common functionality to both
+ * Windows and Unix backends.
+ */
+
+#ifndef UV_THREADPOOL_H_
+#define UV_THREADPOOL_H_
+
+struct uv__work {
+ void (*work)(struct uv__work *w);
+ void (*done)(struct uv__work *w, int status);
+ struct uv_loop_s* loop;
+ void* wq[2];
+};
+
+#endif /* UV_THREADPOOL_H_ */
diff --git a/deps/uv/include/uv-unix.h b/deps/uv/include/uv-unix.h
index d59d743ef2..bbaaefc3ed 100644
--- a/deps/uv/include/uv-unix.h
+++ b/deps/uv/include/uv-unix.h
@@ -42,8 +42,12 @@
#endif
#include <signal.h>
+#include "uv-threadpool.h"
+
#if defined(__linux__)
# include "uv-linux.h"
+#elif defined(_AIX)
+# include "uv-aix.h"
#elif defined(__sun)
# include "uv-sunos.h"
#elif defined(__APPLE__)
@@ -96,13 +100,6 @@ struct uv__async {
int wfd;
};
-struct uv__work {
- void (*work)(struct uv__work *w);
- void (*done)(struct uv__work *w, int status);
- struct uv_loop_s* loop;
- void* wq[2];
-};
-
#ifndef UV_PLATFORM_SEM_T
# define UV_PLATFORM_SEM_T sem_t
#endif
@@ -218,7 +215,7 @@ typedef struct {
#define UV_UDP_SEND_PRIVATE_FIELDS \
void* queue[2]; \
- struct sockaddr_in6 addr; \
+ struct sockaddr_storage addr; \
unsigned int nbufs; \
uv_buf_t* bufs; \
ssize_t status; \
diff --git a/deps/uv/include/uv-version.h b/deps/uv/include/uv-version.h
index 6f8e080a46..d33c8f8bde 100644
--- a/deps/uv/include/uv-version.h
+++ b/deps/uv/include/uv-version.h
@@ -32,7 +32,7 @@
#define UV_VERSION_MAJOR 0
#define UV_VERSION_MINOR 11
-#define UV_VERSION_PATCH 26
+#define UV_VERSION_PATCH 28
#define UV_VERSION_IS_RELEASE 1
#endif /* UV_VERSION_H */
diff --git a/deps/uv/include/uv-win.h b/deps/uv/include/uv-win.h
index 2f24dfe890..136b0b45de 100644
--- a/deps/uv/include/uv-win.h
+++ b/deps/uv/include/uv-win.h
@@ -30,6 +30,15 @@ typedef intptr_t ssize_t;
#endif
#include <winsock2.h>
+
+#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
+typedef struct pollfd {
+ SOCKET fd;
+ short events;
+ short revents;
+} WSAPOLLFD, *PWSAPOLLFD, *LPWSAPOLLFD;
+#endif
+
#include <mswsock.h>
#include <ws2tcpip.h>
#include <windows.h>
@@ -45,6 +54,7 @@ typedef intptr_t ssize_t;
#endif
#include "tree.h"
+#include "uv-threadpool.h"
#define MAX_PIPENAME_LEN 256
@@ -307,7 +317,11 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
/* Counter to keep track of active udp streams */ \
unsigned int active_udp_streams; \
/* Counter to started timer */ \
- uint64_t timer_counter;
+ uint64_t timer_counter; \
+ /* Threadpool */ \
+ void* wq[2]; \
+ uv_mutex_t wq_mutex; \
+ uv_async_t wq_async;
#define UV_REQ_TYPE_PRIVATE \
/* TODO: remove the req suffix */ \
@@ -395,7 +409,7 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
#define UV_TCP_PRIVATE_FIELDS \
SOCKET socket; \
- int bind_error; \
+ int delayed_error; \
union { \
struct { uv_tcp_server_fields }; \
struct { uv_tcp_connection_fields }; \
@@ -520,6 +534,7 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
unsigned int flags;
#define UV_GETADDRINFO_PRIVATE_FIELDS \
+ struct uv__work work_req; \
uv_getaddrinfo_cb getaddrinfo_cb; \
void* alloc; \
WCHAR* node; \
@@ -529,6 +544,7 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
int retcode;
#define UV_GETNAMEINFO_PRIVATE_FIELDS \
+ struct uv__work work_req; \
uv_getnameinfo_cb getnameinfo_cb; \
struct sockaddr_storage storage; \
int flags; \
@@ -547,6 +563,7 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
volatile char exit_cb_pending;
#define UV_FS_PRIVATE_FIELDS \
+ struct uv__work work_req; \
int flags; \
DWORD sys_errno_; \
union { \
@@ -572,6 +589,7 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
};
#define UV_WORK_PRIVATE_FIELDS \
+ struct uv__work work_req;
#define UV_FS_EVENT_PRIVATE_FIELDS \
struct uv_fs_event_req_s { \
diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h
index ef2f840d76..df6d9549c1 100644
--- a/deps/uv/include/uv.h
+++ b/deps/uv/include/uv.h
@@ -258,7 +258,8 @@ UV_EXTERN const char* uv_version_string(void);
*/
/*
- * Returns the default loop.
+ * Returns the initialized default loop. It may return NULL in case of
+ * allocation failture.
*/
UV_EXTERN uv_loop_t* uv_default_loop(void);
@@ -276,20 +277,24 @@ UV_EXTERN int uv_loop_close(uv_loop_t* loop);
/*
* Allocates and initializes a new loop.
- * NOTE: This function is DEPRECATED (to be removed after 0.12), users should
- * allocate the loop manually and use uv_loop_init instead.
+ *
+ * NOTE:
+ * This function is DEPRECATED (to be removed after 0.12), users should
+ * allocate the loop manually and use uv_loop_init instead.
*/
UV_EXTERN uv_loop_t* uv_loop_new(void);
/*
* Cleans up a loop once it has finished executio and frees its memory.
- * NOTE: This function is DEPRECATED (to be removed after 0.12). Users should use
- * uv_loop_close and free the memory manually instead.
+ *
+ * NOTE:
+ * This function is DEPRECATED (to be removed after 0.12). Users should use
+ * uv_loop_close and free the memory manually instead.
*/
UV_EXTERN void uv_loop_delete(uv_loop_t*);
/*
- * Returns size of the loop struct, useful for dynamic lookup with FFI
+ * Returns size of the loop struct, useful for dynamic lookup with FFI.
*/
UV_EXTERN size_t uv_loop_size(void);
@@ -316,10 +321,10 @@ UV_EXTERN int uv_run(uv_loop_t*, uv_run_mode mode);
UV_EXTERN int uv_loop_alive(const uv_loop_t* loop);
/*
- * This function will stop the event loop by forcing uv_run to end
- * as soon as possible, but not sooner than the next loop iteration.
- * If this function was called before blocking for i/o, the loop won't
- * block for i/o on this iteration.
+ * This function will stop the event loop by forcing uv_run to end as soon as
+ * possible, but not sooner than the next loop iteration.
+ * If this function was called before blocking for i/o, the loop won't block
+ * for i/o on this iteration.
*/
UV_EXTERN void uv_stop(uv_loop_t*);
@@ -398,12 +403,12 @@ typedef void (*uv_alloc_cb)(uv_handle_t* handle,
* `nread` is > 0 if there is data available, 0 if libuv is done reading for
* now, or < 0 on error.
*
- * The callee is responsible for closing the stream when an error happens.
- * Trying to read from the stream again is undefined.
+ * The callee is responsible for closing the stream when an error happens
+ * by calling uv_close(). Trying to read from the stream again is undefined.
*
* The callee is responsible for freeing the buffer, libuv does not reuse it.
* The buffer may be a null buffer (where buf->base=NULL and buf->len=0) on
- * EOF or error.
+ * error.
*/
typedef void (*uv_read_cb)(uv_stream_t* stream,
ssize_t nread,
@@ -505,17 +510,17 @@ struct uv_req_s {
};
-/* Platform-specific request types */
+/* Platform-specific request types. */
UV_PRIVATE_REQ_TYPES
/*
- * uv_shutdown_t is a subclass of uv_req_t
+ * uv_shutdown_t is a subclass of uv_req_t.
*
- * Shutdown the outgoing (write) side of a duplex stream. It waits for
- * pending write requests to complete. The handle should refer to a
- * initialized stream. req should be an uninitialized shutdown request
- * struct. The cb is called after shutdown is complete.
+ * Shutdown the outgoing (write) side of a duplex stream. It waits for pending
+ * write requests to complete. The handle should refer to a initialized stream.
+ * req should be an uninitialized shutdown request struct. The cb is called
+ * after shutdown is complete.
*/
UV_EXTERN int uv_shutdown(uv_shutdown_t* req,
uv_stream_t* handle,
@@ -540,20 +545,19 @@ struct uv_shutdown_s {
void* handle_queue[2]; \
UV_HANDLE_PRIVATE_FIELDS \
-/* The abstract base class of all handles. */
+/* The abstract base class of all handles. */
struct uv_handle_s {
UV_HANDLE_FIELDS
};
/*
- * Returns size of various handle types, useful for FFI
- * bindings to allocate correct memory without copying struct
- * definitions
+ * Returns size of various handle types, useful for FFI bindings to allocate
+ * correct memory without copying struct definitions.
*/
UV_EXTERN size_t uv_handle_size(uv_handle_type type);
/*
- * Returns size of request types, useful for dynamic lookup with FFI
+ * Returns size of request types, useful for dynamic lookup with FFI.
*/
UV_EXTERN size_t uv_req_size(uv_req_type type);
@@ -566,7 +570,7 @@ UV_EXTERN size_t uv_req_size(uv_req_type type);
* by closing it with uv_close().
*
* - A uv_pipe_t, uv_tcp_t, uv_udp_t, etc. handle - basically any handle that
- * deals with I/O - is active when it is doing something that involves I/O,
+ * deals with i/o - is active when it is doing something that involves i/o,
* like reading, writing, connecting, accepting new connections, etc.
*
* - A uv_check_t, uv_idle_t, uv_timer_t, etc. handle is active when it has
@@ -601,6 +605,7 @@ UV_EXTERN void uv_close(uv_handle_t* handle, uv_close_cb close_cb);
/*
* Constructor for uv_buf_t.
+ *
* Due to platform differences the user cannot rely on the ordering of the
* base and len members of the uv_buf_t struct. The user is responsible for
* freeing base after the uv_buf_t is done. Return struct passed by value.
@@ -617,7 +622,7 @@ UV_EXTERN uv_buf_t uv_buf_init(char* base, unsigned int len);
UV_STREAM_PRIVATE_FIELDS
/*
- * uv_stream_t is a subclass of uv_handle_t
+ * uv_stream_t is a subclass of uv_handle_t.
*
* uv_stream is an abstract class.
*
@@ -636,16 +641,16 @@ UV_EXTERN int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb);
* the connection. Before calling uv_accept use uv_*_init() must be
* called on the client. Non-zero return value indicates an error.
*
- * When the uv_connection_cb is called it is guaranteed that uv_accept will
+ * When the uv_connection_cb is called it is guaranteed that uv_accept() will
* complete successfully the first time. If you attempt to use it more than
- * once, it may fail. It is suggested to only call uv_accept once per
+ * once, it may fail. It is suggested to only call uv_accept() once per
* uv_connection_cb call.
*/
UV_EXTERN int uv_accept(uv_stream_t* server, uv_stream_t* client);
/*
* Read data from an incoming stream. The callback will be made several
- * times until there is no more data to read or uv_read_stop is called.
+ * times until there is no more data to read or uv_read_stop() is called.
* When we've reached EOF nread will be set to UV_EOF.
*
* When nread < 0, the buf parameter might not point to a valid buffer;
@@ -704,17 +709,19 @@ UV_EXTERN int uv_write2(uv_write_t* req,
uv_write_cb cb);
/*
- * Same as `uv_write()`, but won't queue write request if it can't be completed
+ * Same as uv_write(), but won't queue write request if it can't be completed
* immediately.
+ *
* Will return either:
- * - >= 0: number of bytes written (can be less than the supplied buffer size)
- * - < 0: negative error code
+ * - > 0: number of bytes written (can be less than the supplied buffer size).
+ * - < 0: negative error code (UV_EAGAIN is returned if no data can be sent
+ * immediately).
*/
UV_EXTERN int uv_try_write(uv_stream_t* handle,
const uv_buf_t bufs[],
unsigned int nbufs);
-/* uv_write_t is a subclass of uv_req_t */
+/* uv_write_t is a subclass of uv_req_t. */
struct uv_write_s {
UV_REQ_FIELDS
uv_write_cb cb;
@@ -755,15 +762,14 @@ UV_EXTERN int uv_stream_set_blocking(uv_stream_t* handle, int blocking);
/*
* Used to determine whether a stream is closing or closed.
*
- * N.B. is only valid between the initialization of the handle
- * and the arrival of the close callback, and cannot be used
- * to validate the handle.
+ * N.B. is only valid between the initialization of the handle and the arrival
+ * of the close callback, and cannot be used to validate the handle.
*/
UV_EXTERN int uv_is_closing(const uv_handle_t* handle);
/*
- * uv_tcp_t is a subclass of uv_stream_t
+ * uv_tcp_t is a subclass of uv_stream_t.
*
* Represents a TCP stream or TCP server.
*/
@@ -795,15 +801,16 @@ UV_EXTERN int uv_tcp_keepalive(uv_tcp_t* handle,
/*
* Enable/disable simultaneous asynchronous accept requests that are
* queued by the operating system when listening for new tcp connections.
+ *
* This setting is used to tune a tcp server for the desired performance.
- * Having simultaneous accepts can significantly improve the rate of
- * accepting connections (which is why it is enabled by default) but
- * may lead to uneven load distribution in multi-process setups.
+ * Having simultaneous accepts can significantly improve the rate of accepting
+ * connections (which is why it is enabled by default) but may lead to uneven
+ * load distribution in multi-process setups.
*/
UV_EXTERN int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable);
enum uv_tcp_flags {
- /* Used with uv_tcp_bind, when an IPv6 address is used */
+ /* Used with uv_tcp_bind, when an IPv6 address is used. */
UV_TCP_IPV6ONLY = 1
};
@@ -811,11 +818,11 @@ enum uv_tcp_flags {
* Bind the handle to an address and port. `addr` should point to an
* initialized struct sockaddr_in or struct sockaddr_in6.
*
- * When the port is already taken, you can expect to see an UV_EADDRINUSE
- * error from either uv_tcp_bind(), uv_listen() or uv_tcp_connect().
+ * When the port is already taken, you can expect to see an UV_EADDRINUSE error
+ * from either uv_tcp_bind(), uv_listen() or uv_tcp_connect().
*
- * That is, a successful call to uv_tcp_bind() does not guarantee that
- * the call to uv_listen() or uv_tcp_connect() will succeed as well.
+ * That is, a successful call to uv_tcp_bind() does not guarantee that the call
+ * to uv_listen() or uv_tcp_connect() will succeed as well.
*/
UV_EXTERN int uv_tcp_bind(uv_tcp_t* handle,
const struct sockaddr* addr,
@@ -829,7 +836,7 @@ UV_EXTERN int uv_tcp_getpeername(const uv_tcp_t* handle,
/*
* Establish an IPv4 or IPv6 TCP connection. Provide an initialized TCP handle
- * and an uninitialized uv_connect_t*. `addr` should point to an initialized
+ * and an uninitialized uv_connect_t*. `addr` should point to an initialized
* struct sockaddr_in or struct sockaddr_in6.
*
* The callback is made when the connection has been established or when a
@@ -840,7 +847,7 @@ UV_EXTERN int uv_tcp_connect(uv_connect_t* req,
const struct sockaddr* addr,
uv_connect_cb cb);
-/* uv_connect_t is a subclass of uv_req_t */
+/* uv_connect_t is a subclass of uv_req_t. */
struct uv_connect_s {
UV_REQ_FIELDS
uv_connect_cb cb;
@@ -861,9 +868,10 @@ enum uv_udp_flags {
* remainder was discarded by the OS. Used in uv_udp_recv_cb.
*/
UV_UDP_PARTIAL = 2,
- /* Indicates if SO_REUSEADDR will be set when binding the handle.
+ /*
+ * Indicates if SO_REUSEADDR will be set when binding the handle.
* This sets the SO_REUSEPORT socket flag on the BSDs and OS X. On other
- * UNIX platforms, it sets the SO_REUSEADDR flag. What that means is that
+ * Unix platforms, it sets the SO_REUSEADDR flag. What that means is that
* multiple threads or processes can bind to the same address without error
* (provided they all set the flag) but only the last one to bind will receive
* any traffic, in effect "stealing" the port from the previous listener.
@@ -872,8 +880,7 @@ enum uv_udp_flags {
};
/*
- * Called after uv_udp_send(). status 0 indicates
- * success otherwise error.
+ * Called after uv_udp_send(). status 0 indicates success otherwise error.
*/
typedef void (*uv_udp_send_cb)(uv_udp_send_t* req, int status);
@@ -882,14 +889,20 @@ typedef void (*uv_udp_send_cb)(uv_udp_send_t* req, int status);
*
* handle UDP handle.
* nread Number of bytes that have been received.
- * 0 if there is no more data to read. You may
- * discard or repurpose the read buffer.
- * < 0 if a transmission error was detected.
+ * - 0 if there is no more data to read. You may discard or repurpose
+ * the read buffer. Note that 0 may also mean that an empty datagram
+ * was received (in this case `addr` is not NULL).
+ * - < 0 if a transmission error was detected.
* buf uv_buf_t with the received data.
- * addr struct sockaddr* containing the address of the sender.
- * Can be NULL. Valid for the duration of the callback only.
- * flags One or more OR'ed UV_UDP_* constants.
- * Right now only UV_UDP_PARTIAL is used.
+ * addr struct sockaddr* containing the address of the sender. Can be NULL.
+ * Valid for the duration of the callback only.
+ * flags One or more OR'ed UV_UDP_* constants. Right now only UV_UDP_PARTIAL
+ * is used.
+ *
+ * NOTE:
+ * The receive callback will be called with nread == 0 and addr == NULL when
+ * there is nothing to read, and with nread == 0 and addr != NULL when an empty
+ * UDP packet is received.
*/
typedef void (*uv_udp_recv_cb)(uv_udp_t* handle,
ssize_t nread,
@@ -897,13 +910,23 @@ typedef void (*uv_udp_recv_cb)(uv_udp_t* handle,
const struct sockaddr* addr,
unsigned flags);
-/* uv_udp_t is a subclass of uv_handle_t */
+/* uv_udp_t is a subclass of uv_handle_t. */
struct uv_udp_s {
UV_HANDLE_FIELDS
+ /* read-only */
+ /*
+ * Number of bytes queued for sending. This field strictly shows how much
+ * information is currently queued.
+ */
+ size_t send_queue_size;
+ /*
+ * Number of send requests currently in the queue awaiting to be processed.
+ */
+ size_t send_queue_count;
UV_UDP_PRIVATE_FIELDS
};
-/* uv_udp_send_t is a subclass of uv_req_t */
+/* uv_udp_send_t is a subclass of uv_req_t. */
struct uv_udp_send_s {
UV_REQ_FIELDS
uv_udp_t* handle;
@@ -921,16 +944,16 @@ UV_EXTERN int uv_udp_init(uv_loop_t*, uv_udp_t* handle);
* Opens an existing file descriptor or SOCKET as a udp handle.
*
* Unix only:
- * The only requirement of the sock argument is that it follows the
- * datagram contract (works in unconnected mode, supports sendmsg()/recvmsg(),
- * etc.). In other words, other datagram-type sockets like raw sockets or
- * netlink sockets can also be passed to this function.
- *
- * This sets the SO_REUSEPORT socket flag on the BSDs and OS X. On other
- * UNIX platforms, it sets the SO_REUSEADDR flag. What that means is that
- * multiple threads or processes can bind to the same address without error
- * (provided they all set the flag) but only the last one to bind will receive
- * any traffic, in effect "stealing" the port from the previous listener.
+ * The only requirement of the sock argument is that it follows the datagram
+ * contract (works in unconnected mode, supports sendmsg()/recvmsg(), etc).
+ * In other words, other datagram-type sockets like raw sockets or netlink
+ * sockets can also be passed to this function.
+ *
+ * This sets the SO_REUSEPORT socket flag on the BSDs and OS X. On other Unix
+ * platforms, it sets the SO_REUSEADDR flag. What that means is that multiple
+ * threads or processes can bind to the same address without error (provided
+ * they all set the flag) but only the last one to bind will receive any
+ * traffic, in effect "stealing" the port from the previous listener.
* This behavior is something of an anomaly and may be replaced by an explicit
* opt-in mechanism in future versions of libuv.
*/
@@ -940,7 +963,7 @@ UV_EXTERN int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock);
* Bind to an IP address and port.
*
* Arguments:
- * handle UDP handle. Should have been initialized with `uv_udp_init`.
+ * handle UDP handle. Should have been initialized with uv_udp_init().
* addr struct sockaddr_in or struct sockaddr_in6 with the address and
* port to bind to.
* flags Indicate how the socket will be bound, UV_UDP_IPV6ONLY and
@@ -953,7 +976,7 @@ UV_EXTERN int uv_udp_bind(uv_udp_t* handle,
const struct sockaddr* addr,
unsigned int flags);
-UV_EXTERN int uv_udp_getsockname(uv_udp_t* handle,
+UV_EXTERN int uv_udp_getsockname(const uv_udp_t* handle,
struct sockaddr* name,
int* namelen);
@@ -962,10 +985,10 @@ UV_EXTERN int uv_udp_getsockname(uv_udp_t* handle,
*
* Arguments:
* handle UDP handle. Should have been initialized with
- * `uv_udp_init`.
- * multicast_addr multicast address to set membership for
- * interface_addr interface address
- * membership Should be UV_JOIN_GROUP or UV_LEAVE_GROUP
+ * uv_udp_init().
+ * multicast_addr multicast address to set membership for.
+ * interface_addr interface address.
+ * membership Should be UV_JOIN_GROUP or UV_LEAVE_GROUP.
*
* Returns:
* 0 on success, or an error code < 0 on failure.
@@ -981,8 +1004,8 @@ UV_EXTERN int uv_udp_set_membership(uv_udp_t* handle,
*
* Arguments:
* handle UDP handle. Should have been initialized with
- * `uv_udp_init`.
- * on 1 for on, 0 for off
+ * uv_udp_init().
+ * on 1 for on, 0 for off.
*
* Returns:
* 0 on success, or an error code < 0 on failure.
@@ -990,12 +1013,12 @@ UV_EXTERN int uv_udp_set_membership(uv_udp_t* handle,
UV_EXTERN int uv_udp_set_multicast_loop(uv_udp_t* handle, int on);
/*
- * Set the multicast ttl
+ * Set the multicast ttl.
*
* Arguments:
* handle UDP handle. Should have been initialized with
- * `uv_udp_init`.
- * ttl 1 through 255
+ * uv_udp_init().
+ * ttl 1 through 255.
*
* Returns:
* 0 on success, or an error code < 0 on failure.
@@ -1004,12 +1027,12 @@ UV_EXTERN int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl);
/*
- * Set the multicast interface to send on
+ * Set the multicast interface to send on.
*
* Arguments:
* handle UDP handle. Should have been initialized with
- * `uv_udp_init`.
- * interface_addr interface address
+ * uv_udp_init().
+ * interface_addr interface address.
*
* Returns:
* 0 on success, or an error code < 0 on failure.
@@ -1018,12 +1041,12 @@ UV_EXTERN int uv_udp_set_multicast_interface(uv_udp_t* handle,
const char* interface_addr);
/*
- * Set broadcast on or off
+ * Set broadcast on or off.
*
* Arguments:
* handle UDP handle. Should have been initialized with
- * `uv_udp_init`.
- * on 1 for on, 0 for off
+ * uv_udp_init().
+ * on 1 for on, 0 for off.
*
* Returns:
* 0 on success, or an error code < 0 on failure.
@@ -1031,12 +1054,12 @@ UV_EXTERN int uv_udp_set_multicast_interface(uv_udp_t* handle,
UV_EXTERN int uv_udp_set_broadcast(uv_udp_t* handle, int on);
/*
- * Set the time to live
+ * Set the time to live.
*
* Arguments:
* handle UDP handle. Should have been initialized with
- * `uv_udp_init`.
- * ttl 1 through 255
+ * uv_udp_init().
+ * ttl 1 through 255.
*
* Returns:
* 0 on success, or an error code < 0 on failure.
@@ -1044,13 +1067,12 @@ UV_EXTERN int uv_udp_set_broadcast(uv_udp_t* handle, int on);
UV_EXTERN int uv_udp_set_ttl(uv_udp_t* handle, int ttl);
/*
- * Send data. If the socket has not previously been bound with `uv_udp_bind,`
- * it is bound to 0.0.0.0 (the "all interfaces" address) and a random
- * port number.
+ * Send data. If the socket has not previously been bound with uv_udp_bind() it
+ * is bound to 0.0.0.0 (the "all interfaces" address) and a random port number.
*
* Arguments:
* req UDP request handle. Need not be initialized.
- * handle UDP handle. Should have been initialized with `uv_udp_init`.
+ * handle UDP handle. Should have been initialized with uv_udp_init().
* bufs List of buffers to send.
* nbufs Number of buffers in `bufs`.
* addr struct sockaddr_in or struct sockaddr_in6 with the address and
@@ -1068,12 +1090,25 @@ UV_EXTERN int uv_udp_send(uv_udp_send_t* req,
uv_udp_send_cb send_cb);
/*
- * Receive data. If the socket has not previously been bound with `uv_udp_bind`
- * it is bound to 0.0.0.0 (the "all interfaces" address) and a random
- * port number.
+ * Same as uv_udp_send(), but won't queue a send request if it can't be completed
+ * immediately.
+ *
+ * Will return either:
+ * - >= 0: number of bytes sent (it matches the given buffer size).
+ * - < 0: negative error code (UV_EAGAIN is returned when the message can't be
+ * sent immediately).
+ */
+UV_EXTERN int uv_udp_try_send(uv_udp_t* handle,
+ const uv_buf_t bufs[],
+ unsigned int nbufs,
+ const struct sockaddr* addr);
+/*
+ * Receive data. If the socket has not previously been bound with uv_udp_bind()
+ * it is bound to 0.0.0.0 (the "all interfaces" address) and a random port
+ * number.
*
* Arguments:
- * handle UDP handle. Should have been initialized with `uv_udp_init`.
+ * handle UDP handle. Should have been initialized with uv_udp_init().
* alloc_cb Callback to invoke when temporary storage is needed.
* recv_cb Callback to invoke with received data.
*
@@ -1088,7 +1123,7 @@ UV_EXTERN int uv_udp_recv_start(uv_udp_t* handle,
* Stop listening for incoming datagrams.
*
* Arguments:
- * handle UDP handle. Should have been initialized with `uv_udp_init`.
+ * handle UDP handle. Should have been initialized with uv_udp_init().
*
* Returns:
* 0 on success, or an error code < 0 on failure.
@@ -1097,7 +1132,7 @@ UV_EXTERN int uv_udp_recv_stop(uv_udp_t* handle);
/*
- * uv_tty_t is a subclass of uv_stream_t
+ * uv_tty_t is a subclass of uv_stream_t.
*
* Representing a stream for the console.
*/
@@ -1109,12 +1144,12 @@ struct uv_tty_s {
/*
* Initialize a new TTY stream with the given file descriptor. Usually the
- * file descriptor will be
+ * file descriptor will be:
* 0 = stdin
* 1 = stdout
* 2 = stderr
* The last argument, readable, specifies if you plan on calling
- * uv_read_start with this stream. stdin is readable, stdout is not.
+ * uv_read_start() with this stream. stdin is readable, stdout is not.
*
* TTY streams which are not readable have blocking writes.
*/
@@ -1129,7 +1164,7 @@ UV_EXTERN int uv_tty_set_mode(uv_tty_t*, int mode);
* To be called when the program exits. Resets TTY settings to default
* values for the next process to take over.
*
- * This function is async signal-safe on UNIX platforms but can fail with error
+ * This function is async signal-safe on Unix platforms but can fail with error
* code UV_EBUSY if you call it when execution is inside uv_tty_set_mode().
*/
UV_EXTERN int uv_tty_reset_mode(void);
@@ -1143,15 +1178,16 @@ UV_EXTERN int uv_tty_get_winsize(uv_tty_t*, int* width, int* height);
* Used to detect what type of stream should be used with a given file
* descriptor. Usually this will be used during initialization to guess the
* type of the stdio streams.
+ *
* For isatty() functionality use this function and test for UV_TTY.
*/
UV_EXTERN uv_handle_type uv_guess_handle(uv_file file);
/*
- * uv_pipe_t is a subclass of uv_stream_t
+ * uv_pipe_t is a subclass of uv_stream_t.
*
* Representing a pipe stream or pipe server. On Windows this is a Named
- * Pipe. On Unix this is a UNIX domain socket.
+ * Pipe. On Unix this is a Unix domain socket.
*/
struct uv_pipe_s {
UV_HANDLE_FIELDS
@@ -1172,17 +1208,17 @@ UV_EXTERN int uv_pipe_init(uv_loop_t*, uv_pipe_t* handle, int ipc);
UV_EXTERN int uv_pipe_open(uv_pipe_t*, uv_file file);
/*
- * Bind the pipe to a file path (UNIX) or a name (Windows.)
+ * Bind the pipe to a file path (Unix) or a name (Windows).
*
- * Paths on UNIX get truncated to `sizeof(sockaddr_un.sun_path)` bytes,
+ * Paths on Unix get truncated to `sizeof(sockaddr_un.sun_path)` bytes,
* typically between 92 and 108 bytes.
*/
UV_EXTERN int uv_pipe_bind(uv_pipe_t* handle, const char* name);
/*
- * Connect to the UNIX domain socket or the named pipe.
+ * Connect to the Unix domain socket or the named pipe.
*
- * Paths on UNIX get truncated to `sizeof(sockaddr_un.sun_path)` bytes,
+ * Paths on Unix get truncated to `sizeof(sockaddr_un.sun_path)` bytes,
* typically between 92 and 108 bytes.
*/
UV_EXTERN void uv_pipe_connect(uv_connect_t* req,
@@ -1191,12 +1227,12 @@ UV_EXTERN void uv_pipe_connect(uv_connect_t* req,
uv_connect_cb cb);
/*
- * Get the name of the UNIX domain socket or the named pipe.
+ * Get the name of the Unix domain socket or the named pipe.
*
- * A preallocated buffer must be provided. The len parameter holds the
- * length of the buffer and it's set to the number of bytes written to the
- * buffer on output. If the buffer is not big enough UV_ENOBUFS will be
- * returned and len will contain the required size.
+ * A preallocated buffer must be provided. The len parameter holds the length
+ * of the buffer and it's set to the number of bytes written to the buffer on
+ * output. If the buffer is not big enough UV_ENOBUFS will be returned and len
+ * will contain the required size.
*/
UV_EXTERN int uv_pipe_getsockname(const uv_pipe_t* handle,
char* buf,
@@ -1204,17 +1240,18 @@ UV_EXTERN int uv_pipe_getsockname(const uv_pipe_t* handle,
/*
* This setting applies to Windows only.
- * Set the number of pending pipe instance handles when the pipe server
- * is waiting for connections.
+ *
+ * Set the number of pending pipe instance handles when the pipe server is
+ * waiting for connections.
*/
UV_EXTERN void uv_pipe_pending_instances(uv_pipe_t* handle, int count);
/*
* Used to receive handles over ipc pipes.
*
- * First - call `uv_pipe_pending_count`, if it is > 0 - initialize handle
- * using type, returned by `uv_pipe_pending_type` and call
- * `uv_accept(pipe, handle)`.
+ * First - call uv_pipe_pending_count(), if it is > 0 - initialize handle
+ * using type, returned by uv_pipe_pending_type() and call
+ * uv_accept(pipe, handle).
*/
UV_EXTERN int uv_pipe_pending_count(uv_pipe_t* handle);
UV_EXTERN uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle);
@@ -1227,10 +1264,10 @@ UV_EXTERN uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle);
*
* The purpose of uv_poll is to enable integrating external libraries that
* rely on the event loop to signal it about the socket status changes, like
- * c-ares or libssh2. Using uv_poll_t for any other other purpose is not
- * recommended; uv_tcp_t, uv_udp_t, etc. provide an implementation that is
- * much faster and more scalable than what can be achieved with uv_poll_t,
- * especially on Windows.
+ * c-ares or libssh2. Using uv_poll_t for any other purpose is not recommended;
+ * uv_tcp_t, uv_udp_t, etc. provide an implementation that is much faster and
+ * more scalable than what can be achieved with uv_poll_t, especially on
+ * Windows.
*
* It is possible that uv_poll occasionally signals that a file descriptor is
* readable or writable even when it isn't. The user should therefore always
@@ -1245,7 +1282,7 @@ UV_EXTERN uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle);
* but it might also start polling another socket. However the fd can be safely
* closed immediately after a call to uv_poll_stop() or uv_close().
*
- * On windows only sockets can be polled with uv_poll. On unix any file
+ * On windows only sockets can be polled with uv_poll. On Unix any file
* descriptor that would be accepted by poll(2) can be used with uv_poll.
*/
struct uv_poll_s {
@@ -1262,8 +1299,10 @@ enum uv_poll_event {
/* Initialize the poll watcher using a file descriptor. */
UV_EXTERN int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd);
-/* Initialize the poll watcher using a socket descriptor. On unix this is */
-/* identical to uv_poll_init. On windows it takes a SOCKET handle. */
+/*
+ * Initialize the poll watcher using a socket descriptor. On Unix this is
+ * identical to uv_poll_init. On windows it takes a SOCKET handle.
+ */
UV_EXTERN int uv_poll_init_socket(uv_loop_t* loop,
uv_poll_t* handle,
uv_os_sock_t socket);
@@ -1347,11 +1386,15 @@ UV_EXTERN int uv_idle_stop(uv_idle_t* idle);
/*
* uv_async_t is a subclass of uv_handle_t.
*
- * uv_async_send wakes up the event loop and calls the async handle's callback.
- * There is no guarantee that every uv_async_send call leads to exactly one
- * invocation of the callback; the only guarantee is that the callback function
- * is called at least once after the call to async_send. Unlike all other
- * libuv functions, uv_async_send can be called from another thread.
+ * uv_async_send() wakes up the event loop and calls the async handle's callback.
+ *
+ * Unlike all other libuv functions, uv_async_send() can be called from another
+ * thread.
+ *
+ * NOTE:
+ * There is no guarantee that every uv_async_send() call leads to exactly one
+ * invocation of the callback; the only guarantee is that the callback
+ * function is called at least once after the call to async_send.
*/
struct uv_async_s {
UV_HANDLE_FIELDS
@@ -1420,7 +1463,7 @@ UV_EXTERN uint64_t uv_timer_get_repeat(const uv_timer_t* handle);
/*
- * uv_getaddrinfo_t is a subclass of uv_req_t
+ * uv_getaddrinfo_t is a subclass of uv_req_t.
*
* Request object for uv_getaddrinfo.
*/
@@ -1464,7 +1507,7 @@ UV_EXTERN void uv_freeaddrinfo(struct addrinfo* ai);
/*
-* uv_getnameinfo_t is a subclass of uv_req_t
+* uv_getnameinfo_t is a subclass of uv_req_t.
*
* Request object for uv_getnameinfo.
*/
@@ -1490,14 +1533,15 @@ UV_EXTERN int uv_getnameinfo(uv_loop_t* loop,
int flags);
-/* uv_spawn() options */
+/* uv_spawn() options. */
typedef enum {
UV_IGNORE = 0x00,
UV_CREATE_PIPE = 0x01,
UV_INHERIT_FD = 0x02,
UV_INHERIT_STREAM = 0x04,
- /* When UV_CREATE_PIPE is specified, UV_READABLE_PIPE and UV_WRITABLE_PIPE
+ /*
+ * When UV_CREATE_PIPE is specified, UV_READABLE_PIPE and UV_WRITABLE_PIPE
* determine the direction of flow, from the child process' perspective. Both
* flags may be specified to create a duplex data stream.
*/
@@ -1578,7 +1622,7 @@ enum uv_process_flags {
/*
* Do not wrap any arguments in quotes, or perform any other escaping, when
* converting the argument list into a command line string. This option is
- * only meaningful on Windows systems. On unix it is silently ignored.
+ * only meaningful on Windows systems. On Unix it is silently ignored.
*/
UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS = (1 << 2),
/*
@@ -1591,14 +1635,14 @@ enum uv_process_flags {
UV_PROCESS_DETACHED = (1 << 3),
/*
* Hide the subprocess console window that would normally be created. This
- * option is only meaningful on Windows systems. On unix it is silently
+ * option is only meaningful on Windows systems. On Unix it is silently
* ignored.
*/
UV_PROCESS_WINDOWS_HIDE = (1 << 4)
};
/*
- * uv_process_t is a subclass of uv_handle_t
+ * uv_process_t is a subclass of uv_handle_t.
*/
struct uv_process_s {
UV_HANDLE_FIELDS
@@ -1625,7 +1669,7 @@ UV_EXTERN int uv_spawn(uv_loop_t* loop,
/*
* Kills the process with the specified signal. The user must still
- * call uv_close on the process.
+ * call uv_close() on the process.
*
* Emulates some aspects of Unix exit status on Windows, in that while the
* underlying process will be terminated with a status of `1`,
@@ -1651,7 +1695,7 @@ UV_EXTERN int uv_kill(int pid, int signum);
/*
- * uv_work_t is a subclass of uv_req_t
+ * uv_work_t is a subclass of uv_req_t.
*/
struct uv_work_s {
UV_REQ_FIELDS
@@ -1686,7 +1730,7 @@ UV_EXTERN int uv_queue_work(uv_loop_t* loop,
* - A uv_work_t or uv_getaddrinfo_t request has its callback invoked with
* status == UV_ECANCELED.
*
- * This function is currently only implemented on UNIX platforms. On Windows,
+ * This function is currently only implemented on Unix platforms. On Windows,
* it always returns UV_ENOSYS.
*/
UV_EXTERN int uv_cancel(uv_req_t* req);
@@ -1755,15 +1799,15 @@ typedef struct {
UV_EXTERN int uv_getrusage(uv_rusage_t* rusage);
/*
- * This allocates cpu_infos array, and sets count. The array
- * is freed using uv_free_cpu_info().
+ * This allocates cpu_infos array, and sets count. The array is freed
+ * using uv_free_cpu_info().
*/
UV_EXTERN int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count);
UV_EXTERN void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count);
/*
- * This allocates addresses array, and sets count. The array
- * is freed using uv_free_interface_addresses().
+ * This allocates addresses array, and sets count. The array is freed
+ * using uv_free_interface_addresses().
*/
UV_EXTERN int uv_interface_addresses(uv_interface_address_t** addresses,
int* count);
@@ -1805,6 +1849,7 @@ typedef enum {
UV_FS_UNLINK,
UV_FS_RMDIR,
UV_FS_MKDIR,
+ UV_FS_MKDTEMP,
UV_FS_RENAME,
UV_FS_READDIR,
UV_FS_LINK,
@@ -1814,7 +1859,7 @@ typedef enum {
UV_FS_FCHOWN
} uv_fs_type;
-/* uv_fs_t is a subclass of uv_req_t */
+/* uv_fs_t is a subclass of uv_req_t. */
struct uv_fs_s {
UV_REQ_FIELDS
uv_fs_type fs_type;
@@ -1823,7 +1868,7 @@ struct uv_fs_s {
ssize_t result;
void* ptr;
const char* path;
- uv_stat_t statbuf; /* Stores the result of uv_fs_stat and uv_fs_fstat. */
+ uv_stat_t statbuf; /* Stores the result of uv_fs_stat() and uv_fs_fstat(). */
UV_FS_PRIVATE_FIELDS
};
@@ -1847,6 +1892,9 @@ UV_EXTERN int uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file file,
UV_EXTERN int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path,
int mode, uv_fs_cb cb);
+UV_EXTERN int uv_fs_mkdtemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl,
+ uv_fs_cb cb);
+
UV_EXTERN int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path,
uv_fs_cb cb);
@@ -1890,14 +1938,14 @@ UV_EXTERN int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path,
const char* new_path, uv_fs_cb cb);
/*
- * This flag can be used with uv_fs_symlink on Windows
- * to specify whether path argument points to a directory.
+ * This flag can be used with uv_fs_symlink() on Windows to specify whether
+ * path argument points to a directory.
*/
#define UV_FS_SYMLINK_DIR 0x0001
/*
- * This flag can be used with uv_fs_symlink on Windows
- * to specify whether the symlink is to be created using junction points.
+ * This flag can be used with uv_fs_symlink() on Windows to specify whether
+ * the symlink is to be created using junction points.
*/
#define UV_FS_SYMLINK_JUNCTION 0x0002
@@ -1975,7 +2023,7 @@ UV_EXTERN int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buf, size_t* len);
/*
- * UNIX signal handling on a per-event loop basis. The implementation is not
+ * Unix signal handling on a per-event loop basis. The implementation is not
* ultra efficient so don't go creating a million event loops with a million
* signal watchers.
*
@@ -2030,14 +2078,16 @@ UV_EXTERN int uv_signal_stop(uv_signal_t* handle);
/*
* Gets load average.
+ *
* See: http://en.wikipedia.org/wiki/Load_(computing)
+ *
* Returns [0,0,0] on Windows.
*/
UV_EXTERN void uv_loadavg(double avg[3]);
/*
- * Flags to be passed to uv_fs_event_start.
+ * Flags to be passed to uv_fs_event_start().
*/
enum uv_fs_event_flags {
/*
@@ -2088,32 +2138,34 @@ UV_EXTERN int uv_fs_event_getpath(uv_fs_event_t* handle,
size_t* len);
-/* Utility */
+/* Utilities. */
-/* Convert string ip addresses to binary structures */
+/* Convert string ip addresses to binary structures. */
UV_EXTERN int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr);
UV_EXTERN int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr);
-/* Convert binary addresses to strings */
+/* Convert binary addresses to strings. */
UV_EXTERN int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size);
UV_EXTERN int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size);
-/* Cross-platform IPv6-capable implementation of the 'standard' inet_ntop */
-/* and inet_pton functions. On success they return 0. If an error */
-/* the target of the `dst` pointer is unmodified. */
+/*
+ * Cross-platform IPv6-capable implementation of the 'standard' inet_ntop() and
+ * inet_pton() functions. On success they return 0. If an error the target of
+ * the `dst` pointer is unmodified.
+ */
UV_EXTERN int uv_inet_ntop(int af, const void* src, char* dst, size_t size);
UV_EXTERN int uv_inet_pton(int af, const char* src, void* dst);
-/* Gets the executable path */
+/* Gets the executable path. */
UV_EXTERN int uv_exepath(char* buffer, size_t* size);
-/* Gets the current working directory */
+/* Gets the current working directory. */
UV_EXTERN int uv_cwd(char* buffer, size_t* size);
-/* Changes the current working directory */
+/* Changes the current working directory. */
UV_EXTERN int uv_chdir(const char* dir);
-/* Gets memory info in bytes */
+/* Gets memory info in bytes. */
UV_EXTERN uint64_t uv_get_free_memory(void);
UV_EXTERN uint64_t uv_get_total_memory(void);
@@ -2139,13 +2191,13 @@ UV_EXTERN extern uint64_t uv_hrtime(void);
*
* Note that this function works on a best-effort basis: there is no guarantee
* that libuv can discover all file descriptors that were inherited. In general
- * it does a better job on Windows than it does on unix.
+ * it does a better job on Windows than it does on Unix.
*/
UV_EXTERN void uv_disable_stdio_inheritance(void);
/*
* Opens a shared library. The filename is in utf-8. Returns 0 on success and
- * -1 on error. Call `uv_dlerror(uv_lib_t*)` to get the error message.
+ * -1 on error. Call uv_dlerror(uv_lib_t*) to get the error message.
*/
UV_EXTERN int uv_dlopen(const char* filename, uv_lib_t* lib);
@@ -2166,8 +2218,8 @@ UV_EXTERN int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr);
UV_EXTERN const char* uv_dlerror(const uv_lib_t* lib);
/*
- * The mutex functions return 0 on success or an error code < 0
- * (unless the return type is void, of course).
+ * The mutex functions return 0 on success or an error code < 0 (unless the
+ * return type is void, of course).
*/
UV_EXTERN int uv_mutex_init(uv_mutex_t* handle);
UV_EXTERN void uv_mutex_destroy(uv_mutex_t* handle);
@@ -2216,31 +2268,35 @@ UV_EXTERN int uv_barrier_init(uv_barrier_t* barrier, unsigned int count);
UV_EXTERN void uv_barrier_destroy(uv_barrier_t* barrier);
UV_EXTERN int uv_barrier_wait(uv_barrier_t* barrier);
-/* Waits on a condition variable without a timeout.
+/*
+ * Waits on a condition variable without a timeout.
*
- * Note:
- * 1. callers should be prepared to deal with spurious wakeups.
+ * NOTE:
+ * 1. callers should be prepared to deal with spurious wakeups.
*/
UV_EXTERN void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex);
-/* Waits on a condition variable with a timeout in nano seconds.
+/*
+ * Waits on a condition variable with a timeout in nano seconds.
* Returns 0 for success or UV_ETIMEDOUT on timeout, It aborts when other
* errors happen.
*
- * Note:
- * 1. callers should be prepared to deal with spurious wakeups.
- * 2. the granularity of timeout on Windows is never less than one millisecond.
- * 3. uv_cond_timedwait takes a relative timeout, not an absolute time.
+ * NOTE:
+ * 1. callers should be prepared to deal with spurious wakeups.
+ * 2. the granularity of timeout on Windows is never less than one millisecond.
+ * 3. uv_cond_timedwait() takes a relative timeout, not an absolute time.
*/
UV_EXTERN int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex,
uint64_t timeout);
-/* Runs a function once and only once. Concurrent calls to uv_once() with the
+/*
+ * Runs a function once and only once. Concurrent calls to uv_once() with the
* same guard will block all callers except one (it's unspecified which one).
* The guard should be initialized statically with the UV_ONCE_INIT macro.
*/
UV_EXTERN void uv_once(uv_once_t* guard, void (*callback)(void));
-/* Thread-local storage. These functions largely follow the semantics of
+/*
+ * Thread-local storage. These functions largely follow the semantics of
* pthread_key_create(), pthread_key_delete(), pthread_getspecific() and
* pthread_setspecific().
*
@@ -2278,11 +2334,11 @@ union uv_any_req {
struct uv_loop_s {
/* User data - use this for whatever. */
void* data;
- /* Loop reference counting */
+ /* Loop reference counting. */
unsigned int active_handles;
void* handle_queue[2];
void* active_reqs[2];
- /* Internal flag to signal loop stop */
+ /* Internal flag to signal loop stop. */
unsigned int stop_flag;
UV_LOOP_PRIVATE_FIELDS
};
diff --git a/deps/uv/src/unix/threadpool.c b/deps/uv/src/threadpool.c
index 18687249b1..33890f02b5 100644
--- a/deps/uv/src/unix/threadpool.c
+++ b/deps/uv/src/threadpool.c
@@ -19,7 +19,24 @@
* IN THE SOFTWARE.
*/
-#include "internal.h"
+#include "uv-common.h"
+
+#if !defined(_WIN32)
+# include "unix/internal.h"
+#else
+# include "win/req-inl.h"
+/* TODO(saghul): unify internal req functions */
+static void uv__req_init(uv_loop_t* loop,
+ uv_req_t* req,
+ uv_req_type type) {
+ uv_req_init(loop, req);
+ req->type = type;
+ uv__req_register(loop, req);
+}
+# define uv__req_init(loop, req, type) \
+ uv__req_init((loop), (uv_req_t*)(req), (type))
+#endif
+
#include <stdlib.h>
#define MAX_THREADPOOL_SIZE 128
@@ -91,6 +108,32 @@ static void post(QUEUE* q) {
}
+#ifndef _WIN32
+UV_DESTRUCTOR(static void cleanup(void)) {
+ unsigned int i;
+
+ if (initialized == 0)
+ return;
+
+ post(&exit_message);
+
+ for (i = 0; i < nthreads; i++)
+ if (uv_thread_join(threads + i))
+ abort();
+
+ if (threads != default_threads)
+ free(threads);
+
+ uv_mutex_destroy(&mutex);
+ uv_cond_destroy(&cond);
+
+ threads = NULL;
+ nthreads = 0;
+ initialized = 0;
+}
+#endif
+
+
static void init_once(void) {
unsigned int i;
const char* val;
@@ -129,30 +172,6 @@ static void init_once(void) {
}
-UV_DESTRUCTOR(static void cleanup(void)) {
- unsigned int i;
-
- if (initialized == 0)
- return;
-
- post(&exit_message);
-
- for (i = 0; i < nthreads; i++)
- if (uv_thread_join(threads + i))
- abort();
-
- if (threads != default_threads)
- free(threads);
-
- uv_mutex_destroy(&mutex);
- uv_cond_destroy(&cond);
-
- threads = NULL;
- nthreads = 0;
- initialized = 0;
-}
-
-
void uv__work_submit(uv_loop_t* loop,
struct uv__work* w,
void (*work)(struct uv__work* w),
@@ -179,7 +198,7 @@ static int uv__work_cancel(uv_loop_t* loop, uv_req_t* req, struct uv__work* w) {
uv_mutex_unlock(&mutex);
if (!cancelled)
- return -EBUSY;
+ return UV_EBUSY;
w->work = uv__cancelled;
uv_mutex_lock(&loop->wq_mutex);
@@ -213,7 +232,7 @@ void uv__work_done(uv_async_t* handle) {
QUEUE_REMOVE(q);
w = container_of(q, struct uv__work, wq);
- err = (w->work == uv__cancelled) ? -ECANCELED : 0;
+ err = (w->work == uv__cancelled) ? UV_ECANCELED : 0;
w->done(w, err);
}
}
@@ -244,7 +263,7 @@ int uv_queue_work(uv_loop_t* loop,
uv_work_cb work_cb,
uv_after_work_cb after_work_cb) {
if (work_cb == NULL)
- return -EINVAL;
+ return UV_EINVAL;
uv__req_init(loop, req, UV_WORK);
req->loop = loop;
@@ -277,7 +296,7 @@ int uv_cancel(uv_req_t* req) {
wreq = &((uv_work_t*) req)->work_req;
break;
default:
- return -EINVAL;
+ return UV_EINVAL;
}
return uv__work_cancel(loop, req, wreq);
diff --git a/deps/uv/src/unix/aix.c b/deps/uv/src/unix/aix.c
index 2521681305..eb90111345 100644
--- a/deps/uv/src/unix/aix.c
+++ b/deps/uv/src/unix/aix.c
@@ -39,12 +39,235 @@
#include <unistd.h>
#include <fcntl.h>
#include <utmp.h>
+#include <libgen.h>
#include <sys/protosw.h>
#include <libperfstat.h>
#include <sys/proc.h>
#include <sys/procfs.h>
+#include <sys/poll.h>
+
+#include <sys/pollset.h>
+#include <ctype.h>
+#include <sys/ahafs_evProds.h>
+
+#include <sys/mntctl.h>
+#include <sys/vmount.h>
+#include <limits.h>
+#include <strings.h>
+#include <sys/vnode.h>
+
+#define RDWR_BUF_SIZE 4096
+#define EQ(a,b) (strcmp(a,b) == 0)
+
+int uv__platform_loop_init(uv_loop_t* loop, int default_loop) {
+ loop->fs_fd = -1;
+
+ /* Passing maxfd of -1 should mean the limit is determined
+ * by the user's ulimit or the global limit as per the doc */
+ loop->backend_fd = pollset_create(-1);
+
+ if (loop->backend_fd == -1)
+ return -1;
+
+ return 0;
+}
+
+
+void uv__platform_loop_delete(uv_loop_t* loop) {
+ if (loop->fs_fd != -1) {
+ uv__close(loop->fs_fd);
+ loop->fs_fd = -1;
+ }
+
+ if (loop->backend_fd != -1) {
+ pollset_destroy(loop->backend_fd);
+ loop->backend_fd = -1;
+ }
+}
+
+
+void uv__io_poll(uv_loop_t* loop, int timeout) {
+ struct pollfd events[1024];
+ struct pollfd pqry;
+ struct pollfd* pe;
+ struct poll_ctl pc;
+ QUEUE* q;
+ uv__io_t* w;
+ uint64_t base;
+ uint64_t diff;
+ int nevents;
+ int count;
+ int nfds;
+ int i;
+ int rc;
+ int add_failed;
+
+ if (loop->nfds == 0) {
+ assert(QUEUE_EMPTY(&loop->watcher_queue));
+ return;
+ }
+
+ while (!QUEUE_EMPTY(&loop->watcher_queue)) {
+ q = QUEUE_HEAD(&loop->watcher_queue);
+ QUEUE_REMOVE(q);
+ QUEUE_INIT(q);
+
+ w = QUEUE_DATA(q, uv__io_t, watcher_queue);
+ assert(w->pevents != 0);
+ assert(w->fd >= 0);
+ assert(w->fd < (int) loop->nwatchers);
+
+ pc.events = w->pevents;
+ pc.fd = w->fd;
+
+ add_failed = 0;
+ if (w->events == 0) {
+ pc.cmd = PS_ADD;
+ if (pollset_ctl(loop->backend_fd, &pc, 1)) {
+ if (errno != EINVAL) {
+ assert(0 && "Failed to add file descriptor (pc.fd) to pollset");
+ abort();
+ }
+ /* Check if the fd is already in the pollset */
+ pqry.fd = pc.fd;
+ rc = pollset_query(loop->backend_fd, &pqry);
+ switch (rc) {
+ case -1:
+ assert(0 && "Failed to query pollset for file descriptor");
+ abort();
+ case 0:
+ assert(0 && "Pollset does not contain file descriptor");
+ abort();
+ }
+ /* If we got here then the pollset already contained the file descriptor even though
+ * we didn't think it should. This probably shouldn't happen, but we can continue. */
+ add_failed = 1;
+ }
+ }
+ if (w->events != 0 || add_failed) {
+ /* Modify, potentially removing events -- need to delete then add.
+ * Could maybe mod if we knew for sure no events are removed, but
+ * content of w->events is handled above as not reliable (falls back)
+ * so may require a pollset_query() which would have to be pretty cheap
+ * compared to a PS_DELETE to be worth optimising. Alternatively, could
+ * lazily remove events, squelching them in the mean time. */
+ pc.cmd = PS_DELETE;
+ if (pollset_ctl(loop->backend_fd, &pc, 1)) {
+ assert(0 && "Failed to delete file descriptor (pc.fd) from pollset");
+ abort();
+ }
+ pc.cmd = PS_ADD;
+ if (pollset_ctl(loop->backend_fd, &pc, 1)) {
+ assert(0 && "Failed to add file descriptor (pc.fd) to pollset");
+ abort();
+ }
+ }
+
+ w->events = w->pevents;
+ }
+
+ assert(timeout >= -1);
+ base = loop->time;
+ count = 48; /* Benchmarks suggest this gives the best throughput. */
+
+ for (;;) {
+ nfds = pollset_poll(loop->backend_fd,
+ events,
+ ARRAY_SIZE(events),
+ timeout);
+
+ /* Update loop->time unconditionally. It's tempting to skip the update when
+ * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the
+ * operating system didn't reschedule our process while in the syscall.
+ */
+ SAVE_ERRNO(uv__update_time(loop));
+
+ if (nfds == 0) {
+ assert(timeout != -1);
+ return;
+ }
+
+ if (nfds == -1) {
+ if (errno != EINTR) {
+ abort();
+ }
+
+ if (timeout == -1)
+ continue;
+
+ if (timeout == 0)
+ return;
+
+ /* Interrupted by a signal. Update timeout and poll again. */
+ goto update_timeout;
+ }
+
+ nevents = 0;
+
+ assert(loop->watchers != NULL);
+ loop->watchers[loop->nwatchers] = (void*) events;
+ loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;
+
+ for (i = 0; i < nfds; i++) {
+ pe = events + i;
+ pc.cmd = PS_DELETE;
+ pc.fd = pe->fd;
+
+ /* Skip invalidated events, see uv__platform_invalidate_fd */
+ if (pc.fd == -1)
+ continue;
+
+ assert(pc.fd >= 0);
+ assert((unsigned) pc.fd < loop->nwatchers);
+
+ w = loop->watchers[pc.fd];
+
+ if (w == NULL) {
+ /* File descriptor that we've stopped watching, disarm it.
+ *
+ * Ignore all errors because we may be racing with another thread
+ * when the file descriptor is closed.
+ */
+ pollset_ctl(loop->backend_fd, &pc, 1);
+ continue;
+ }
+
+ w->cb(loop, w, pe->revents);
+ nevents++;
+ }
+
+ loop->watchers[loop->nwatchers] = NULL;
+ loop->watchers[loop->nwatchers + 1] = NULL;
+
+ if (nevents != 0) {
+ if (nfds == ARRAY_SIZE(events) && --count != 0) {
+ /* Poll for more events but don't block this time. */
+ timeout = 0;
+ continue;
+ }
+ return;
+ }
+
+ if (timeout == 0)
+ return;
+
+ if (timeout == -1)
+ continue;
+
+update_timeout:
+ assert(timeout > 0);
+
+ diff = loop->time - base;
+ if (diff >= (uint64_t) timeout)
+ return;
+
+ timeout -= diff;
+ }
+}
+
+
uint64_t uv__hrtime(uv_clocktype_t type) {
uint64_t G = 1000000000;
timebasestruct_t t;
@@ -58,28 +281,24 @@ uint64_t uv__hrtime(uv_clocktype_t type) {
* We could use a static buffer for the path manipulations that we need outside
* of the function, but this function could be called by multiple consumers and
* we don't want to potentially create a race condition in the use of snprintf.
+ * There is no direct way of getting the exe path in AIX - either through /procfs
+ * or through some libc APIs. The below approach is to parse the argv[0]'s pattern
+ * and use it in conjunction with PATH environment variable to craft one.
*/
int uv_exepath(char* buffer, size_t* size) {
ssize_t res;
- char pp[64], cwdl[PATH_MAX];
+ char cwd[PATH_MAX], cwdl[PATH_MAX];
+ char symlink[PATH_MAX], temp_buffer[PATH_MAX];
+ char pp[64];
struct psinfo ps;
int fd;
+ char **argv;
- if (buffer == NULL)
- return (-1);
-
- if (size == NULL)
- return (-1);
-
- (void) snprintf(pp, sizeof(pp), "/proc/%lu/cwd", (unsigned long) getpid());
-
- res = readlink(pp, cwdl, sizeof(cwdl) - 1);
- if (res < 0)
- return res;
+ if ((buffer == NULL) || (size == NULL))
+ return -EINVAL;
- cwdl[res] = '\0';
+ snprintf(pp, sizeof(pp), "/proc/%lu/psinfo", (unsigned long) getpid());
- (void) snprintf(pp, sizeof(pp), "/proc/%lu/psinfo", (unsigned long) getpid());
fd = open(pp, O_RDONLY);
if (fd < 0)
return fd;
@@ -89,9 +308,163 @@ int uv_exepath(char* buffer, size_t* size) {
if (res < 0)
return res;
- (void) snprintf(buffer, *size, "%s%s", cwdl, ps.pr_fname);
- *size = strlen(buffer);
- return 0;
+ if (ps.pr_argv == 0)
+ return -EINVAL;
+
+ argv = (char **) *((char ***) (intptr_t) ps.pr_argv);
+
+ if ((argv == NULL) || (argv[0] == NULL))
+ return -EINVAL;
+
+ /*
+ * Three possibilities for argv[0]:
+ * i) an absolute path such as: /home/user/myprojects/nodejs/node
+ * ii) a relative path such as: ./node or ./myprojects/nodejs/node
+ * iii) a bare filename such as "node", after exporting PATH variable
+ * to its location.
+ */
+
+ /* case #1, absolute path. */
+ if (argv[0][0] == '/') {
+ snprintf(symlink, PATH_MAX-1, "%s", argv[0]);
+
+ /* This could or could not be a symlink. */
+ res = readlink(symlink, temp_buffer, PATH_MAX-1);
+
+ /* if readlink fails, it is a normal file just copy symlink to the
+ * outbut buffer.
+ */
+ if (res < 0) {
+ assert(*size > strlen(symlink));
+ strcpy(buffer, symlink);
+
+ /* If it is a link, the resolved filename is again a relative path,
+ * make it absolute.
+ */
+ } else {
+ assert(*size > (strlen(symlink) + 1 + strlen(temp_buffer)));
+ snprintf(buffer, *size-1, "%s/%s", dirname(symlink), temp_buffer);
+ }
+ *size = strlen(buffer);
+ return 0;
+
+ /* case #2, relative path with usage of '.' */
+ } else if (argv[0][0] == '.') {
+ char *relative = strchr(argv[0], '/');
+ if (relative == NULL)
+ return -EINVAL;
+
+ /* Get the current working directory to resolve the relative path. */
+ snprintf(cwd, PATH_MAX-1, "/proc/%lu/cwd", (unsigned long) getpid());
+
+ /* This is always a symlink, resolve it. */
+ res = readlink(cwd, cwdl, sizeof(cwdl) - 1);
+ if (res < 0)
+ return -errno;
+
+ snprintf(symlink, PATH_MAX-1, "%s%s", cwdl, relative + 1);
+
+ res = readlink(symlink, temp_buffer, PATH_MAX-1);
+ if (res < 0) {
+ assert(*size > strlen(symlink));
+ strcpy(buffer, symlink);
+ } else {
+ assert(*size > (strlen(symlink) + 1 + strlen(temp_buffer)));
+ snprintf(buffer, *size-1, "%s/%s", dirname(symlink), temp_buffer);
+ }
+ *size = strlen(buffer);
+ return 0;
+
+ /* case #3, relative path without usage of '.', such as invocations in Node test suite. */
+ } else if (strchr(argv[0], '/') != NULL) {
+ /* Get the current working directory to resolve the relative path. */
+ snprintf(cwd, PATH_MAX-1, "/proc/%lu/cwd", (unsigned long) getpid());
+
+ /* This is always a symlink, resolve it. */
+ res = readlink(cwd, cwdl, sizeof(cwdl) - 1);
+ if (res < 0)
+ return -errno;
+
+ snprintf(symlink, PATH_MAX-1, "%s%s", cwdl, argv[0]);
+
+ res = readlink(symlink, temp_buffer, PATH_MAX-1);
+ if (res < 0) {
+ assert(*size > strlen(symlink));
+ strcpy(buffer, symlink);
+ } else {
+ assert(*size > (strlen(symlink) + 1 + strlen(temp_buffer)));
+ snprintf(buffer, *size-1, "%s/%s", dirname(symlink), temp_buffer);
+ }
+ *size = strlen(buffer);
+ return 0;
+ /* Usage of absolute filename with location exported in PATH */
+ } else {
+ char clonedpath[8192]; /* assume 8k buffer will fit PATH */
+ char *token = NULL;
+ struct stat statstruct;
+
+ /* Get the paths. */
+ char *path = getenv("PATH");
+ if(sizeof(clonedpath) <= strlen(path))
+ return -EINVAL;
+
+ /* Get a local copy. */
+ strcpy(clonedpath, path);
+
+ /* Tokenize. */
+ token = strtok(clonedpath, ":");
+
+ /* Get current working directory. (may be required in the loop). */
+ snprintf(cwd, PATH_MAX-1, "/proc/%lu/cwd", (unsigned long) getpid());
+ res = readlink(cwd, cwdl, sizeof(cwdl) - 1);
+ if (res < 0)
+ return -errno;
+ /* Run through the tokens, append our executable file name with each,
+ * and see which one succeeds. Exit on first match. */
+ while(token != NULL) {
+ if (token[0] == '.') {
+ /* Path contains a token relative to current directory. */
+ char *relative = strchr(token, '/');
+ if (relative != NULL)
+ /* A path which is not current directory. */
+ snprintf(symlink, PATH_MAX-1, "%s%s/%s", cwdl, relative+1, ps.pr_fname);
+ else
+ snprintf(symlink, PATH_MAX-1, "%s%s", cwdl, ps.pr_fname);
+ if (stat(symlink, &statstruct) != -1) {
+ /* File exists. Resolve if it is a link. */
+ res = readlink(symlink, temp_buffer, PATH_MAX-1);
+ if (res < 0) {
+ assert(*size > strlen(symlink));
+ strcpy(buffer, symlink);
+ } else {
+ assert(*size > (strlen(symlink) + 1 + strlen(temp_buffer)));
+ snprintf(buffer, *size-1, "%s/%s", dirname(symlink), temp_buffer);
+ }
+ *size = strlen(buffer);
+ return 0;
+ }
+
+ /* Absolute path names. */
+ } else {
+ snprintf(symlink, PATH_MAX-1, "%s/%s", token, ps.pr_fname);
+ if (stat(symlink, &statstruct) != -1) {
+ res = readlink(symlink, temp_buffer, PATH_MAX-1);
+ if (res < 0) {
+ assert(*size > strlen(symlink));
+ strcpy(buffer, symlink);
+ } else {
+ assert(*size > (strlen(symlink) + 1 + strlen(temp_buffer)));
+ snprintf(buffer, *size-1, "%s/%s", dirname(symlink), temp_buffer);
+ }
+ *size = strlen(buffer);
+ return 0;
+ }
+ }
+ token = strtok(NULL, ":");
+ }
+ /* Out of tokens (path entries), and no match found */
+ return -EINVAL;
+ }
}
@@ -128,8 +501,369 @@ void uv_loadavg(double avg[3]) {
}
+static char *uv__rawname(char *cp) {
+ static char rawbuf[FILENAME_MAX+1];
+ char *dp = rindex(cp, '/');
+
+ if (dp == 0)
+ return 0;
+
+ *dp = 0;
+ strcpy(rawbuf, cp);
+ *dp = '/';
+ strcat(rawbuf, "/r");
+ strcat(rawbuf, dp+1);
+ return rawbuf;
+}
+
+
+/*
+ * Determine whether given pathname is a directory
+ * Returns 0 if the path is a directory, -1 if not
+ *
+ * Note: Opportunity here for more detailed error information but
+ * that requires changing callers of this function as well
+ */
+static int uv__path_is_a_directory(char* filename) {
+ struct stat statbuf;
+
+ if (stat(filename, &statbuf) < 0)
+ return -1; /* failed: not a directory, assume it is a file */
+
+ if (statbuf.st_type == VDIR)
+ return 0;
+
+ return -1;
+}
+
+
+/*
+ * Check whether AHAFS is mounted.
+ * Returns 0 if AHAFS is mounted, or an error code < 0 on failure
+ */
+static int uv__is_ahafs_mounted(void){
+ int rv, i = 2;
+ struct vmount *p;
+ int size_multiplier = 10;
+ size_t siz = sizeof(struct vmount)*size_multiplier;
+ struct vmount *vmt;
+ const char *dev = "/aha";
+ char *obj, *stub;
+
+ p = malloc(siz);
+ if (p == NULL)
+ return -errno;
+
+ /* Retrieve all mounted filesystems */
+ rv = mntctl(MCTL_QUERY, siz, (char*)p);
+ if (rv < 0)
+ return -errno;
+ if (rv == 0) {
+ /* buffer was not large enough, reallocate to correct size */
+ siz = *(int*)p;
+ free(p);
+ p = malloc(siz);
+ if (p == NULL)
+ return -errno;
+ rv = mntctl(MCTL_QUERY, siz, (char*)p);
+ if (rv < 0)
+ return -errno;
+ }
+
+ /* Look for dev in filesystems mount info */
+ for(vmt = p, i = 0; i < rv; i++) {
+ obj = vmt2dataptr(vmt, VMT_OBJECT); /* device */
+ stub = vmt2dataptr(vmt, VMT_STUB); /* mount point */
+
+ if (EQ(obj, dev) || EQ(uv__rawname(obj), dev) || EQ(stub, dev)) {
+ free(p); /* Found a match */
+ return 0;
+ }
+ vmt = (struct vmount *) ((char *) vmt + vmt->vmt_length);
+ }
+
+ /* /aha is required for monitoring filesystem changes */
+ return -1;
+}
+
+/*
+ * Recursive call to mkdir() to create intermediate folders, if any
+ * Returns code from mkdir call
+ */
+static int uv__makedir_p(const char *dir) {
+ char tmp[256];
+ char *p = NULL;
+ size_t len;
+ int err;
+
+ snprintf(tmp, sizeof(tmp),"%s",dir);
+ len = strlen(tmp);
+ if (tmp[len - 1] == '/')
+ tmp[len - 1] = 0;
+ for (p = tmp + 1; *p; p++) {
+ if (*p == '/') {
+ *p = 0;
+ err = mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+ if(err != 0)
+ return err;
+ *p = '/';
+ }
+ }
+ return mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+}
+
+/*
+ * Creates necessary subdirectories in the AIX Event Infrastructure
+ * file system for monitoring the object specified.
+ * Returns code from mkdir call
+ */
+static int uv__make_subdirs_p(const char *filename) {
+ char cmd[2048];
+ char *p;
+ int rc = 0;
+
+ /* Strip off the monitor file name */
+ p = strrchr(filename, '/');
+
+ if (p == NULL)
+ return 0;
+
+ if (uv__path_is_a_directory((char*)filename) == 0) {
+ sprintf(cmd, "/aha/fs/modDir.monFactory");
+ } else {
+ sprintf(cmd, "/aha/fs/modFile.monFactory");
+ }
+
+ strncat(cmd, filename, (p - filename));
+ rc = uv__makedir_p(cmd);
+
+ if (rc == -1 && errno != EEXIST){
+ return -errno;
+ }
+
+ return rc;
+}
+
+
+/*
+ * Checks if /aha is mounted, then proceeds to set up the monitoring
+ * objects for the specified file.
+ * Returns 0 on success, or an error code < 0 on failure
+ */
+static int uv__setup_ahafs(const char* filename, int *fd) {
+ int rc = 0;
+ char mon_file_write_string[RDWR_BUF_SIZE];
+ char mon_file[PATH_MAX];
+ int file_is_directory = 0; /* -1 == NO, 0 == YES */
+
+ /* Create monitor file name for object */
+ file_is_directory = uv__path_is_a_directory((char*)filename);
+
+ if (file_is_directory == 0)
+ sprintf(mon_file, "/aha/fs/modDir.monFactory");
+ else
+ sprintf(mon_file, "/aha/fs/modFile.monFactory");
+
+ if ((strlen(mon_file) + strlen(filename) + 5) > PATH_MAX)
+ return -ENAMETOOLONG;
+
+ /* Make the necessary subdirectories for the monitor file */
+ rc = uv__make_subdirs_p(filename);
+ if (rc == -1 && errno != EEXIST)
+ return rc;
+
+ strcat(mon_file, filename);
+ strcat(mon_file, ".mon");
+
+ *fd = 0; errno = 0;
+
+ /* Open the monitor file, creating it if necessary */
+ *fd = open(mon_file, O_CREAT|O_RDWR);
+ if (*fd < 0)
+ return -errno;
+
+ /* Write out the monitoring specifications.
+ * In this case, we are monitoring for a state change event type
+ * CHANGED=YES
+ * We will be waiting in select call, rather than a read:
+ * WAIT_TYPE=WAIT_IN_SELECT
+ * We only want minimal information for files:
+ * INFO_LVL=1
+ * For directories, we want more information to track what file
+ * caused the change
+ * INFO_LVL=2
+ */
+
+ if (file_is_directory == 0)
+ sprintf(mon_file_write_string, "CHANGED=YES;WAIT_TYPE=WAIT_IN_SELECT;INFO_LVL=2");
+ else
+ sprintf(mon_file_write_string, "CHANGED=YES;WAIT_TYPE=WAIT_IN_SELECT;INFO_LVL=1");
+
+ rc = write(*fd, mon_file_write_string, strlen(mon_file_write_string)+1);
+ if (rc < 0)
+ return -errno;
+
+ return 0;
+}
+
+/*
+ * Skips a specified number of lines in the buffer passed in.
+ * Walks the buffer pointed to by p and attempts to skip n lines.
+ * Returns the total number of lines skipped
+ */
+static int uv__skip_lines(char **p, int n) {
+ int lines = 0;
+
+ while(n > 0) {
+ *p = strchr(*p, '\n');
+ if (!p)
+ return lines;
+
+ (*p)++;
+ n--;
+ lines++;
+ }
+ return lines;
+}
+
+
+/*
+ * Parse the event occurrence data to figure out what event just occurred
+ * and take proper action.
+ *
+ * The buf is a pointer to the buffer containing the event occurrence data
+ * Returns 0 on success, -1 if unrecoverable error in parsing
+ *
+ */
+static int uv__parse_data(char *buf, int *events, uv_fs_event_t* handle) {
+ int evp_rc, i;
+ char *p;
+ char filename[PATH_MAX]; /* To be used when handling directories */
+
+ p = buf;
+ *events = 0;
+
+ /* Clean the filename buffer*/
+ for(i = 0; i < PATH_MAX; i++) {
+ filename[i] = 0;
+ }
+ i = 0;
+
+ /* Check for BUF_WRAP */
+ if (strncmp(buf, "BUF_WRAP", strlen("BUF_WRAP")) == 0) {
+ assert(0 && "Buffer wrap detected, Some event occurrences lost!");
+ return 0;
+ }
+
+ /* Since we are using the default buffer size (4K), and have specified
+ * INFO_LVL=1, we won't see any EVENT_OVERFLOW conditions. Applications
+ * should check for this keyword if they are using an INFO_LVL of 2 or
+ * higher, and have a buffer size of <= 4K
+ */
+
+ /* Skip to RC_FROM_EVPROD */
+ if (uv__skip_lines(&p, 9) != 9)
+ return -1;
+
+ if (sscanf(p, "RC_FROM_EVPROD=%d\nEND_EVENT_DATA", &evp_rc) == 1) {
+ if (uv__path_is_a_directory(handle->path) == 0) { /* Directory */
+ if (evp_rc == AHAFS_MODDIR_UNMOUNT || evp_rc == AHAFS_MODDIR_REMOVE_SELF) {
+ /* The directory is no longer available for monitoring */
+ *events = UV_RENAME;
+ handle->dir_filename = NULL;
+ } else {
+ /* A file was added/removed inside the directory */
+ *events = UV_CHANGE;
+
+ /* Get the EVPROD_INFO */
+ if (uv__skip_lines(&p, 1) != 1)
+ return -1;
+
+ /* Scan out the name of the file that triggered the event*/
+ if (sscanf(p, "BEGIN_EVPROD_INFO\n%sEND_EVPROD_INFO", filename) == 1) {
+ handle->dir_filename = strdup((const char*)&filename);
+ } else
+ return -1;
+ }
+ } else { /* Regular File */
+ if (evp_rc == AHAFS_MODFILE_RENAME)
+ *events = UV_RENAME;
+ else
+ *events = UV_CHANGE;
+ }
+ }
+ else
+ return -1;
+
+ return 0;
+}
+
+
+/* This is the internal callback */
+static void uv__ahafs_event(uv_loop_t* loop, uv__io_t* event_watch, unsigned int fflags) {
+ char result_data[RDWR_BUF_SIZE];
+ int bytes, rc = 0;
+ uv_fs_event_t* handle;
+ int events = 0;
+ int i = 0;
+ char fname[PATH_MAX];
+ char *p;
+
+ handle = container_of(event_watch, uv_fs_event_t, event_watcher);
+
+ /* Clean all the buffers*/
+ for(i = 0; i < PATH_MAX; i++) {
+ fname[i] = 0;
+ }
+ i = 0;
+
+ /* At this point, we assume that polling has been done on the
+ * file descriptor, so we can just read the AHAFS event occurrence
+ * data and parse its results without having to block anything
+ */
+ bytes = pread(event_watch->fd, result_data, RDWR_BUF_SIZE, 0);
+
+ assert((bytes <= 0) && "uv__ahafs_event - Error reading monitor file");
+
+ /* Parse the data */
+ if(bytes > 0)
+ rc = uv__parse_data(result_data, &events, handle);
+
+ /* For directory changes, the name of the files that triggered the change
+ * are never absolute pathnames
+ */
+ if (uv__path_is_a_directory(handle->path) == 0) {
+ p = handle->dir_filename;
+ while(*p != NULL){
+ fname[i]= *p;
+ i++;
+ p++;
+ }
+ } else {
+ /* For file changes, figure out whether filename is absolute or not */
+ if (handle->path[0] == '/') {
+ p = strrchr(handle->path, '/');
+ p++;
+
+ while(*p != NULL) {
+ fname[i]= *p;
+ i++;
+ p++;
+ }
+ }
+ }
+
+ /* Unrecoverable error */
+ if (rc == -1)
+ return;
+ else /* Call the actual JavaScript callback function */
+ handle->cb(handle, (const char*)&fname, events, 0);
+}
+
+
int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
- return -ENOSYS;
+ uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT);
+ return 0;
}
@@ -137,17 +871,99 @@ int uv_fs_event_start(uv_fs_event_t* handle,
uv_fs_event_cb cb,
const char* filename,
unsigned int flags) {
- return -ENOSYS;
+ int fd, rc, i = 0, res = 0;
+ char cwd[PATH_MAX];
+ char absolute_path[PATH_MAX];
+ char fname[PATH_MAX];
+ char *p;
+
+ /* Clean all the buffers*/
+ for(i = 0; i < PATH_MAX; i++) {
+ cwd[i] = 0;
+ absolute_path[i] = 0;
+ fname[i] = 0;
+ }
+ i = 0;
+
+ /* Figure out whether filename is absolute or not */
+ if (filename[0] == '/') {
+ /* We have absolute pathname, create the relative pathname*/
+ sprintf(absolute_path, filename);
+ p = strrchr(filename, '/');
+ p++;
+ } else {
+ if (filename[0] == '.' && filename[1] == '/') {
+ /* We have a relative pathname, compose the absolute pathname */
+ sprintf(fname, filename);
+ snprintf(cwd, PATH_MAX-1, "/proc/%lu/cwd", (unsigned long) getpid());
+ res = readlink(cwd, absolute_path, sizeof(absolute_path) - 1);
+ if (res < 0)
+ return res;
+ p = strrchr(absolute_path, '/');
+ p++;
+ p++;
+ } else {
+ /* We have a relative pathname, compose the absolute pathname */
+ sprintf(fname, filename);
+ snprintf(cwd, PATH_MAX-1, "/proc/%lu/cwd", (unsigned long) getpid());
+ res = readlink(cwd, absolute_path, sizeof(absolute_path) - 1);
+ if (res < 0)
+ return res;
+ p = strrchr(absolute_path, '/');
+ p++;
+ }
+ /* Copy to filename buffer */
+ while(filename[i] != NULL) {
+ *p = filename[i];
+ i++;
+ p++;
+ }
+ }
+
+ if (uv__is_ahafs_mounted() < 0) /* /aha checks failed */
+ return UV_ENOSYS;
+
+ /* Setup ahafs */
+ rc = uv__setup_ahafs((const char *)absolute_path, &fd);
+ if (rc != 0)
+ return rc;
+
+ /* Setup/Initialize all the libuv routines */
+ uv__handle_start(handle);
+ uv__io_init(&handle->event_watcher, uv__ahafs_event, fd);
+ handle->path = strdup((const char*)&absolute_path);
+ handle->cb = cb;
+
+ uv__io_start(handle->loop, &handle->event_watcher, UV__POLLIN);
+
+ return 0;
}
int uv_fs_event_stop(uv_fs_event_t* handle) {
- return -ENOSYS;
+
+ if (!uv__is_active(handle))
+ return 0;
+
+ uv__io_close(handle->loop, &handle->event_watcher);
+ uv__handle_stop(handle);
+
+ if (uv__path_is_a_directory(handle->path) == 0) {
+ free(handle->dir_filename);
+ handle->dir_filename = NULL;
+ }
+
+ free(handle->path);
+ handle->path = NULL;
+ uv__close(handle->event_watcher.fd);
+ handle->event_watcher.fd = -1;
+
+ return 0;
}
void uv__fs_event_close(uv_fs_event_t* handle) {
- UNREACHABLE();
+ uv_fs_event_stop(handle);
}
@@ -175,7 +991,7 @@ int uv_resident_set_memory(size_t* rss) {
int err;
int fd;
- (void) snprintf(pp, sizeof(pp), "/proc/%lu/psinfo", (unsigned long) getpid());
+ snprintf(pp, sizeof(pp), "/proc/%lu/psinfo", (unsigned long) getpid());
fd = open(pp, O_RDONLY);
if (fd == -1)
@@ -397,3 +1213,21 @@ void uv_free_interface_addresses(uv_interface_address_t* addresses,
free(addresses);
}
+
+void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
+ struct pollfd* events;
+ uintptr_t i;
+ uintptr_t nfds;
+
+ assert(loop->watchers != NULL);
+
+ events = (struct pollfd*) loop->watchers[loop->nwatchers];
+ nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
+ if (events == NULL)
+ return;
+
+ /* Invalidate events with same file descriptor */
+ for (i = 0; i < nfds; i++)
+ if ((int) events[i].fd == fd)
+ events[i].fd = -1;
+}
diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c
index 402bb00eb2..4770d8d8c6 100644
--- a/deps/uv/src/unix/core.c
+++ b/deps/uv/src/unix/core.c
@@ -70,6 +70,10 @@
# endif
#endif
+#ifdef _AIX
+#include <sys/ioctl.h>
+#endif
+
static void uv__run_pending(uv_loop_t* loop);
/* Verify that uv_buf_t is ABI-compatible with struct iovec. */
@@ -444,7 +448,8 @@ int uv__close(int fd) {
}
-#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \
+ defined(_AIX)
int uv__nonblock(int fd, int set) {
int r;
diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c
index 8a4edcbc0a..47f667229d 100644
--- a/deps/uv/src/unix/fs.c
+++ b/deps/uv/src/unix/fs.c
@@ -214,9 +214,23 @@ skip:
}
+static ssize_t uv__fs_mkdtemp(uv_fs_t* req) {
+ return mkdtemp((char*) req->path) ? 0 : -1;
+}
+
+
static ssize_t uv__fs_read(uv_fs_t* req) {
ssize_t result;
+#if defined(_AIX)
+ struct stat buf;
+ if(fstat(req->file, &buf))
+ return -1;
+ if(S_ISDIR(buf.st_mode)) {
+ errno = EISDIR;
+ return -1;
+ }
+#endif /* defined(_AIX) */
if (req->off < 0) {
if (req->nbufs == 1)
result = read(req->file, req->bufs[0].base, req->bufs[0].len);
@@ -683,7 +697,8 @@ static void uv__to_stat(struct stat* src, uv_stat_t* dst) {
dst->st_birthtim.tv_nsec = src->st_birthtimespec.tv_nsec;
dst->st_flags = src->st_flags;
dst->st_gen = src->st_gen;
-#elif defined(_BSD_SOURCE) || defined(_SVID_SOURCE) || defined(_XOPEN_SOURCE)
+#elif !defined(_AIX) && \
+ (defined(_BSD_SOURCE) || defined(_SVID_SOURCE) || defined(_XOPEN_SOURCE))
dst->st_atim.tv_sec = src->st_atim.tv_sec;
dst->st_atim.tv_nsec = src->st_atim.tv_nsec;
dst->st_mtim.tv_sec = src->st_mtim.tv_sec;
@@ -779,6 +794,7 @@ static void uv__fs_work(struct uv__work* w) {
X(LSTAT, uv__fs_lstat(req->path, &req->statbuf));
X(LINK, link(req->path, req->new_path));
X(MKDIR, mkdir(req->path, req->mode));
+ X(MKDTEMP, uv__fs_mkdtemp(req));
X(READ, uv__fs_read(req));
X(READDIR, uv__fs_readdir(req));
X(READLINK, uv__fs_readlink(req));
@@ -991,6 +1007,18 @@ int uv_fs_mkdir(uv_loop_t* loop,
}
+int uv_fs_mkdtemp(uv_loop_t* loop,
+ uv_fs_t* req,
+ const char* tpl,
+ uv_fs_cb cb) {
+ INIT(MKDTEMP);
+ req->path = strdup(tpl);
+ if (req->path == NULL)
+ return -ENOMEM;
+ POST;
+}
+
+
int uv_fs_open(uv_loop_t* loop,
uv_fs_t* req,
const char* path,
diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h
index fd29b88d42..114cb696ee 100644
--- a/deps/uv/src/unix/internal.h
+++ b/deps/uv/src/unix/internal.h
@@ -42,6 +42,12 @@
# include <port.h>
#endif /* __sun */
+#if defined(_AIX)
+#define reqevents events
+#define rtnevents revents
+#include <sys/poll.h>
+#endif /* _AIX */
+
#if defined(__APPLE__) && !TARGET_OS_IPHONE
# include <CoreServices/CoreServices.h>
#endif
@@ -89,7 +95,7 @@
# define UV__POLLHUP UV__EPOLLHUP
#endif
-#if defined(__sun)
+#if defined(__sun) || defined(_AIX)
# define UV__POLLIN POLLIN
# define UV__POLLOUT POLLOUT
# define UV__POLLERR POLLERR
@@ -210,13 +216,6 @@ void uv__signal_close(uv_signal_t* handle);
void uv__signal_global_once_init(void);
void uv__signal_loop_cleanup(uv_loop_t* loop);
-/* thread pool */
-void uv__work_submit(uv_loop_t* loop,
- struct uv__work *w,
- void (*work)(struct uv__work *w),
- void (*done)(struct uv__work *w, int status));
-void uv__work_done(uv_async_t* handle);
-
/* platform specific */
uint64_t uv__hrtime(uv_clocktype_t type);
int uv__kqueue_init(uv_loop_t* loop);
diff --git a/deps/uv/src/unix/loop.c b/deps/uv/src/unix/loop.c
index 52c9328e75..aa74be6455 100644
--- a/deps/uv/src/unix/loop.c
+++ b/deps/uv/src/unix/loop.c
@@ -89,8 +89,10 @@ uv_loop_t* uv_loop_new(void) {
void uv_loop_delete(uv_loop_t* loop) {
uv_loop_t* default_loop;
+ int err;
default_loop = default_loop_ptr;
- assert(uv_loop_close(loop) == 0);
+ err = uv_loop_close(loop);
+ assert(err == 0);
if (loop != default_loop)
free(loop);
}
diff --git a/deps/uv/src/unix/openbsd.c b/deps/uv/src/unix/openbsd.c
index 75ba921637..cde8d4d0c9 100644
--- a/deps/uv/src/unix/openbsd.c
+++ b/deps/uv/src/unix/openbsd.c
@@ -180,29 +180,23 @@ int uv_get_process_title(char* buffer, size_t size) {
int uv_resident_set_memory(size_t* rss) {
- kvm_t *kd = NULL;
- struct kinfo_proc *kinfo = NULL;
- pid_t pid;
- int nprocs, max_size = sizeof(struct kinfo_proc);
+ struct kinfo_proc kinfo;
size_t page_size = getpagesize();
+ size_t size = sizeof(struct kinfo_proc);
+ int mib[6];
- pid = getpid();
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = getpid();
+ mib[4] = sizeof(struct kinfo_proc);
+ mib[5] = 1;
- kd = kvm_open(NULL, _PATH_MEM, NULL, O_RDONLY, "kvm_open");
- if (kd == NULL) goto error;
-
- kinfo = kvm_getprocs(kd, KERN_PROC_PID, pid, max_size, &nprocs);
- if (kinfo == NULL) goto error;
-
- *rss = kinfo->p_vm_rssize * page_size;
-
- kvm_close(kd);
+ if (sysctl(mib, 6, &kinfo, &size, NULL, 0) < 0)
+ return -errno;
+ *rss = kinfo.p_vm_rssize * page_size;
return 0;
-
-error:
- if (kd) kvm_close(kd);
- return -EPERM;
}
diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c
index 43334f0efb..ae7880c33f 100644
--- a/deps/uv/src/unix/stream.c
+++ b/deps/uv/src/unix/stream.c
@@ -60,21 +60,10 @@ static void uv__stream_connect(uv_stream_t*);
static void uv__write(uv_stream_t* stream);
static void uv__read(uv_stream_t* stream);
static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events);
+static void uv__write_callbacks(uv_stream_t* stream);
static size_t uv__write_req_size(uv_write_t* req);
-static size_t uv_count_bufs(const uv_buf_t bufs[], unsigned int nbufs) {
- unsigned int i;
- size_t bytes;
-
- bytes = 0;
- for (i = 0; i < nbufs; i++)
- bytes += bufs[i].len;
-
- return bytes;
-}
-
-
void uv__stream_init(uv_loop_t* loop,
uv_stream_t* stream,
uv_handle_type type) {
@@ -390,33 +379,12 @@ void uv__stream_destroy(uv_stream_t* stream) {
QUEUE_REMOVE(q);
req = QUEUE_DATA(q, uv_write_t, queue);
- uv__req_unregister(stream->loop, req);
+ req->error = -ECANCELED;
- if (req->bufs != req->bufsml)
- free(req->bufs);
- req->bufs = NULL;
-
- if (req->cb != NULL)
- req->cb(req, -ECANCELED);
+ QUEUE_INSERT_TAIL(&stream->write_completed_queue, &req->queue);
}
- while (!QUEUE_EMPTY(&stream->write_completed_queue)) {
- q = QUEUE_HEAD(&stream->write_completed_queue);
- QUEUE_REMOVE(q);
-
- req = QUEUE_DATA(q, uv_write_t, queue);
- uv__req_unregister(stream->loop, req);
-
- if (req->bufs != NULL) {
- stream->write_queue_size -= uv__write_req_size(req);
- if (req->bufs != req->bufsml)
- free(req->bufs);
- req->bufs = NULL;
- }
-
- if (req->cb)
- req->cb(req, req->error);
- }
+ uv__write_callbacks(stream);
if (stream->shutdown_req) {
/* The ECANCELED error code is a lie, the shutdown(2) syscall is a
@@ -428,6 +396,8 @@ void uv__stream_destroy(uv_stream_t* stream) {
stream->shutdown_req->cb(stream->shutdown_req, -ECANCELED);
stream->shutdown_req = NULL;
}
+
+ assert(stream->write_queue_size == 0);
}
@@ -660,8 +630,8 @@ static size_t uv__write_req_size(uv_write_t* req) {
size_t size;
assert(req->bufs != NULL);
- size = uv_count_bufs(req->bufs + req->write_index,
- req->nbufs - req->write_index);
+ size = uv__count_bufs(req->bufs + req->write_index,
+ req->nbufs - req->write_index);
assert(req->handle->write_queue_size >= size);
return size;
@@ -903,10 +873,6 @@ static void uv__write_callbacks(uv_stream_t* stream) {
}
assert(QUEUE_EMPTY(&stream->write_completed_queue));
-
- /* Write queue drained. */
- if (QUEUE_EMPTY(&stream->write_queue))
- uv__drain(stream);
}
@@ -1223,6 +1189,10 @@ static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
if (events & (UV__POLLOUT | UV__POLLERR | UV__POLLHUP)) {
uv__write(stream);
uv__write_callbacks(stream);
+
+ /* Write queue drained. */
+ if (QUEUE_EMPTY(&stream->write_queue))
+ uv__drain(stream);
}
}
@@ -1327,7 +1297,7 @@ int uv_write2(uv_write_t* req,
memcpy(req->bufs, bufs, nbufs * sizeof(bufs[0]));
req->nbufs = nbufs;
req->write_index = 0;
- stream->write_queue_size += uv_count_bufs(bufs, nbufs);
+ stream->write_queue_size += uv__count_bufs(bufs, nbufs);
/* Append the request to write_queue. */
QUEUE_INSERT_TAIL(&stream->write_queue, &req->queue);
@@ -1386,7 +1356,7 @@ int uv_try_write(uv_stream_t* stream,
/* Connecting or already writing some data */
if (stream->connect_req != NULL || stream->write_queue_size != 0)
- return 0;
+ return -EAGAIN;
has_pollout = uv__io_active(&stream->io_watcher, UV__POLLOUT);
@@ -1395,7 +1365,7 @@ int uv_try_write(uv_stream_t* stream,
return r;
/* Remove not written bytes from write queue size */
- written = uv_count_bufs(bufs, nbufs);
+ written = uv__count_bufs(bufs, nbufs);
if (req.bufs != NULL)
req_size = uv__write_req_size(&req);
else
@@ -1416,7 +1386,10 @@ int uv_try_write(uv_stream_t* stream,
uv__stream_osx_interrupt_select(stream);
}
- return (int) written;
+ if (written == 0)
+ return -EAGAIN;
+ else
+ return written;
}
diff --git a/deps/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c
index 9556bd7e3b..bf91cbdf9f 100644
--- a/deps/uv/src/unix/udp.c
+++ b/deps/uv/src/unix/udp.c
@@ -38,10 +38,9 @@
static void uv__udp_run_completed(uv_udp_t* handle);
-static void uv__udp_run_pending(uv_udp_t* handle);
static void uv__udp_io(uv_loop_t* loop, uv__io_t* w, unsigned int revents);
-static void uv__udp_recvmsg(uv_loop_t* loop, uv__io_t* w, unsigned int revents);
-static void uv__udp_sendmsg(uv_loop_t* loop, uv__io_t* w, unsigned int revents);
+static void uv__udp_recvmsg(uv_udp_t* handle);
+static void uv__udp_sendmsg(uv_udp_t* handle);
static int uv__udp_maybe_deferred_bind(uv_udp_t* handle,
int domain,
unsigned int flags);
@@ -65,22 +64,19 @@ void uv__udp_finish_close(uv_udp_t* handle) {
assert(!uv__io_active(&handle->io_watcher, UV__POLLIN | UV__POLLOUT));
assert(handle->io_watcher.fd == -1);
- uv__udp_run_completed(handle);
-
while (!QUEUE_EMPTY(&handle->write_queue)) {
q = QUEUE_HEAD(&handle->write_queue);
QUEUE_REMOVE(q);
req = QUEUE_DATA(q, uv_udp_send_t, queue);
- uv__req_unregister(handle->loop, req);
+ req->status = -ECANCELED;
+ QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue);
+ }
- if (req->bufs != req->bufsml)
- free(req->bufs);
- req->bufs = NULL;
+ uv__udp_run_completed(handle);
- if (req->send_cb != NULL)
- req->send_cb(req, -ECANCELED);
- }
+ assert(handle->send_queue_size == 0);
+ assert(handle->send_queue_count == 0);
/* Now tear down the handle. */
handle->recv_cb = NULL;
@@ -89,50 +85,6 @@ void uv__udp_finish_close(uv_udp_t* handle) {
}
-static void uv__udp_run_pending(uv_udp_t* handle) {
- uv_udp_send_t* req;
- QUEUE* q;
- struct msghdr h;
- ssize_t size;
-
- while (!QUEUE_EMPTY(&handle->write_queue)) {
- q = QUEUE_HEAD(&handle->write_queue);
- assert(q != NULL);
-
- req = QUEUE_DATA(q, uv_udp_send_t, queue);
- assert(req != NULL);
-
- memset(&h, 0, sizeof h);
- h.msg_name = &req->addr;
- h.msg_namelen = (req->addr.sin6_family == AF_INET6 ?
- sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in));
- h.msg_iov = (struct iovec*) req->bufs;
- h.msg_iovlen = req->nbufs;
-
- do {
- size = sendmsg(handle->io_watcher.fd, &h, 0);
- }
- while (size == -1 && errno == EINTR);
-
- /* TODO try to write once or twice more in the
- * hope that the socket becomes readable again?
- */
- if (size == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
- break;
-
- req->status = (size == -1 ? -errno : size);
-
- /* Sending a datagram is an atomic operation: either all data
- * is written or nothing is (and EMSGSIZE is raised). That is
- * why we don't handle partial writes. Just pop the request
- * off the write queue and onto the completed queue, done.
- */
- QUEUE_REMOVE(&req->queue);
- QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue);
- }
-}
-
-
static void uv__udp_run_completed(uv_udp_t* handle) {
uv_udp_send_t* req;
QUEUE* q;
@@ -144,6 +96,9 @@ static void uv__udp_run_completed(uv_udp_t* handle) {
req = QUEUE_DATA(q, uv_udp_send_t, queue);
uv__req_unregister(handle->loop, req);
+ handle->send_queue_size -= uv__count_bufs(req->bufs, req->nbufs);
+ handle->send_queue_count--;
+
if (req->bufs != req->bufsml)
free(req->bufs);
req->bufs = NULL;
@@ -159,33 +114,40 @@ static void uv__udp_run_completed(uv_udp_t* handle) {
else
req->send_cb(req, req->status);
}
+
+ if (QUEUE_EMPTY(&handle->write_queue)) {
+ /* Pending queue and completion queue empty, stop watcher. */
+ uv__io_stop(handle->loop, &handle->io_watcher, UV__POLLOUT);
+ if (!uv__io_active(&handle->io_watcher, UV__POLLIN))
+ uv__handle_stop(handle);
+ }
}
static void uv__udp_io(uv_loop_t* loop, uv__io_t* w, unsigned int revents) {
+ uv_udp_t* handle;
+
+ handle = container_of(w, uv_udp_t, io_watcher);
+ assert(handle->type == UV_UDP);
+
if (revents & UV__POLLIN)
- uv__udp_recvmsg(loop, w, revents);
+ uv__udp_recvmsg(handle);
- if (revents & UV__POLLOUT)
- uv__udp_sendmsg(loop, w, revents);
+ if (revents & UV__POLLOUT) {
+ uv__udp_sendmsg(handle);
+ uv__udp_run_completed(handle);
+ }
}
-static void uv__udp_recvmsg(uv_loop_t* loop,
- uv__io_t* w,
- unsigned int revents) {
+static void uv__udp_recvmsg(uv_udp_t* handle) {
struct sockaddr_storage peer;
struct msghdr h;
- uv_udp_t* handle;
ssize_t nread;
uv_buf_t buf;
int flags;
int count;
- handle = container_of(w, uv_udp_t, io_watcher);
- assert(handle->type == UV_UDP);
- assert(revents & UV__POLLIN);
-
assert(handle->recv_cb != NULL);
assert(handle->alloc_cb != NULL);
@@ -242,34 +204,43 @@ static void uv__udp_recvmsg(uv_loop_t* loop,
}
-static void uv__udp_sendmsg(uv_loop_t* loop,
- uv__io_t* w,
- unsigned int revents) {
- uv_udp_t* handle;
+static void uv__udp_sendmsg(uv_udp_t* handle) {
+ uv_udp_send_t* req;
+ QUEUE* q;
+ struct msghdr h;
+ ssize_t size;
- handle = container_of(w, uv_udp_t, io_watcher);
- assert(handle->type == UV_UDP);
- assert(revents & UV__POLLOUT);
+ while (!QUEUE_EMPTY(&handle->write_queue)) {
+ q = QUEUE_HEAD(&handle->write_queue);
+ assert(q != NULL);
+
+ req = QUEUE_DATA(q, uv_udp_send_t, queue);
+ assert(req != NULL);
- assert(!QUEUE_EMPTY(&handle->write_queue)
- || !QUEUE_EMPTY(&handle->write_completed_queue));
+ memset(&h, 0, sizeof h);
+ h.msg_name = &req->addr;
+ h.msg_namelen = (req->addr.ss_family == AF_INET6 ?
+ sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in));
+ h.msg_iov = (struct iovec*) req->bufs;
+ h.msg_iovlen = req->nbufs;
- /* Write out pending data first. */
- uv__udp_run_pending(handle);
+ do {
+ size = sendmsg(handle->io_watcher.fd, &h, 0);
+ } while (size == -1 && errno == EINTR);
- /* Drain 'request completed' queue. */
- uv__udp_run_completed(handle);
+ if (size == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
+ break;
- if (!QUEUE_EMPTY(&handle->write_completed_queue)) {
- /* Schedule completion callbacks. */
- uv__io_feed(handle->loop, &handle->io_watcher);
- }
- else if (QUEUE_EMPTY(&handle->write_queue)) {
- /* Pending queue and completion queue empty, stop watcher. */
- uv__io_stop(loop, &handle->io_watcher, UV__POLLOUT);
+ req->status = (size == -1 ? -errno : size);
- if (!uv__io_active(&handle->io_watcher, UV__POLLIN))
- uv__handle_stop(handle);
+ /* Sending a datagram is an atomic operation: either all data
+ * is written or nothing is (and EMSGSIZE is raised). That is
+ * why we don't handle partial writes. Just pop the request
+ * off the write queue and onto the completed queue, done.
+ */
+ QUEUE_REMOVE(&req->queue);
+ QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue);
+ uv__io_feed(handle->loop, &handle->io_watcher);
}
}
@@ -410,6 +381,7 @@ int uv__udp_send(uv_udp_send_t* req,
unsigned int addrlen,
uv_udp_send_cb send_cb) {
int err;
+ int empty_queue;
assert(nbufs > 0);
@@ -417,8 +389,13 @@ int uv__udp_send(uv_udp_send_t* req,
if (err)
return err;
- uv__req_init(handle->loop, req, UV_UDP_SEND);
+ /* It's legal for send_queue_count > 0 even when the write_queue is empty;
+ * it means there are error-state requests in the write_completed_queue that
+ * will touch up send_queue_size/count later.
+ */
+ empty_queue = (handle->send_queue_count == 0);
+ uv__req_init(handle->loop, req, UV_UDP_SEND);
assert(addrlen <= sizeof(req->addr));
memcpy(&req->addr, addr, addrlen);
req->send_cb = send_cb;
@@ -433,14 +410,60 @@ int uv__udp_send(uv_udp_send_t* req,
return -ENOMEM;
memcpy(req->bufs, bufs, nbufs * sizeof(bufs[0]));
+ handle->send_queue_size += uv__count_bufs(req->bufs, req->nbufs);
+ handle->send_queue_count++;
QUEUE_INSERT_TAIL(&handle->write_queue, &req->queue);
- uv__io_start(handle->loop, &handle->io_watcher, UV__POLLOUT);
uv__handle_start(handle);
+ if (empty_queue)
+ uv__udp_sendmsg(handle);
+ else
+ uv__io_start(handle->loop, &handle->io_watcher, UV__POLLOUT);
+
return 0;
}
+int uv__udp_try_send(uv_udp_t* handle,
+ const uv_buf_t bufs[],
+ unsigned int nbufs,
+ const struct sockaddr* addr,
+ unsigned int addrlen) {
+ int err;
+ struct msghdr h;
+ ssize_t size;
+
+ assert(nbufs > 0);
+
+ /* already sending a message */
+ if (handle->send_queue_count != 0)
+ return -EAGAIN;
+
+ err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
+ if (err)
+ return err;
+
+ memset(&h, 0, sizeof h);
+ h.msg_name = (struct sockaddr*) addr;
+ h.msg_namelen = addrlen;
+ h.msg_iov = (struct iovec*) bufs;
+ h.msg_iovlen = nbufs;
+
+ do {
+ size = sendmsg(handle->io_watcher.fd, &h, 0);
+ } while (size == -1 && errno == EINTR);
+
+ if (size == -1) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
+ return -EAGAIN;
+ else
+ return -errno;
+ }
+
+ return size;
+}
+
+
static int uv__udp_set_membership4(uv_udp_t* handle,
const struct sockaddr_in* multicast_addr,
const char* interface_addr,
@@ -531,6 +554,8 @@ int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) {
uv__handle_init(loop, (uv_handle_t*)handle, UV_UDP);
handle->alloc_cb = NULL;
handle->recv_cb = NULL;
+ handle->send_queue_size = 0;
+ handle->send_queue_count = 0;
uv__io_init(&handle->io_watcher, uv__udp_io, -1);
QUEUE_INIT(&handle->write_queue);
QUEUE_INIT(&handle->write_completed_queue);
@@ -579,7 +604,7 @@ int uv_udp_set_membership(uv_udp_t* handle,
static int uv__setsockopt_maybe_char(uv_udp_t* handle, int option, int val) {
-#if defined(__sun)
+#if defined(__sun) || defined(_AIX)
char arg = val;
#else
int arg = val;
@@ -678,7 +703,9 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr)
}
-int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name, int* namelen) {
+int uv_udp_getsockname(const uv_udp_t* handle,
+ struct sockaddr* name,
+ int* namelen) {
socklen_t socklen;
if (handle->io_watcher.fd == -1)
diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c
index d9553c9162..4e3968cb44 100644
--- a/deps/uv/src/uv-common.c
+++ b/deps/uv/src/uv-common.c
@@ -233,6 +233,26 @@ int uv_udp_send(uv_udp_send_t* req,
}
+int uv_udp_try_send(uv_udp_t* handle,
+ const uv_buf_t bufs[],
+ unsigned int nbufs,
+ const struct sockaddr* addr) {
+ unsigned int addrlen;
+
+ if (handle->type != UV_UDP)
+ return UV_EINVAL;
+
+ if (addr->sa_family == AF_INET)
+ addrlen = sizeof(struct sockaddr_in);
+ else if (addr->sa_family == AF_INET6)
+ addrlen = sizeof(struct sockaddr_in6);
+ else
+ return UV_EINVAL;
+
+ return uv__udp_try_send(handle, bufs, nbufs, addr, addrlen);
+}
+
+
int uv_udp_recv_start(uv_udp_t* handle,
uv_alloc_cb alloc_cb,
uv_udp_recv_cb recv_cb) {
@@ -446,6 +466,19 @@ int uv__getaddrinfo_translate_error(int sys_err) {
return 0; /* Pacify compiler. */
}
+
+size_t uv__count_bufs(const uv_buf_t bufs[], unsigned int nbufs) {
+ unsigned int i;
+ size_t bytes;
+
+ bytes = 0;
+ for (i = 0; i < nbufs; i++)
+ bytes += (size_t) bufs[i].len;
+
+ return bytes;
+}
+
+
int uv_fs_event_getpath(uv_fs_event_t* handle, char* buf, size_t* len) {
size_t required_len;
diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h
index 3bcdcef3d4..34c287898c 100644
--- a/deps/uv/src/uv-common.h
+++ b/deps/uv/src/uv-common.h
@@ -83,6 +83,12 @@ int uv__udp_send(uv_udp_send_t* req,
unsigned int addrlen,
uv_udp_send_cb send_cb);
+int uv__udp_try_send(uv_udp_t* handle,
+ const uv_buf_t bufs[],
+ unsigned int nbufs,
+ const struct sockaddr* addr,
+ unsigned int addrlen);
+
int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloccb,
uv_udp_recv_cb recv_cb);
@@ -92,6 +98,15 @@ void uv__fs_poll_close(uv_fs_poll_t* handle);
int uv__getaddrinfo_translate_error(int sys_err); /* EAI_* error. */
+void uv__work_submit(uv_loop_t* loop,
+ struct uv__work *w,
+ void (*work)(struct uv__work *w),
+ void (*done)(struct uv__work *w, int status));
+
+void uv__work_done(uv_async_t* handle);
+
+size_t uv__count_bufs(const uv_buf_t bufs[], unsigned int nbufs);
+
#define uv__has_active_reqs(loop) \
(QUEUE_EMPTY(&(loop)->active_reqs) == 0)
diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c
index 540fb5fa0d..c39597561d 100644
--- a/deps/uv/src/win/core.c
+++ b/deps/uv/src/win/core.c
@@ -26,7 +26,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#if !defined(__MINGW32__)
+#if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR)
#include <crtdbg.h>
#endif
@@ -44,19 +44,21 @@ static uv_once_t uv_init_guard_ = UV_ONCE_INIT;
static uv_once_t uv_default_loop_init_guard_ = UV_ONCE_INIT;
-#if defined(_DEBUG) && !defined(__MINGW32__)
-/* Our crt debug report handler allows us to temporarily disable asserts */
-/* just for the current thread. */
+#if defined(_DEBUG) && (defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR))
+/* Our crt debug report handler allows us to temporarily disable asserts
+ * just for the current thread.
+ */
-__declspec( thread ) int uv__crt_assert_enabled = TRUE;
+UV_THREAD_LOCAL int uv__crt_assert_enabled = TRUE;
static int uv__crt_dbg_report_handler(int report_type, char *message, int *ret_val) {
if (uv__crt_assert_enabled || report_type != _CRT_ASSERT)
return FALSE;
if (ret_val) {
- /* Set ret_val to 0 to continue with normal execution. */
- /* Set ret_val to 1 to trigger a breakpoint. */
+ /* Set ret_val to 0 to continue with normal execution.
+ * Set ret_val to 1 to trigger a breakpoint.
+ */
if(IsDebuggerPresent())
*ret_val = 1;
@@ -67,6 +69,8 @@ static int uv__crt_dbg_report_handler(int report_type, char *message, int *ret_v
/* Don't call _CrtDbgReport. */
return TRUE;
}
+#else
+UV_THREAD_LOCAL int uv__crt_assert_enabled = FALSE;
#endif
@@ -84,21 +88,24 @@ static void uv_init(void) {
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
SEM_NOOPENFILEERRORBOX);
- /* Tell the CRT to not exit the application when an invalid parameter is */
- /* passed. The main issue is that invalid FDs will trigger this behavior. */
+ /* Tell the CRT to not exit the application when an invalid parameter is
+ * passed. The main issue is that invalid FDs will trigger this behavior.
+ */
#if !defined(__MINGW32__) || __MSVCRT_VERSION__ >= 0x800
_set_invalid_parameter_handler(uv__crt_invalid_parameter_handler);
#endif
- /* We also need to setup our debug report handler because some CRT */
- /* functions (eg _get_osfhandle) raise an assert when called with invalid */
- /* FDs even though they return the proper error code in the release build. */
-#if defined(_DEBUG) && !defined(__MINGW32__)
+ /* We also need to setup our debug report handler because some CRT
+ * functions (eg _get_osfhandle) raise an assert when called with invalid
+ * FDs even though they return the proper error code in the release build.
+ */
+#if defined(_DEBUG) && (defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR))
_CrtSetReportHook(uv__crt_dbg_report_handler);
#endif
- /* Fetch winapi function pointers. This must be done first because other */
- /* intialization code might need these function pointers to be loaded. */
+ /* Fetch winapi function pointers. This must be done first because other
+ * intialization code might need these function pointers to be loaded.
+ */
uv_winapi_init();
/* Initialize winsock */
@@ -127,12 +134,14 @@ int uv_loop_init(uv_loop_t* loop) {
if (loop->iocp == NULL)
return uv_translate_sys_error(GetLastError());
- /* To prevent uninitialized memory access, loop->time must be intialized */
- /* to zero before calling uv_update_time for the first time. */
+ /* To prevent uninitialized memory access, loop->time must be intialized
+ * to zero before calling uv_update_time for the first time.
+ */
loop->time = 0;
loop->last_tick_count = 0;
uv_update_time(loop);
+ QUEUE_INIT(&loop->wq);
QUEUE_INIT(&loop->handle_queue);
QUEUE_INIT(&loop->active_reqs);
loop->active_handles = 0;
@@ -159,6 +168,15 @@ int uv_loop_init(uv_loop_t* loop) {
loop->timer_counter = 0;
loop->stop_flag = 0;
+ if (uv_mutex_init(&loop->wq_mutex))
+ abort();
+
+ if (uv_async_init(loop, &loop->wq_async, uv__work_done))
+ abort();
+
+ uv__handle_unref(&loop->wq_async);
+ loop->wq_async.flags |= UV__HANDLE_INTERNAL;
+
return 0;
}
@@ -183,6 +201,31 @@ uv_loop_t* uv_default_loop(void) {
}
+static void uv__loop_close(uv_loop_t* loop) {
+ /* close the async handle without needeing an extra loop iteration */
+ assert(!loop->wq_async.async_sent);
+ loop->wq_async.close_cb = NULL;
+ uv__handle_closing(&loop->wq_async);
+ uv__handle_close(&loop->wq_async);
+
+ if (loop != &uv_default_loop_) {
+ size_t i;
+ for (i = 0; i < ARRAY_SIZE(loop->poll_peer_sockets); i++) {
+ SOCKET sock = loop->poll_peer_sockets[i];
+ if (sock != 0 && sock != INVALID_SOCKET)
+ closesocket(sock);
+ }
+ }
+ /* TODO: cleanup default loop*/
+
+ uv_mutex_lock(&loop->wq_mutex);
+ assert(QUEUE_EMPTY(&loop->wq) && "thread pool work queue not empty!");
+ assert(!uv__has_active_reqs(loop));
+ uv_mutex_unlock(&loop->wq_mutex);
+ uv_mutex_destroy(&loop->wq_mutex);
+}
+
+
int uv_loop_close(uv_loop_t* loop) {
QUEUE* q;
uv_handle_t* h;
@@ -193,15 +236,13 @@ int uv_loop_close(uv_loop_t* loop) {
if (!(h->flags & UV__HANDLE_INTERNAL))
return UV_EBUSY;
}
- if (loop != &uv_default_loop_) {
- size_t i;
- for (i = 0; i < ARRAY_SIZE(loop->poll_peer_sockets); i++) {
- SOCKET sock = loop->poll_peer_sockets[i];
- if (sock != 0 && sock != INVALID_SOCKET)
- closesocket(sock);
- }
- }
- /* TODO: cleanup default loop*/
+
+ uv__loop_close(loop);
+
+#ifndef NDEBUG
+ memset(loop, -1, sizeof(*loop));
+#endif
+
return 0;
}
@@ -224,7 +265,8 @@ uv_loop_t* uv_loop_new(void) {
void uv_loop_delete(uv_loop_t* loop) {
- assert(uv_loop_close(loop) == 0);
+ int err = uv_loop_close(loop);
+ assert(err == 0);
if (loop != &uv_default_loop_)
free(loop);
}
@@ -236,22 +278,31 @@ int uv_backend_fd(const uv_loop_t* loop) {
int uv_backend_timeout(const uv_loop_t* loop) {
- return 0;
+ if (loop->stop_flag != 0)
+ return 0;
+
+ if (!uv__has_active_handles(loop) && !uv__has_active_reqs(loop))
+ return 0;
+
+ if (loop->pending_reqs_tail)
+ return 0;
+
+ if (loop->endgame_handles)
+ return 0;
+
+ if (loop->idle_handles)
+ return 0;
+
+ return uv__next_timeout(loop);
}
-static void uv_poll(uv_loop_t* loop, int block) {
- DWORD bytes, timeout;
+static void uv_poll(uv_loop_t* loop, DWORD timeout) {
+ DWORD bytes;
ULONG_PTR key;
OVERLAPPED* overlapped;
uv_req_t* req;
- if (block) {
- timeout = uv_get_poll_timeout(loop);
- } else {
- timeout = 0;
- }
-
GetQueuedCompletionStatus(loop->iocp,
&bytes,
&key,
@@ -266,28 +317,22 @@ static void uv_poll(uv_loop_t* loop, int block) {
/* Serious error */
uv_fatal_error(GetLastError(), "GetQueuedCompletionStatus");
} else {
- /* We're sure that at least `timeout` milliseconds have expired, but */
- /* this may not be reflected yet in the GetTickCount() return value. */
- /* Therefore we ensure it's taken into account here. */
+ /* We're sure that at least `timeout` milliseconds have expired, but
+ * this may not be reflected yet in the GetTickCount() return value.
+ * Therefore we ensure it's taken into account here.
+ */
uv__time_forward(loop, timeout);
}
}
-static void uv_poll_ex(uv_loop_t* loop, int block) {
+static void uv_poll_ex(uv_loop_t* loop, DWORD timeout) {
BOOL success;
- DWORD timeout;
uv_req_t* req;
OVERLAPPED_ENTRY overlappeds[128];
ULONG count;
ULONG i;
- if (block) {
- timeout = uv_get_poll_timeout(loop);
- } else {
- timeout = 0;
- }
-
success = pGetQueuedCompletionStatusEx(loop->iocp,
overlappeds,
ARRAY_SIZE(overlappeds),
@@ -305,9 +350,10 @@ static void uv_poll_ex(uv_loop_t* loop, int block) {
/* Serious error */
uv_fatal_error(GetLastError(), "GetQueuedCompletionStatusEx");
} else if (timeout > 0) {
- /* We're sure that at least `timeout` milliseconds have expired, but */
- /* this may not be reflected yet in the GetTickCount() return value. */
- /* Therefore we ensure it's taken into account here. */
+ /* We're sure that at least `timeout` milliseconds have expired, but
+ * this may not be reflected yet in the GetTickCount() return value.
+ * Therefore we ensure it's taken into account here.
+ */
uv__time_forward(loop, timeout);
}
}
@@ -326,8 +372,9 @@ int uv_loop_alive(const uv_loop_t* loop) {
int uv_run(uv_loop_t *loop, uv_run_mode mode) {
+ DWORD timeout;
int r;
- void (*poll)(uv_loop_t* loop, int block);
+ void (*poll)(uv_loop_t* loop, DWORD timeout);
if (pGetQueuedCompletionStatusEx)
poll = &uv_poll_ex;
@@ -346,13 +393,11 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
uv_idle_invoke(loop);
uv_prepare_invoke(loop);
- (*poll)(loop, loop->idle_handles == NULL &&
- loop->pending_reqs_tail == NULL &&
- loop->endgame_handles == NULL &&
- !loop->stop_flag &&
- (loop->active_handles > 0 ||
- !QUEUE_EMPTY(&loop->active_reqs)) &&
- !(mode & UV_RUN_NOWAIT));
+ timeout = 0;
+ if ((mode & UV_RUN_NOWAIT) == 0)
+ timeout = uv_backend_timeout(loop);
+
+ (*poll)(loop, timeout);
uv_check_invoke(loop);
uv_process_endgames(loop);
diff --git a/deps/uv/src/win/error.c b/deps/uv/src/win/error.c
index 3162bc787f..5c5514736e 100644
--- a/deps/uv/src/win/error.c
+++ b/deps/uv/src/win/error.c
@@ -133,6 +133,7 @@ int uv_translate_sys_error(int sys_errno) {
case ERROR_DIRECTORY: return UV_ENOENT;
case ERROR_FILE_NOT_FOUND: return UV_ENOENT;
case ERROR_INVALID_NAME: return UV_ENOENT;
+ case ERROR_INVALID_DRIVE: return UV_ENOENT;
case ERROR_INVALID_REPARSE_DATA: return UV_ENOENT;
case ERROR_MOD_NOT_FOUND: return UV_ENOENT;
case ERROR_PATH_NOT_FOUND: return UV_ENOENT;
diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c
index f31c0a2999..8b52e610f4 100644
--- a/deps/uv/src/win/fs.c
+++ b/deps/uv/src/win/fs.c
@@ -44,12 +44,8 @@
#define QUEUE_FS_TP_JOB(loop, req) \
do { \
- if (!QueueUserWorkItem(&uv_fs_thread_proc, \
- req, \
- WT_EXECUTEDEFAULT)) { \
- return uv_translate_sys_error(GetLastError()); \
- } \
uv__req_register(loop, req); \
+ uv__work_submit((loop), &(req)->work_req, uv__fs_work, uv__fs_done); \
} while (0)
#define SET_REQ_RESULT(req, result_value) \
@@ -232,11 +228,7 @@ INLINE static void uv_fs_req_init(uv_loop_t* loop, uv_fs_t* req,
req->result = 0;
req->ptr = NULL;
req->path = NULL;
-
- if (cb != NULL) {
- req->cb = cb;
- memset(&req->overlapped, 0, sizeof(req->overlapped));
- }
+ req->cb = cb;
}
@@ -729,6 +721,78 @@ void fs__mkdir(uv_fs_t* req) {
}
+/* Some parts of the implementation were borrowed from glibc. */
+void fs__mkdtemp(uv_fs_t* req) {
+ static const WCHAR letters[] =
+ L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ size_t len;
+ WCHAR* template_part;
+ static uint64_t value;
+ unsigned int count;
+ int fd;
+
+ /* A lower bound on the number of temporary files to attempt to
+ generate. The maximum total number of temporary file names that
+ can exist for a given template is 62**6. It should never be
+ necessary to try all these combinations. Instead if a reasonable
+ number of names is tried (we define reasonable as 62**3) fail to
+ give the system administrator the chance to remove the problems. */
+#define ATTEMPTS_MIN (62 * 62 * 62)
+
+ /* The number of times to attempt to generate a temporary file. To
+ conform to POSIX, this must be no smaller than TMP_MAX. */
+#if ATTEMPTS_MIN < TMP_MAX
+ unsigned int attempts = TMP_MAX;
+#else
+ unsigned int attempts = ATTEMPTS_MIN;
+#endif
+
+ len = wcslen(req->pathw);
+ if (len < 6 || wcsncmp(&req->pathw[len - 6], L"XXXXXX", 6)) {
+ SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
+ return;
+ }
+
+ /* This is where the Xs start. */
+ template_part = &req->pathw[len - 6];
+
+ /* Get some random data. */
+ value += uv_hrtime() ^ _getpid();
+
+ for (count = 0; count < attempts; value += 7777, ++count) {
+ uint64_t v = value;
+
+ /* Fill in the random bits. */
+ template_part[0] = letters[v % 62];
+ v /= 62;
+ template_part[1] = letters[v % 62];
+ v /= 62;
+ template_part[2] = letters[v % 62];
+ v /= 62;
+ template_part[3] = letters[v % 62];
+ v /= 62;
+ template_part[4] = letters[v % 62];
+ v /= 62;
+ template_part[5] = letters[v % 62];
+
+ fd = _wmkdir(req->pathw);
+
+ if (fd >= 0) {
+ len = strlen(req->path);
+ wcstombs((char*) req->path + len - 6, template_part, 6);
+ SET_REQ_RESULT(req, 0);
+ return;
+ } else if (errno != EEXIST) {
+ SET_REQ_RESULT(req, -1);
+ return;
+ }
+ }
+
+ /* We got out of the loop because we ran out of combinations to try. */
+ SET_REQ_RESULT(req, -1);
+}
+
+
void fs__readdir(uv_fs_t* req) {
WCHAR* pathw = req->pathw;
size_t len = wcslen(pathw);
@@ -1401,7 +1465,7 @@ static void fs__create_junction(uv_fs_t* req, const WCHAR* path,
/* Open the directory */
handle = CreateFileW(new_path,
- GENERIC_ALL,
+ GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
@@ -1510,11 +1574,10 @@ static void fs__fchown(uv_fs_t* req) {
}
-static DWORD WINAPI uv_fs_thread_proc(void* parameter) {
- uv_fs_t* req = (uv_fs_t*) parameter;
- uv_loop_t* loop = req->loop;
+static void uv__fs_work(struct uv__work* w) {
+ uv_fs_t* req;
- assert(req != NULL);
+ req = container_of(w, uv_fs_t, work_req);
assert(req->type == UV_FS);
#define XX(uc, lc) case UV_FS_##uc: fs__##lc(req); break;
@@ -1537,6 +1600,7 @@ static DWORD WINAPI uv_fs_thread_proc(void* parameter) {
XX(UNLINK, unlink)
XX(RMDIR, rmdir)
XX(MKDIR, mkdir)
+ XX(MKDTEMP, mkdtemp)
XX(RENAME, rename)
XX(READDIR, readdir)
XX(LINK, link)
@@ -1547,9 +1611,41 @@ static DWORD WINAPI uv_fs_thread_proc(void* parameter) {
default:
assert(!"bad uv_fs_type");
}
+}
- POST_COMPLETION_FOR_REQ(loop, req);
- return 0;
+
+static void uv__fs_done(struct uv__work* w, int status) {
+ uv_fs_t* req;
+
+ req = container_of(w, uv_fs_t, work_req);
+ uv__req_unregister(req->loop, req);
+
+ if (status == UV_ECANCELED) {
+ assert(req->result == 0);
+ req->result = UV_ECANCELED;
+ }
+
+ if (req->cb != NULL)
+ req->cb(req);
+}
+
+
+void uv_fs_req_cleanup(uv_fs_t* req) {
+ if (req->flags & UV_FS_CLEANEDUP)
+ return;
+
+ if (req->flags & UV_FS_FREE_PATHS)
+ free(req->pathw);
+
+ if (req->flags & UV_FS_FREE_PTR)
+ free(req->ptr);
+
+ req->path = NULL;
+ req->pathw = NULL;
+ req->new_pathw = NULL;
+ req->ptr = NULL;
+
+ req->flags |= UV_FS_CLEANEDUP;
}
@@ -1701,6 +1797,26 @@ int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
}
+int uv_fs_mkdtemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl,
+ uv_fs_cb cb) {
+ int err;
+
+ uv_fs_req_init(loop, req, UV_FS_MKDTEMP, cb);
+
+ err = fs__capture_path(loop, req, tpl, NULL, TRUE);
+ if (err)
+ return uv_translate_sys_error(err);
+
+ if (cb) {
+ QUEUE_FS_TP_JOB(loop, req);
+ return 0;
+ } else {
+ fs__mkdtemp(req);
+ return req->result;
+ }
+}
+
+
int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
int err;
@@ -2064,30 +2180,3 @@ int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file fd, double atime,
return req->result;
}
}
-
-
-void uv_process_fs_req(uv_loop_t* loop, uv_fs_t* req) {
- assert(req->cb);
- uv__req_unregister(loop, req);
- req->cb(req);
-}
-
-
-void uv_fs_req_cleanup(uv_fs_t* req) {
- if (req->flags & UV_FS_CLEANEDUP)
- return;
-
- if (req->flags & UV_FS_FREE_PATHS)
- free(req->pathw);
-
- if (req->flags & UV_FS_FREE_PTR)
- free(req->ptr);
-
- req->path = NULL;
- req->pathw = NULL;
- req->new_pathw = NULL;
- req->ptr = NULL;
-
- req->flags |= UV_FS_CLEANEDUP;
-}
-
diff --git a/deps/uv/src/win/getaddrinfo.c b/deps/uv/src/win/getaddrinfo.c
index b87a933f0f..086200a9ea 100644
--- a/deps/uv/src/win/getaddrinfo.c
+++ b/deps/uv/src/win/getaddrinfo.c
@@ -56,25 +56,13 @@
#define ALIGNED_SIZE(X) ((((X) + 3) >> 2) << 2)
-/* getaddrinfo worker thread implementation */
-static DWORD WINAPI getaddrinfo_thread_proc(void* parameter) {
- uv_getaddrinfo_t* req = (uv_getaddrinfo_t*) parameter;
- uv_loop_t* loop = req->loop;
- int ret;
-
- assert(req != NULL);
-
- /* call OS function on this thread */
- ret = GetAddrInfoW(req->node,
- req->service,
- req->hints,
- &req->res);
- req->retcode = ret;
-
- /* post getaddrinfo completed */
- POST_COMPLETION_FOR_REQ(loop, req);
+static void uv__getaddrinfo_work(struct uv__work* w) {
+ uv_getaddrinfo_t* req;
+ int err;
- return 0;
+ req = container_of(w, uv_getaddrinfo_t, work_req);
+ err = GetAddrInfoW(req->node, req->service, req->hints, &req->res);
+ req->retcode = uv__getaddrinfo_translate_error(err);
}
@@ -87,7 +75,8 @@ static DWORD WINAPI getaddrinfo_thread_proc(void* parameter) {
* and copy all structs and referenced strings into the one block.
* Each size calculation is adjusted to avoid unaligned pointers.
*/
-void uv_process_getaddrinfo_req(uv_loop_t* loop, uv_getaddrinfo_t* req) {
+static void uv__getaddrinfo_done(struct uv__work* w, int status) {
+ uv_getaddrinfo_t* req;
int addrinfo_len = 0;
int name_len = 0;
size_t addrinfo_struct_len = ALIGNED_SIZE(sizeof(struct addrinfo));
@@ -95,7 +84,8 @@ void uv_process_getaddrinfo_req(uv_loop_t* loop, uv_getaddrinfo_t* req) {
struct addrinfo* addrinfo_ptr;
char* alloc_ptr = NULL;
char* cur_ptr = NULL;
- int err = 0;
+
+ req = container_of(w, uv_getaddrinfo_t, work_req);
/* release input parameter memory */
if (req->alloc != NULL) {
@@ -103,6 +93,16 @@ void uv_process_getaddrinfo_req(uv_loop_t* loop, uv_getaddrinfo_t* req) {
req->alloc = NULL;
}
+ if (status == UV_ECANCELED) {
+ assert(req->retcode == 0);
+ req->retcode = UV_EAI_CANCELED;
+ if (req->res != NULL) {
+ FreeAddrInfoW(req->res);
+ req->res = NULL;
+ }
+ goto complete;
+ }
+
if (req->retcode == 0) {
/* convert addrinfoW to addrinfo */
/* first calculate required length */
@@ -113,7 +113,7 @@ void uv_process_getaddrinfo_req(uv_loop_t* loop, uv_getaddrinfo_t* req) {
if (addrinfow_ptr->ai_canonname != NULL) {
name_len = uv_utf16_to_utf8(addrinfow_ptr->ai_canonname, -1, NULL, 0);
if (name_len == 0) {
- err = uv_translate_sys_error(GetLastError());
+ req->retcode = uv_translate_sys_error(GetLastError());
goto complete;
}
addrinfo_len += ALIGNED_SIZE(name_len);
@@ -178,11 +178,8 @@ void uv_process_getaddrinfo_req(uv_loop_t* loop, uv_getaddrinfo_t* req) {
}
}
} else {
- err = UV_EAI_MEMORY;
+ req->retcode = UV_EAI_MEMORY;
}
- } else {
- /* GetAddrInfo failed */
- err = uv__getaddrinfo_translate_error(req->retcode);
}
/* return memory to system */
@@ -192,10 +189,10 @@ void uv_process_getaddrinfo_req(uv_loop_t* loop, uv_getaddrinfo_t* req) {
}
complete:
- uv__req_unregister(loop, req);
+ uv__req_unregister(req->loop, req);
/* finally do callback with converted result */
- req->getaddrinfo_cb(req, err, (struct addrinfo*)alloc_ptr);
+ req->getaddrinfo_cb(req, req->retcode, (struct addrinfo*)alloc_ptr);
}
@@ -246,6 +243,7 @@ int uv_getaddrinfo(uv_loop_t* loop,
req->res = NULL;
req->type = UV_GETADDRINFO;
req->loop = loop;
+ req->retcode = 0;
/* calculate required memory size for all input values */
if (node != NULL) {
@@ -323,13 +321,10 @@ int uv_getaddrinfo(uv_loop_t* loop,
req->hints = NULL;
}
- /* Ask thread to run. Treat this as a long operation */
- if (QueueUserWorkItem(&getaddrinfo_thread_proc,
- req,
- WT_EXECUTELONGFUNCTION) == 0) {
- err = GetLastError();
- goto error;
- }
+ uv__work_submit(loop,
+ &req->work_req,
+ uv__getaddrinfo_work,
+ uv__getaddrinfo_done);
uv__req_register(loop, req);
diff --git a/deps/uv/src/win/getnameinfo.c b/deps/uv/src/win/getnameinfo.c
index 48eb16d8ca..45608dae85 100644
--- a/deps/uv/src/win/getnameinfo.c
+++ b/deps/uv/src/win/getnameinfo.c
@@ -27,23 +27,31 @@
#include "internal.h"
#include "req-inl.h"
-
-/* getnameinfo worker thread implementation */
-static DWORD WINAPI getnameinfo_thread_proc(void* parameter) {
- uv_getnameinfo_t* req = (uv_getnameinfo_t*)parameter;
- uv_loop_t* loop = req->loop;
+#ifndef GetNameInfo
+int WSAAPI GetNameInfoW(
+ const SOCKADDR *pSockaddr,
+ socklen_t SockaddrLength,
+ PWCHAR pNodeBuffer,
+ DWORD NodeBufferSize,
+ PWCHAR pServiceBuffer,
+ DWORD ServiceBufferSize,
+ INT Flags
+);
+#endif
+
+static void uv__getnameinfo_work(struct uv__work* w) {
+ uv_getnameinfo_t* req;
WCHAR host[NI_MAXHOST];
WCHAR service[NI_MAXSERV];
int ret = 0;
- assert(req != NULL);
-
+ req = container_of(w, uv_getnameinfo_t, work_req);
ret = GetNameInfoW((struct sockaddr*)&req->storage,
sizeof(req->storage),
host,
- sizeof(host),
+ ARRAY_SIZE(host),
service,
- sizeof(service),
+ ARRAY_SIZE(service),
req->flags);
req->retcode = uv__getaddrinfo_translate_error(ret);
@@ -65,30 +73,29 @@ static DWORD WINAPI getnameinfo_thread_proc(void* parameter) {
sizeof(req->service),
NULL,
NULL);
-
- /* post getnameinfo completed */
- POST_COMPLETION_FOR_REQ(loop, req);
-
- return 0;
}
/*
* Called from uv_run when complete.
*/
-void uv_process_getnameinfo_req(uv_loop_t* loop, uv_getnameinfo_t* req) {
+static void uv__getnameinfo_done(struct uv__work* w, int status) {
+ uv_getnameinfo_t* req;
char* host;
char* service;
- if (req->retcode == 0) {
+ req = container_of(w, uv_getnameinfo_t, work_req);
+ uv__req_unregister(req->loop, req);
+ host = service = NULL;
+
+ if (status == UV_ECANCELED) {
+ assert(req->retcode == 0);
+ req->retcode = UV_EAI_CANCELED;
+ } else if (req->retcode == 0) {
host = req->host;
service = req->service;
- } else {
- host = NULL;
- service = NULL;
}
- uv__req_unregister(loop, req);
req->getnameinfo_cb(req, req->retcode, host, service);
}
@@ -119,20 +126,18 @@ int uv_getnameinfo(uv_loop_t* loop,
}
uv_req_init(loop, (uv_req_t*)req);
+ uv__req_register(loop, req);
req->getnameinfo_cb = getnameinfo_cb;
req->flags = flags;
req->type = UV_GETNAMEINFO;
req->loop = loop;
+ req->retcode = 0;
- /* Ask thread to run. Treat this as a long operation. */
- if (QueueUserWorkItem(&getnameinfo_thread_proc,
- req,
- WT_EXECUTELONGFUNCTION) == 0) {
- return uv_translate_sys_error(GetLastError());
- }
-
- uv__req_register(loop, req);
+ uv__work_submit(loop,
+ &req->work_req,
+ uv__getnameinfo_work,
+ uv__getnameinfo_done);
return 0;
}
diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h
index 83c4a66893..9eadb71235 100644
--- a/deps/uv/src/win/internal.h
+++ b/deps/uv/src/win/internal.h
@@ -31,13 +31,16 @@
#ifdef _MSC_VER
# define INLINE __inline
+# define UV_THREAD_LOCAL __declspec( thread )
#else
# define INLINE inline
+# define UV_THREAD_LOCAL __thread
#endif
#ifdef _DEBUG
-extern __declspec( thread ) int uv__crt_assert_enabled;
+
+extern UV_THREAD_LOCAL int uv__crt_assert_enabled;
#define UV_BEGIN_DISABLE_CRT_ASSERT() \
{ \
@@ -72,7 +75,6 @@ extern __declspec( thread ) int uv__crt_assert_enabled;
/* Used by streams and UDP handles. */
#define UV_HANDLE_READING 0x00000100
#define UV_HANDLE_BOUND 0x00000200
-#define UV_HANDLE_BIND_ERROR 0x00000400
#define UV_HANDLE_LISTENING 0x00000800
#define UV_HANDLE_CONNECTION 0x00001000
#define UV_HANDLE_CONNECTED 0x00002000
@@ -122,6 +124,12 @@ extern __declspec( thread ) int uv__crt_assert_enabled;
/*
* TCP
*/
+
+typedef struct {
+ WSAPROTOCOL_INFOW socket_info;
+ int delayed_error;
+} uv__ipc_socket_info_ex;
+
int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb);
int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client);
int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb,
@@ -140,7 +148,7 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp);
void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle);
-int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info,
+int uv_tcp_import(uv_tcp_t* tcp, uv__ipc_socket_info_ex* socket_info_ex,
int tcp_connection);
int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid,
@@ -231,7 +239,7 @@ void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle);
*/
void uv_timer_endgame(uv_loop_t* loop, uv_timer_t* handle);
-DWORD uv_get_poll_timeout(uv_loop_t* loop);
+DWORD uv__next_timeout(const uv_loop_t* loop);
void uv__time_forward(uv_loop_t* loop, uint64_t msecs);
void uv_process_timers(uv_loop_t* loop);
@@ -286,28 +294,9 @@ int uv_translate_sys_error(int sys_errno);
/*
- * Getaddrinfo
- */
-void uv_process_getaddrinfo_req(uv_loop_t* loop, uv_getaddrinfo_t* req);
-
-
-/*
-* Getnameinfo
-*/
-void uv_process_getnameinfo_req(uv_loop_t* loop, uv_getnameinfo_t* req);
-
-
-/*
* FS
*/
void uv_fs_init();
-void uv_process_fs_req(uv_loop_t* loop, uv_fs_t* req);
-
-
-/*
- * Threadpool
- */
-void uv_process_work_req(uv_loop_t* loop, uv_work_t* req);
/*
diff --git a/deps/uv/src/win/pipe.c b/deps/uv/src/win/pipe.c
index 2fcedde369..3bf2a220d0 100644
--- a/deps/uv/src/win/pipe.c
+++ b/deps/uv/src/win/pipe.c
@@ -35,10 +35,10 @@ typedef struct uv__ipc_queue_item_s uv__ipc_queue_item_t;
struct uv__ipc_queue_item_s {
/*
- * NOTE: It is important for socket_info to be the first field,
+ * NOTE: It is important for socket_info_ex to be the first field,
* because we will we assigning it to the pending_ipc_info.socket_info
*/
- WSAPROTOCOL_INFOW socket_info;
+ uv__ipc_socket_info_ex socket_info_ex;
QUEUE member;
int tcp_connection;
};
@@ -73,7 +73,7 @@ typedef struct {
/* IPC frame, which contains an imported TCP socket stream. */
typedef struct {
uv_ipc_frame_header_t header;
- WSAPROTOCOL_INFOW socket_info;
+ uv__ipc_socket_info_ex socket_info_ex;
} uv_ipc_frame_uv_stream;
static void eof_timer_init(uv_pipe_t* pipe);
@@ -230,7 +230,7 @@ static int uv_set_pipe_handle(uv_loop_t* loop,
NTSTATUS nt_status;
IO_STATUS_BLOCK io_status;
FILE_MODE_INFORMATION mode_info;
- DWORD mode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT;
+ DWORD mode = PIPE_READMODE_BYTE | PIPE_WAIT;
DWORD current_mode = 0;
DWORD err = 0;
@@ -246,11 +246,9 @@ static int uv_set_pipe_handle(uv_loop_t* loop,
if (!GetNamedPipeHandleState(pipeHandle, &current_mode, NULL, NULL,
NULL, NULL, 0)) {
return -1;
- } else if (current_mode != mode) {
+ } else if (current_mode & PIPE_NOWAIT) {
SetLastError(ERROR_ACCESS_DENIED);
return -1;
- } else {
- duplex_flags &= ~UV_HANDLE_WRITABLE;
}
} else {
/* If this returns ERROR_INVALID_PARAMETER we probably opened
@@ -410,7 +408,7 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
socket = WSASocketW(FROM_PROTOCOL_INFO,
FROM_PROTOCOL_INFO,
FROM_PROTOCOL_INFO,
- &item->socket_info,
+ &item->socket_info_ex.socket_info,
0,
WSA_FLAG_OVERLAPPED);
free(item);
@@ -789,7 +787,7 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) {
item = QUEUE_DATA(q, uv__ipc_queue_item_t, member);
err = uv_tcp_import((uv_tcp_t*)client,
- &item->socket_info,
+ &item->socket_info_ex,
item->tcp_connection);
if (err != 0)
return err;
@@ -1134,10 +1132,13 @@ static int uv_pipe_write_impl(uv_loop_t* loop,
tcp_send_handle = (uv_tcp_t*)send_handle;
err = uv_tcp_duplicate_socket(tcp_send_handle, handle->ipc_pid,
- &ipc_frame.socket_info);
+ &ipc_frame.socket_info_ex.socket_info);
if (err) {
return err;
}
+
+ ipc_frame.socket_info_ex.delayed_error = tcp_send_handle->delayed_error;
+
ipc_frame.header.flags |= UV_IPC_TCP_SERVER;
if (tcp_send_handle->flags & UV_HANDLE_CONNECTION) {
@@ -1254,7 +1255,7 @@ static int uv_pipe_write_impl(uv_loop_t* loop,
}
/* Request queued by the kernel. */
- req->queued_bytes = uv_count_bufs(bufs, nbufs);
+ req->queued_bytes = uv__count_bufs(bufs, nbufs);
handle->write_queue_size += req->queued_bytes;
} else if (handle->flags & UV_HANDLE_BLOCKING_WRITES) {
/* Using overlapped IO, but wait for completion before returning */
@@ -1311,7 +1312,7 @@ static int uv_pipe_write_impl(uv_loop_t* loop,
req->queued_bytes = 0;
} else {
/* Request queued by the kernel. */
- req->queued_bytes = uv_count_bufs(bufs, nbufs);
+ req->queued_bytes = uv__count_bufs(bufs, nbufs);
handle->write_queue_size += req->queued_bytes;
}
@@ -1397,7 +1398,7 @@ static void uv_pipe_read_error_or_eof(uv_loop_t* loop, uv_pipe_t* handle,
void uv__pipe_insert_pending_socket(uv_pipe_t* handle,
- WSAPROTOCOL_INFOW* info,
+ uv__ipc_socket_info_ex* info,
int tcp_connection) {
uv__ipc_queue_item_t* item;
@@ -1405,7 +1406,7 @@ void uv__pipe_insert_pending_socket(uv_pipe_t* handle,
if (item == NULL)
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
- memcpy(&item->socket_info, info, sizeof(item->socket_info));
+ memcpy(&item->socket_info_ex, info, sizeof(item->socket_info_ex));
item->tcp_connection = tcp_connection;
QUEUE_INSERT_TAIL(&handle->pending_ipc_info.queue, &item->member);
handle->pending_ipc_info.queue_len++;
@@ -1471,11 +1472,11 @@ void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle,
if (ipc_frame.header.flags & UV_IPC_TCP_SERVER) {
assert(avail - sizeof(ipc_frame.header) >=
- sizeof(ipc_frame.socket_info));
+ sizeof(ipc_frame.socket_info_ex));
/* Read the TCP socket info. */
if (!ReadFile(handle->handle,
- &ipc_frame.socket_info,
+ &ipc_frame.socket_info_ex,
sizeof(ipc_frame) - sizeof(ipc_frame.header),
&bytes,
NULL)) {
@@ -1489,7 +1490,7 @@ void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle,
/* Store the pending socket info. */
uv__pipe_insert_pending_socket(
handle,
- &ipc_frame.socket_info,
+ &ipc_frame.socket_info_ex,
ipc_frame.header.flags & UV_IPC_TCP_CONNECTION);
}
@@ -1772,7 +1773,34 @@ static void eof_timer_close_cb(uv_handle_t* handle) {
int uv_pipe_open(uv_pipe_t* pipe, uv_file file) {
HANDLE os_handle = uv__get_osfhandle(file);
- DWORD duplex_flags = UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
+ NTSTATUS nt_status;
+ IO_STATUS_BLOCK io_status;
+ FILE_ACCESS_INFORMATION access;
+ DWORD duplex_flags = 0;
+
+ /* Determine what kind of permissions we have on this handle.
+ * Cygwin opens the pipe in message mode, but we can support it,
+ * just query the access flags and set the stream flags accordingly.
+ */
+ nt_status = pNtQueryInformationFile(os_handle,
+ &io_status,
+ &access,
+ sizeof(access),
+ FileAccessInformation);
+ if (nt_status != STATUS_SUCCESS)
+ return UV_EINVAL;
+
+ if (pipe->ipc) {
+ if (!(access.AccessFlags & FILE_WRITE_DATA) ||
+ !(access.AccessFlags & FILE_READ_DATA)) {
+ return UV_EINVAL;
+ }
+ }
+
+ if (access.AccessFlags & FILE_WRITE_DATA)
+ duplex_flags |= UV_HANDLE_WRITABLE;
+ if (access.AccessFlags & FILE_READ_DATA)
+ duplex_flags |= UV_HANDLE_READABLE;
if (os_handle == INVALID_HANDLE_VALUE ||
uv_set_pipe_handle(pipe->loop, pipe, os_handle, duplex_flags) == -1) {
diff --git a/deps/uv/src/win/process.c b/deps/uv/src/win/process.c
index 7a85858c56..40023e5572 100644
--- a/deps/uv/src/win/process.c
+++ b/deps/uv/src/win/process.c
@@ -25,6 +25,8 @@
#include <stdlib.h>
#include <signal.h>
#include <limits.h>
+#include <malloc.h>
+#include <wchar.h>
#include "uv.h"
#include "internal.h"
@@ -36,14 +38,27 @@
typedef struct env_var {
- const char* narrow;
- const WCHAR* wide;
- size_t len; /* including null or '=' */
- DWORD value_len;
- int supplied;
+ const WCHAR* const wide;
+ const WCHAR* const wide_eq;
+ const size_t len; /* including null or '=' */
} env_var_t;
-#define E_V(str) { str "=", L##str, sizeof(str), 0, 0 }
+#define E_V(str) { L##str, L##str L"=", sizeof(str) }
+
+static const env_var_t required_vars[] = { /* keep me sorted */
+ E_V("HOMEDRIVE"),
+ E_V("HOMEPATH"),
+ E_V("LOGONSERVER"),
+ E_V("PATH"),
+ E_V("SYSTEMDRIVE"),
+ E_V("SYSTEMROOT"),
+ E_V("TEMP"),
+ E_V("USERDOMAIN"),
+ E_V("USERNAME"),
+ E_V("USERPROFILE"),
+ E_V("WINDIR"),
+};
+static size_t n_required_vars = ARRAY_SIZE(required_vars);
static HANDLE uv_global_job_handle_;
@@ -587,25 +602,56 @@ error:
}
-/*
- * If we learn that people are passing in huge environment blocks
- * then we should probably qsort() the array and then bsearch()
- * to see if it contains this variable. But there are ownership
- * issues associated with that solution; this is the caller's
- * char**, and modifying it is rude.
- */
-static void check_required_vars_contains_var(env_var_t* required, int count,
- const char* var) {
- int i;
- for (i = 0; i < count; ++i) {
- if (_strnicmp(required[i].narrow, var, required[i].len) == 0) {
- required[i].supplied = 1;
- return;
+int env_strncmp(const wchar_t* a, int na, const wchar_t* b) {
+ wchar_t* a_eq;
+ wchar_t* b_eq;
+ wchar_t* A;
+ wchar_t* B;
+ int nb;
+ int r;
+
+ if (na < 0) {
+ a_eq = wcschr(a, L'=');
+ assert(a_eq);
+ na = (int)(long)(a_eq - a);
+ } else {
+ na--;
+ }
+ b_eq = wcschr(b, L'=');
+ assert(b_eq);
+ nb = b_eq - b;
+
+ A = alloca((na+1) * sizeof(wchar_t));
+ B = alloca((nb+1) * sizeof(wchar_t));
+
+ r = LCMapStringW(LOCALE_INVARIANT, LCMAP_UPPERCASE, a, na, A, na);
+ assert(r==na);
+ A[na] = L'\0';
+ r = LCMapStringW(LOCALE_INVARIANT, LCMAP_UPPERCASE, b, nb, B, nb);
+ assert(r==nb);
+ B[nb] = L'\0';
+
+ while (1) {
+ wchar_t AA = *A++;
+ wchar_t BB = *B++;
+ if (AA < BB) {
+ return -1;
+ } else if (AA > BB) {
+ return 1;
+ } else if (!AA && !BB) {
+ return 0;
}
}
}
+static int qsort_wcscmp(const void *a, const void *b) {
+ wchar_t* astr = *(wchar_t* const*)a;
+ wchar_t* bstr = *(wchar_t* const*)b;
+ return env_strncmp(astr, -1, bstr);
+}
+
+
/*
* The way windows takes environment variables is different than what C does;
* Windows wants a contiguous block of null-terminated strings, terminated
@@ -616,95 +662,171 @@ static void check_required_vars_contains_var(env_var_t* required, int count,
* TEMP. SYSTEMDRIVE is probably also important. We therefore ensure that
* these get defined if the input environment block does not contain any
* values for them.
+ *
+ * Also add variables known to Cygwin to be required for correct
+ * subprocess operation in many cases:
+ * https://github.com/Alexpux/Cygwin/blob/b266b04fbbd3a595f02ea149e4306d3ab9b1fe3d/winsup/cygwin/environ.cc#L955
+ *
*/
int make_program_env(char* env_block[], WCHAR** dst_ptr) {
WCHAR* dst;
WCHAR* ptr;
char** env;
- size_t env_len = 1; /* room for closing null */
+ size_t env_len = 0;
int len;
size_t i;
DWORD var_size;
+ size_t env_block_count = 1; /* 1 for null-terminator */
+ WCHAR* dst_copy;
+ WCHAR** ptr_copy;
+ WCHAR** env_copy;
+ DWORD* required_vars_value_len = alloca(n_required_vars * sizeof(DWORD*));
- env_var_t required_vars[] = {
- E_V("SYSTEMROOT"),
- E_V("SYSTEMDRIVE"),
- E_V("TEMP"),
- };
-
+ /* first pass: determine size in UTF-16 */
for (env = env_block; *env; env++) {
int len;
- check_required_vars_contains_var(required_vars,
- ARRAY_SIZE(required_vars),
- *env);
-
- len = MultiByteToWideChar(CP_UTF8,
- 0,
- *env,
- -1,
- NULL,
- 0);
- if (len <= 0) {
- return GetLastError();
+ if (strchr(*env, '=')) {
+ len = MultiByteToWideChar(CP_UTF8,
+ 0,
+ *env,
+ -1,
+ NULL,
+ 0);
+ if (len <= 0) {
+ return GetLastError();
+ }
+ env_len += len;
+ env_block_count++;
}
+ }
- env_len += len;
+ /* second pass: copy to UTF-16 environment block */
+ dst_copy = _malloca(env_len * sizeof(WCHAR));
+ if (!dst_copy) {
+ return ERROR_OUTOFMEMORY;
}
+ env_copy = alloca(env_block_count * sizeof(WCHAR*));
- for (i = 0; i < ARRAY_SIZE(required_vars); ++i) {
- if (!required_vars[i].supplied) {
- env_len += required_vars[i].len;
+ ptr = dst_copy;
+ ptr_copy = env_copy;
+ for (env = env_block; *env; env++) {
+ if (strchr(*env, '=')) {
+ len = MultiByteToWideChar(CP_UTF8,
+ 0,
+ *env,
+ -1,
+ ptr,
+ (int) (env_len - (ptr - dst_copy)));
+ if (len <= 0) {
+ DWORD err = GetLastError();
+ _freea(dst_copy);
+ return err;
+ }
+ *ptr_copy++ = ptr;
+ ptr += len;
+ }
+ }
+ *ptr_copy = NULL;
+ assert(env_len == ptr - dst_copy);
+
+ /* sort our (UTF-16) copy */
+ qsort(env_copy, env_block_count-1, sizeof(wchar_t*), qsort_wcscmp);
+
+ /* third pass: check for required variables */
+ for (ptr_copy = env_copy, i = 0; i < n_required_vars; ) {
+ int cmp;
+ if (!*ptr_copy) {
+ cmp = -1;
+ } else {
+ cmp = env_strncmp(required_vars[i].wide_eq,
+ required_vars[i].len,
+ *ptr_copy);
+ }
+ if (cmp < 0) {
+ /* missing required var */
var_size = GetEnvironmentVariableW(required_vars[i].wide, NULL, 0);
- if (var_size == 0) {
- return GetLastError();
+ required_vars_value_len[i] = var_size;
+ if (var_size != 0) {
+ env_len += required_vars[i].len;
+ env_len += var_size;
}
- required_vars[i].value_len = var_size;
- env_len += var_size;
+ i++;
+ } else {
+ ptr_copy++;
+ if (cmp == 0)
+ i++;
}
}
- dst = malloc(env_len * sizeof(WCHAR));
+ /* final pass: copy, in sort order, and inserting required variables */
+ dst = malloc((1+env_len) * sizeof(WCHAR));
if (!dst) {
+ _freea(dst_copy);
return ERROR_OUTOFMEMORY;
}
- ptr = dst;
-
- for (env = env_block; *env; env++, ptr += len) {
- len = MultiByteToWideChar(CP_UTF8,
- 0,
- *env,
- -1,
- ptr,
- (int) (env_len - (ptr - dst)));
- if (len <= 0) {
- free(dst);
- return GetLastError();
+ for (ptr = dst, ptr_copy = env_copy, i = 0;
+ *ptr_copy || i < n_required_vars;
+ ptr += len) {
+ int cmp;
+ if (i >= n_required_vars) {
+ cmp = 1;
+ } else if (!*ptr_copy) {
+ cmp = -1;
+ } else {
+ cmp = env_strncmp(required_vars[i].wide_eq,
+ required_vars[i].len,
+ *ptr_copy);
}
- }
-
- for (i = 0; i < ARRAY_SIZE(required_vars); ++i) {
- if (!required_vars[i].supplied) {
- wcscpy(ptr, required_vars[i].wide);
- ptr += required_vars[i].len - 1;
- *ptr++ = L'=';
- var_size = GetEnvironmentVariableW(required_vars[i].wide,
- ptr,
- required_vars[i].value_len);
- if (var_size == 0) {
- uv_fatal_error(GetLastError(), "GetEnvironmentVariableW");
+ if (cmp < 0) {
+ /* missing required var */
+ len = required_vars_value_len[i];
+ if (len) {
+ wcscpy(ptr, required_vars[i].wide_eq);
+ ptr += required_vars[i].len;
+ var_size = GetEnvironmentVariableW(required_vars[i].wide,
+ ptr,
+ (int) (env_len - (ptr - dst)));
+ if (var_size != len-1) { /* race condition? */
+ uv_fatal_error(GetLastError(), "GetEnvironmentVariableW");
+ }
}
- ptr += required_vars[i].value_len;
+ i++;
+ } else {
+ /* copy var from env_block */
+ DWORD r;
+ len = wcslen(*ptr_copy) + 1;
+ r = wmemcpy_s(ptr, (env_len - (ptr - dst)), *ptr_copy, len);
+ assert(!r);
+ ptr_copy++;
+ if (cmp == 0)
+ i++;
}
}
/* Terminate with an extra NULL. */
+ assert(env_len == (ptr - dst));
*ptr = L'\0';
+ _freea(dst_copy);
*dst_ptr = dst;
return 0;
}
+/*
+ * Attempt to find the value of the PATH environment variable in the child's
+ * preprocessed environment.
+ *
+ * If found, a pointer into `env` is returned. If not found, NULL is returned.
+ */
+static WCHAR* find_path(WCHAR *env) {
+ for (; env != NULL && *env != 0; env += wcslen(env) + 1) {
+ if (wcsncmp(env, L"PATH=", 5) == 0)
+ return &env[5];
+ }
+
+ return NULL;
+}
/*
* Called on Windows thread-pool thread to indicate that
@@ -802,7 +924,7 @@ int uv_spawn(uv_loop_t* loop,
const uv_process_options_t* options) {
int i;
int err = 0;
- WCHAR* path = NULL;
+ WCHAR* path = NULL, *alloc_path = NULL;
BOOL result;
WCHAR* application_path = NULL, *application = NULL, *arguments = NULL,
*env = NULL, *cwd = NULL;
@@ -876,7 +998,8 @@ int uv_spawn(uv_loop_t* loop,
}
/* Get PATH environment variable. */
- {
+ path = find_path(env);
+ if (path == NULL) {
DWORD path_len, r;
path_len = GetEnvironmentVariableW(L"PATH", NULL, 0);
@@ -885,11 +1008,12 @@ int uv_spawn(uv_loop_t* loop,
goto done;
}
- path = (WCHAR*) malloc(path_len * sizeof(WCHAR));
- if (path == NULL) {
+ alloc_path = (WCHAR*) malloc(path_len * sizeof(WCHAR));
+ if (alloc_path == NULL) {
err = ERROR_OUTOFMEMORY;
goto done;
}
+ path = alloc_path;
r = GetEnvironmentVariableW(L"PATH", path, path_len);
if (r == 0 || r >= path_len) {
@@ -1023,7 +1147,7 @@ int uv_spawn(uv_loop_t* loop,
free(arguments);
free(cwd);
free(env);
- free(path);
+ free(alloc_path);
if (process->child_stdio_buffer != NULL) {
/* Clean up child stdio handles. */
diff --git a/deps/uv/src/win/req-inl.h b/deps/uv/src/win/req-inl.h
index cbc2ba8e18..97342e5c7e 100644
--- a/deps/uv/src/win/req-inl.h
+++ b/deps/uv/src/win/req-inl.h
@@ -195,26 +195,10 @@ INLINE static void uv_process_reqs(uv_loop_t* loop) {
uv_process_poll_req(loop, (uv_poll_t*) req->data, req);
break;
- case UV_GETADDRINFO:
- uv_process_getaddrinfo_req(loop, (uv_getaddrinfo_t*) req);
- break;
-
- case UV_GETNAMEINFO:
- uv_process_getnameinfo_req(loop, (uv_getnameinfo_t*)req);
- break;
-
case UV_PROCESS_EXIT:
uv_process_proc_exit(loop, (uv_process_t*) req->data);
break;
- case UV_FS:
- uv_process_fs_req(loop, (uv_fs_t*) req);
- break;
-
- case UV_WORK:
- uv_process_work_req(loop, (uv_work_t*) req);
- break;
-
case UV_FS_EVENT_REQ:
uv_process_fs_event_req(loop, req, (uv_fs_event_t*) req->data);
break;
diff --git a/deps/uv/src/win/stream-inl.h b/deps/uv/src/win/stream-inl.h
index e4bf086368..97a6b90b50 100644
--- a/deps/uv/src/win/stream-inl.h
+++ b/deps/uv/src/win/stream-inl.h
@@ -53,15 +53,4 @@ INLINE static void uv_connection_init(uv_stream_t* handle) {
}
-INLINE static size_t uv_count_bufs(const uv_buf_t bufs[], unsigned int nbufs) {
- unsigned int i;
- size_t bytes;
-
- bytes = 0;
- for (i = 0; i < nbufs; i++)
- bytes += (size_t) bufs[i].len;
-
- return bytes;
-}
-
#endif /* UV_WIN_STREAM_INL_H_ */
diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c
index ccd7a11e2c..a213ad63e7 100644
--- a/deps/uv/src/win/tcp.c
+++ b/deps/uv/src/win/tcp.c
@@ -156,6 +156,7 @@ int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* handle) {
handle->func_acceptex = NULL;
handle->func_connectex = NULL;
handle->processed_accepts = 0;
+ handle->delayed_error = 0;
return 0;
}
@@ -235,6 +236,17 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
}
+/* Unlike on Unix, here we don't set SO_REUSEADDR, because it doesn't just
+ * allow binding to addresses that are in use by sockets in TIME_WAIT, it
+ * effectively allows 'stealing' a port which is in use by another application.
+ *
+ * SO_EXCLUSIVEADDRUSE is also not good here because it does cehck all sockets,
+ * regardless of state, so we'd get an error even if the port is in use by a
+ * socket in TIME_WAIT state.
+ *
+ * See issue #1360.
+ *
+ */
static int uv_tcp_try_bind(uv_tcp_t* handle,
const struct sockaddr* addr,
unsigned int addrlen,
@@ -291,8 +303,7 @@ static int uv_tcp_try_bind(uv_tcp_t* handle,
err = WSAGetLastError();
if (err == WSAEADDRINUSE) {
/* Some errors are not to be reported until connect() or listen() */
- handle->bind_error = err;
- handle->flags |= UV_HANDLE_BIND_ERROR;
+ handle->delayed_error = err;
} else {
return err;
}
@@ -517,8 +528,8 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
return WSAEISCONN;
}
- if (handle->flags & UV_HANDLE_BIND_ERROR) {
- return handle->bind_error;
+ if (handle->delayed_error) {
+ return handle->delayed_error;
}
if (!(handle->flags & UV_HANDLE_BOUND)) {
@@ -528,6 +539,8 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
0);
if (err)
return err;
+ if (handle->delayed_error)
+ return handle->delayed_error;
}
if (!handle->func_acceptex) {
@@ -699,8 +712,8 @@ static int uv_tcp_try_connect(uv_connect_t* req,
DWORD bytes;
int err;
- if (handle->flags & UV_HANDLE_BIND_ERROR) {
- return handle->bind_error;
+ if (handle->delayed_error) {
+ return handle->delayed_error;
}
if (!(handle->flags & UV_HANDLE_BOUND)) {
@@ -714,6 +727,8 @@ static int uv_tcp_try_connect(uv_connect_t* req,
err = uv_tcp_try_bind(handle, bind_addr, addrlen, 0);
if (err)
return err;
+ if (handle->delayed_error)
+ return handle->delayed_error;
}
if (!handle->func_connectex) {
@@ -762,8 +777,8 @@ int uv_tcp_getsockname(const uv_tcp_t* handle,
return UV_EINVAL;
}
- if (handle->flags & UV_HANDLE_BIND_ERROR) {
- return uv_translate_sys_error(handle->bind_error);
+ if (handle->delayed_error) {
+ return uv_translate_sys_error(handle->delayed_error);
}
result = getsockname(handle->socket, name, namelen);
@@ -784,8 +799,8 @@ int uv_tcp_getpeername(const uv_tcp_t* handle,
return UV_EINVAL;
}
- if (handle->flags & UV_HANDLE_BIND_ERROR) {
- return uv_translate_sys_error(handle->bind_error);
+ if (handle->delayed_error) {
+ return uv_translate_sys_error(handle->delayed_error);
}
result = getpeername(handle->socket, name, namelen);
@@ -839,7 +854,7 @@ int uv_tcp_write(uv_loop_t* loop,
uv_insert_pending_req(loop, (uv_req_t*) req);
} else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
/* Request queued by the kernel. */
- req->queued_bytes = uv_count_bufs(bufs, nbufs);
+ req->queued_bytes = uv__count_bufs(bufs, nbufs);
handle->reqs_pending++;
handle->write_reqs_pending++;
REGISTER_HANDLE_REQ(loop, handle, req);
@@ -1009,8 +1024,12 @@ void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle,
}
if (req->cb) {
- err = GET_REQ_SOCK_ERROR(req);
- req->cb(req, uv_translate_sys_error(err));
+ err = uv_translate_sys_error(GET_REQ_SOCK_ERROR(req));
+ if (err == UV_ECONNABORTED) {
+ /* use UV_ECANCELED for consistency with Unix */
+ err = UV_ECANCELED;
+ }
+ req->cb(req, err);
}
handle->write_reqs_pending--;
@@ -1102,14 +1121,13 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
}
-int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info,
+int uv_tcp_import(uv_tcp_t* tcp, uv__ipc_socket_info_ex* socket_info_ex,
int tcp_connection) {
int err;
-
SOCKET socket = WSASocketW(FROM_PROTOCOL_INFO,
FROM_PROTOCOL_INFO,
FROM_PROTOCOL_INFO,
- socket_protocol_info,
+ &socket_info_ex->socket_info,
0,
WSA_FLAG_OVERLAPPED);
@@ -1126,7 +1144,7 @@ int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info,
err = uv_tcp_set_socket(tcp->loop,
tcp,
socket,
- socket_protocol_info->iAddressFamily,
+ socket_info_ex->socket_info.iAddressFamily,
1);
if (err) {
closesocket(socket);
@@ -1141,6 +1159,8 @@ int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info,
tcp->flags |= UV_HANDLE_BOUND;
tcp->flags |= UV_HANDLE_SHARED_TCP_SOCKET;
+ tcp->delayed_error = socket_info_ex->delayed_error;
+
tcp->loop->active_tcp_streams++;
return 0;
}
@@ -1201,13 +1221,10 @@ int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid,
return ERROR_INVALID_PARAMETER;
}
- /* Report any deferred bind errors now. */
- if (handle->flags & UV_HANDLE_BIND_ERROR) {
- return handle->bind_error;
- }
-
- if (listen(handle->socket, SOMAXCONN) == SOCKET_ERROR) {
- return WSAGetLastError();
+ if (!(handle->delayed_error)) {
+ if (listen(handle->socket, SOMAXCONN) == SOCKET_ERROR) {
+ handle->delayed_error = WSAGetLastError();
+ }
}
}
}
diff --git a/deps/uv/src/win/threadpool.c b/deps/uv/src/win/threadpool.c
deleted file mode 100644
index 9539844c66..0000000000
--- a/deps/uv/src/win/threadpool.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <assert.h>
-
-#include "uv.h"
-#include "internal.h"
-#include "req-inl.h"
-
-
-static void uv_work_req_init(uv_loop_t* loop, uv_work_t* req,
- uv_work_cb work_cb, uv_after_work_cb after_work_cb) {
- uv_req_init(loop, (uv_req_t*) req);
- req->type = UV_WORK;
- req->loop = loop;
- req->work_cb = work_cb;
- req->after_work_cb = after_work_cb;
- memset(&req->overlapped, 0, sizeof(req->overlapped));
-}
-
-
-static DWORD WINAPI uv_work_thread_proc(void* parameter) {
- uv_work_t* req = (uv_work_t*)parameter;
- uv_loop_t* loop = req->loop;
-
- assert(req != NULL);
- assert(req->type == UV_WORK);
- assert(req->work_cb);
-
- req->work_cb(req);
-
- POST_COMPLETION_FOR_REQ(loop, req);
-
- return 0;
-}
-
-
-int uv_queue_work(uv_loop_t* loop, uv_work_t* req, uv_work_cb work_cb,
- uv_after_work_cb after_work_cb) {
- if (work_cb == NULL)
- return UV_EINVAL;
-
- uv_work_req_init(loop, req, work_cb, after_work_cb);
-
- if (!QueueUserWorkItem(&uv_work_thread_proc, req, WT_EXECUTELONGFUNCTION)) {
- return uv_translate_sys_error(GetLastError());
- }
-
- uv__req_register(loop, req);
- return 0;
-}
-
-
-int uv_cancel(uv_req_t* req) {
- return UV_ENOSYS;
-}
-
-
-void uv_process_work_req(uv_loop_t* loop, uv_work_t* req) {
- uv__req_unregister(loop, req);
- if(req->after_work_cb)
- req->after_work_cb(req, 0);
-}
diff --git a/deps/uv/src/win/timer.c b/deps/uv/src/win/timer.c
index 16a2fc5f5f..c229d4c897 100644
--- a/deps/uv/src/win/timer.c
+++ b/deps/uv/src/win/timer.c
@@ -36,10 +36,11 @@ void uv_update_time(uv_loop_t* loop) {
time.QuadPart = loop->time;
- /* GetTickCount() can conceivably wrap around, so when the current tick */
- /* count is lower than the last tick count, we'll assume it has wrapped. */
- /* uv_poll must make sure that the timer can never overflow more than */
- /* once between two subsequent uv_update_time calls. */
+ /* GetTickCount() can conceivably wrap around, so when the current tick
+ * count is lower than the last tick count, we'll assume it has wrapped.
+ * uv_poll must make sure that the timer can never overflow more than
+ * once between two subsequent uv_update_time calls.
+ */
time.LowPart = ticks;
if (ticks < loop->last_tick_count)
time.HighPart++;
@@ -47,13 +48,14 @@ void uv_update_time(uv_loop_t* loop) {
/* Remember the last tick count. */
loop->last_tick_count = ticks;
- /* The GetTickCount() resolution isn't too good. Sometimes it'll happen */
- /* that GetQueuedCompletionStatus() or GetQueuedCompletionStatusEx() has */
- /* waited for a couple of ms but this is not reflected in the GetTickCount */
- /* result yet. Therefore whenever GetQueuedCompletionStatus times out */
- /* we'll add the number of ms that it has waited to the current loop time. */
- /* When that happened the loop time might be a little ms farther than what */
- /* we've just computed, and we shouldn't update the loop time. */
+ /* The GetTickCount() resolution isn't too good. Sometimes it'll happen
+ * that GetQueuedCompletionStatus() or GetQueuedCompletionStatusEx() has
+ * waited for a couple of ms but this is not reflected in the GetTickCount
+ * result yet. Therefore whenever GetQueuedCompletionStatus times out
+ * we'll add the number of ms that it has waited to the current loop time.
+ * When that happened the loop time might be a little ms farther than what
+ * we've just computed, and we shouldn't update the loop time.
+ */
if (loop->time < time.QuadPart)
loop->time = time.QuadPart;
}
@@ -193,24 +195,26 @@ uint64_t uv_timer_get_repeat(const uv_timer_t* handle) {
}
-DWORD uv_get_poll_timeout(uv_loop_t* loop) {
+DWORD uv__next_timeout(const uv_loop_t* loop) {
uv_timer_t* timer;
int64_t delta;
- /* Check if there are any running timers */
- timer = RB_MIN(uv_timer_tree_s, &loop->timers);
+ /* Check if there are any running timers
+ * Need to cast away const first, since RB_MIN doesn't know what we are
+ * going to do with this return value, it can't be marked const
+ */
+ timer = RB_MIN(uv_timer_tree_s, &((uv_loop_t*)loop)->timers);
if (timer) {
- uv_update_time(loop);
-
delta = timer->due - loop->time;
if (delta >= UINT_MAX >> 1) {
- /* A timeout value of UINT_MAX means infinite, so that's no good. But */
- /* more importantly, there's always the risk that GetTickCount wraps. */
- /* uv_update_time can detect this, but we must make sure that the */
- /* tick counter never overflows twice between two subsequent */
- /* uv_update_time calls. We do this by never sleeping more than half */
- /* the time it takes to wrap the counter - which is huge overkill, */
- /* but hey, it's not so bad to wake up every 25 days. */
+ /* A timeout value of UINT_MAX means infinite, so that's no good. But
+ * more importantly, there's always the risk that GetTickCount wraps.
+ * uv_update_time can detect this, but we must make sure that the
+ * tick counter never overflows twice between two subsequent
+ * uv_update_time calls. We do this by never sleeping more than half
+ * the time it takes to wrap the counter - which is huge overkill,
+ * but hey, it's not so bad to wake up every 25 days.
+ */
return UINT_MAX >> 1;
} else if (delta < 0) {
/* Negative timeout values are not allowed */
diff --git a/deps/uv/src/win/tty.c b/deps/uv/src/win/tty.c
index 87e3eb5d8a..6b8297cbd9 100644
--- a/deps/uv/src/win/tty.c
+++ b/deps/uv/src/win/tty.c
@@ -30,6 +30,10 @@
# include <stdint.h>
#endif
+#ifndef COMMON_LVB_REVERSE_VIDEO
+# define COMMON_LVB_REVERSE_VIDEO 0x4000
+#endif
+
#include "uv.h"
#include "internal.h"
#include "handle-inl.h"
diff --git a/deps/uv/src/win/udp.c b/deps/uv/src/win/udp.c
index 865890455a..ef63dd73df 100644
--- a/deps/uv/src/win/udp.c
+++ b/deps/uv/src/win/udp.c
@@ -37,8 +37,9 @@ const unsigned int uv_active_udp_streams_threshold = 0;
/* A zero-size buffer for use by uv_udp_read */
static char uv_zero_[] = "";
-int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name,
- int* namelen) {
+int uv_udp_getsockname(const uv_udp_t* handle,
+ struct sockaddr* name,
+ int* namelen) {
int result;
if (!(handle->flags & UV_HANDLE_BOUND)) {
@@ -129,6 +130,8 @@ int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) {
handle->activecnt = 0;
handle->func_wsarecv = WSARecv;
handle->func_wsarecvfrom = WSARecvFrom;
+ handle->send_queue_size = 0;
+ handle->send_queue_count = 0;
uv_req_init(loop, (uv_req_t*) &(handle->recv_req));
handle->recv_req.type = UV_UDP_RECV;
@@ -396,12 +399,16 @@ static int uv__send(uv_udp_send_t* req,
/* Request completed immediately. */
req->queued_bytes = 0;
handle->reqs_pending++;
+ handle->send_queue_size += req->queued_bytes;
+ handle->send_queue_count++;
REGISTER_HANDLE_REQ(loop, handle, req);
uv_insert_pending_req(loop, (uv_req_t*)req);
} else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
/* Request queued by the kernel. */
- req->queued_bytes = uv_count_bufs(bufs, nbufs);
+ req->queued_bytes = uv__count_bufs(bufs, nbufs);
handle->reqs_pending++;
+ handle->send_queue_size += req->queued_bytes;
+ handle->send_queue_count++;
REGISTER_HANDLE_REQ(loop, handle, req);
} else {
/* Send failed due to an error. */
@@ -524,6 +531,11 @@ void uv_process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle,
assert(handle->type == UV_UDP);
+ assert(handle->send_queue_size >= req->queued_bytes);
+ assert(handle->send_queue_count >= 1);
+ handle->send_queue_size -= req->queued_bytes;
+ handle->send_queue_count--;
+
UNREGISTER_HANDLE_REQ(loop, handle, req);
if (req->cb) {
@@ -860,3 +872,12 @@ int uv__udp_send(uv_udp_send_t* req,
return 0;
}
+
+
+int uv__udp_try_send(uv_udp_t* handle,
+ const uv_buf_t bufs[],
+ unsigned int nbufs,
+ const struct sockaddr* addr,
+ unsigned int addrlen) {
+ return UV_ENOSYS;
+}
diff --git a/deps/uv/test/run-tests.c b/deps/uv/test/run-tests.c
index cd50ee09f3..d8f3cda540 100644
--- a/deps/uv/test/run-tests.c
+++ b/deps/uv/test/run-tests.c
@@ -39,6 +39,7 @@
int ipc_helper(int listen_after_write);
int ipc_helper_tcp_connection(void);
int ipc_send_recv_helper(void);
+int ipc_helper_bind_twice(void);
int stdio_over_pipes_helper(void);
static int maybe_run_test(int argc, char **argv);
@@ -82,6 +83,10 @@ static int maybe_run_test(int argc, char **argv) {
return ipc_helper_tcp_connection();
}
+ if (strcmp(argv[1], "ipc_helper_bind_twice") == 0) {
+ return ipc_helper_bind_twice();
+ }
+
if (strcmp(argv[1], "stdio_over_pipes_helper") == 0) {
return stdio_over_pipes_helper();
}
diff --git a/deps/uv/test/test-barrier.c b/deps/uv/test/test-barrier.c
index 25a55d6cfe..dfd2dbdef1 100644
--- a/deps/uv/test/test-barrier.c
+++ b/deps/uv/test/test-barrier.c
@@ -41,10 +41,6 @@ static void worker(void* arg) {
uv_sleep(c->delay);
c->worker_barrier_wait_rval = uv_barrier_wait(&c->barrier);
- if (c->worker_barrier_wait_rval == 1) {
- uv_barrier_destroy(&c->barrier);
- ASSERT(c->main_barrier_wait_rval == 0);
- }
}
@@ -53,21 +49,16 @@ TEST_IMPL(barrier_1) {
worker_config wc;
memset(&wc, 0, sizeof(wc));
- wc.main_barrier_wait_rval = -1;
- wc.worker_barrier_wait_rval = -1;
ASSERT(0 == uv_barrier_init(&wc.barrier, 2));
ASSERT(0 == uv_thread_create(&thread, worker, &wc));
uv_sleep(100);
-
wc.main_barrier_wait_rval = uv_barrier_wait(&wc.barrier);
- if (wc.main_barrier_wait_rval == 1) {
- uv_barrier_destroy(&wc.barrier);
- ASSERT(wc.worker_barrier_wait_rval == 0);
- }
ASSERT(0 == uv_thread_join(&thread));
+ uv_barrier_destroy(&wc.barrier);
+
ASSERT(1 == (wc.main_barrier_wait_rval ^ wc.worker_barrier_wait_rval));
return 0;
@@ -80,19 +71,15 @@ TEST_IMPL(barrier_2) {
memset(&wc, 0, sizeof(wc));
wc.delay = 100;
- wc.main_barrier_wait_rval = -1;
- wc.worker_barrier_wait_rval = -1;
ASSERT(0 == uv_barrier_init(&wc.barrier, 2));
ASSERT(0 == uv_thread_create(&thread, worker, &wc));
wc.main_barrier_wait_rval = uv_barrier_wait(&wc.barrier);
- if (wc.main_barrier_wait_rval == 1) {
- uv_barrier_destroy(&wc.barrier);
- ASSERT(wc.worker_barrier_wait_rval == 0);
- }
ASSERT(0 == uv_thread_join(&thread));
+ uv_barrier_destroy(&wc.barrier);
+
ASSERT(1 == (wc.main_barrier_wait_rval ^ wc.worker_barrier_wait_rval));
return 0;
@@ -104,19 +91,15 @@ TEST_IMPL(barrier_3) {
worker_config wc;
memset(&wc, 0, sizeof(wc));
- wc.main_barrier_wait_rval = -1;
- wc.worker_barrier_wait_rval = -1;
ASSERT(0 == uv_barrier_init(&wc.barrier, 2));
ASSERT(0 == uv_thread_create(&thread, worker, &wc));
wc.main_barrier_wait_rval = uv_barrier_wait(&wc.barrier);
- if (wc.main_barrier_wait_rval == 1) {
- uv_barrier_destroy(&wc.barrier);
- ASSERT(wc.worker_barrier_wait_rval == 0);
- }
ASSERT(0 == uv_thread_join(&thread));
+ uv_barrier_destroy(&wc.barrier);
+
ASSERT(1 == (wc.main_barrier_wait_rval ^ wc.worker_barrier_wait_rval));
return 0;
diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c
index 40c7726cad..4c6ccfab2c 100644
--- a/deps/uv/test/test-fs.c
+++ b/deps/uv/test/test-fs.c
@@ -65,6 +65,7 @@ static int read_cb_count;
static int write_cb_count;
static int unlink_cb_count;
static int mkdir_cb_count;
+static int mkdtemp_cb_count;
static int rmdir_cb_count;
static int readdir_cb_count;
static int stat_cb_count;
@@ -93,6 +94,8 @@ static uv_fs_t write_req;
static uv_fs_t unlink_req;
static uv_fs_t close_req;
static uv_fs_t mkdir_req;
+static uv_fs_t mkdtemp_req1;
+static uv_fs_t mkdtemp_req2;
static uv_fs_t rmdir_req;
static uv_fs_t readdir_req;
static uv_fs_t stat_req;
@@ -376,6 +379,32 @@ static void mkdir_cb(uv_fs_t* req) {
}
+static void check_mkdtemp_result(uv_fs_t* req) {
+ int r;
+
+ ASSERT(req->fs_type == UV_FS_MKDTEMP);
+ ASSERT(req->result == 0);
+ ASSERT(req->path);
+ ASSERT(strlen(req->path) == 15);
+ ASSERT(memcmp(req->path, "test_dir_", 9) == 0);
+ ASSERT(memcmp(req->path + 9, "XXXXXX", 6) != 0);
+ check_permission(req->path, 0700);
+
+ /* Check if req->path is actually a directory */
+ r = uv_fs_stat(uv_default_loop(), &stat_req, req->path, NULL);
+ ASSERT(r == 0);
+ ASSERT(((uv_stat_t*)stat_req.ptr)->st_mode & S_IFDIR);
+ uv_fs_req_cleanup(&stat_req);
+}
+
+
+static void mkdtemp_cb(uv_fs_t* req) {
+ ASSERT(req == &mkdtemp_req1);
+ check_mkdtemp_result(req);
+ mkdtemp_cb_count++;
+}
+
+
static void rmdir_cb(uv_fs_t* req) {
ASSERT(req == &rmdir_req);
ASSERT(req->fs_type == UV_FS_RMDIR);
@@ -927,6 +956,37 @@ TEST_IMPL(fs_async_sendfile) {
}
+TEST_IMPL(fs_mkdtemp) {
+ int r;
+ const char* path_template = "test_dir_XXXXXX";
+
+ loop = uv_default_loop();
+
+ r = uv_fs_mkdtemp(loop, &mkdtemp_req1, path_template, mkdtemp_cb);
+ ASSERT(r == 0);
+
+ uv_run(loop, UV_RUN_DEFAULT);
+ ASSERT(mkdtemp_cb_count == 1);
+
+ /* sync mkdtemp */
+ r = uv_fs_mkdtemp(loop, &mkdtemp_req2, path_template, NULL);
+ ASSERT(r == 0);
+ check_mkdtemp_result(&mkdtemp_req2);
+
+ /* mkdtemp return different values on subsequent calls */
+ ASSERT(strcmp(mkdtemp_req1.path, mkdtemp_req2.path) != 0);
+
+ /* Cleanup */
+ rmdir(mkdtemp_req1.path);
+ rmdir(mkdtemp_req2.path);
+ uv_fs_req_cleanup(&mkdtemp_req1);
+ uv_fs_req_cleanup(&mkdtemp_req2);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+
TEST_IMPL(fs_fstat) {
int r;
uv_fs_t req;
@@ -985,6 +1045,13 @@ TEST_IMPL(fs_fstat) {
ASSERT(s->st_birthtim.tv_nsec == t.st_birthtimespec.tv_nsec);
ASSERT(s->st_flags == t.st_flags);
ASSERT(s->st_gen == t.st_gen);
+#elif defined(_AIX)
+ ASSERT(s->st_atim.tv_sec == t.st_atime);
+ ASSERT(s->st_atim.tv_nsec == 0);
+ ASSERT(s->st_mtim.tv_sec == t.st_mtime);
+ ASSERT(s->st_mtim.tv_nsec == 0);
+ ASSERT(s->st_ctim.tv_sec == t.st_ctime);
+ ASSERT(s->st_ctim.tv_nsec == 0);
#elif defined(__sun) || \
defined(_BSD_SOURCE) || \
defined(_SVID_SOURCE) || \
diff --git a/deps/uv/test/test-getsockname.c b/deps/uv/test/test-getsockname.c
index a67d967f0b..565c17fe50 100644
--- a/deps/uv/test/test-getsockname.c
+++ b/deps/uv/test/test-getsockname.c
@@ -353,6 +353,9 @@ TEST_IMPL(getsockname_udp) {
ASSERT(getsocknamecount == 2);
+ ASSERT(udp.send_queue_size == 0);
+ ASSERT(udpServer.send_queue_size == 0);
+
MAKE_VALGRIND_HAPPY();
return 0;
}
diff --git a/deps/uv/test/test-ipc.c b/deps/uv/test/test-ipc.c
index 61b649b66c..ed8c4dd7f0 100644
--- a/deps/uv/test/test-ipc.c
+++ b/deps/uv/test/test-ipc.c
@@ -27,6 +27,7 @@
static uv_pipe_t channel;
static uv_tcp_t tcp_server;
+static uv_tcp_t tcp_server2;
static uv_tcp_t tcp_connection;
static int exit_cb_called;
@@ -38,8 +39,6 @@ static int local_conn_accepted;
static int remote_conn_accepted;
static int tcp_server_listening;
static uv_write_t write_req;
-static uv_pipe_t channel;
-static uv_tcp_t tcp_server;
static uv_write_t conn_notify_req;
static int close_cb_called;
static int connection_accepted;
@@ -205,6 +204,71 @@ static void on_read(uv_stream_t* handle,
free(buf->base);
}
+#ifdef _WIN32
+static void on_read_listen_after_bound_twice(uv_stream_t* handle,
+ ssize_t nread,
+ const uv_buf_t* buf) {
+ int r;
+ uv_pipe_t* pipe;
+ uv_handle_type pending;
+
+ pipe = (uv_pipe_t*) handle;
+
+ if (nread == 0) {
+ /* Everything OK, but nothing read. */
+ free(buf->base);
+ return;
+ }
+
+ if (nread < 0) {
+ if (nread == UV_EOF) {
+ free(buf->base);
+ return;
+ }
+
+ printf("error recving on channel: %s\n", uv_strerror(nread));
+ abort();
+ }
+
+ fprintf(stderr, "got %d bytes\n", (int)nread);
+
+ ASSERT(uv_pipe_pending_count(pipe) > 0);
+ pending = uv_pipe_pending_type(pipe);
+ ASSERT(nread > 0 && buf->base && pending != UV_UNKNOWN_HANDLE);
+ read_cb_called++;
+
+ if (read_cb_called == 1) {
+ /* Accept the first TCP server, and start listening on it. */
+ ASSERT(pending == UV_TCP);
+ r = uv_tcp_init(uv_default_loop(), &tcp_server);
+ ASSERT(r == 0);
+
+ r = uv_accept((uv_stream_t*)pipe, (uv_stream_t*)&tcp_server);
+ ASSERT(r == 0);
+
+ r = uv_listen((uv_stream_t*)&tcp_server, 12, on_connection);
+ ASSERT(r == 0);
+ } else if (read_cb_called == 2) {
+ /* Accept the second TCP server, and start listening on it. */
+ ASSERT(pending == UV_TCP);
+ r = uv_tcp_init(uv_default_loop(), &tcp_server2);
+ ASSERT(r == 0);
+
+ r = uv_accept((uv_stream_t*)pipe, (uv_stream_t*)&tcp_server2);
+ ASSERT(r == 0);
+
+ r = uv_listen((uv_stream_t*)&tcp_server2, 12, on_connection);
+ ASSERT(r == UV_EADDRINUSE);
+
+ uv_close((uv_handle_t*)&tcp_server, NULL);
+ uv_close((uv_handle_t*)&tcp_server2, NULL);
+ ASSERT(0 == uv_pipe_pending_count(pipe));
+ uv_close((uv_handle_t*)&channel, NULL);
+ }
+
+ free(buf->base);
+}
+#endif
void spawn_helper(uv_pipe_t* channel,
uv_process_t* process,
@@ -424,6 +488,13 @@ TEST_IMPL(listen_no_simultaneous_accepts) {
MAKE_VALGRIND_HAPPY();
return 0;
}
+
+TEST_IMPL(ipc_listen_after_bind_twice) {
+ int r = run_ipc_test("ipc_helper_bind_twice", on_read_listen_after_bound_twice);
+ ASSERT(read_cb_called == 2);
+ ASSERT(exit_cb_called == 1);
+ return r;
+}
#endif
@@ -608,7 +679,7 @@ int ipc_helper(int listen_after_write) {
int ipc_helper_tcp_connection(void) {
/*
- * This is launched from test-ipc.c. stdin is a duplex channel that we
+ * This is launched from test-ipc.c. stdin is a duplex channel
* over which a handle will be transmitted.
*/
@@ -657,3 +728,51 @@ int ipc_helper_tcp_connection(void) {
MAKE_VALGRIND_HAPPY();
return 0;
}
+
+int ipc_helper_bind_twice(void) {
+ /*
+ * This is launched from test-ipc.c. stdin is a duplex channel
+ * over which two handles will be transmitted.
+ */
+ struct sockaddr_in addr;
+ uv_write_t write_req;
+ uv_write_t write_req2;
+ int r;
+ uv_buf_t buf;
+
+ ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
+
+ r = uv_pipe_init(uv_default_loop(), &channel, 1);
+ ASSERT(r == 0);
+
+ uv_pipe_open(&channel, 0);
+
+ ASSERT(1 == uv_is_readable((uv_stream_t*) &channel));
+ ASSERT(1 == uv_is_writable((uv_stream_t*) &channel));
+ ASSERT(0 == uv_is_closing((uv_handle_t*) &channel));
+
+ buf = uv_buf_init("hello\n", 6);
+
+ r = uv_tcp_init(uv_default_loop(), &tcp_server);
+ ASSERT(r == 0);
+ r = uv_tcp_init(uv_default_loop(), &tcp_server2);
+ ASSERT(r == 0);
+
+ r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0);
+ ASSERT(r == 0);
+ r = uv_tcp_bind(&tcp_server2, (const struct sockaddr*) &addr, 0);
+ ASSERT(r == 0);
+
+ r = uv_write2(&write_req, (uv_stream_t*)&channel, &buf, 1,
+ (uv_stream_t*)&tcp_server, NULL);
+ ASSERT(r == 0);
+ r = uv_write2(&write_req2, (uv_stream_t*)&channel, &buf, 1,
+ (uv_stream_t*)&tcp_server2, NULL);
+ ASSERT(r == 0);
+
+ r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
+ ASSERT(r == 0);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h
index 15c2e4ed38..6dbe22307e 100644
--- a/deps/uv/test/test-list.h
+++ b/deps/uv/test/test-list.h
@@ -28,6 +28,7 @@ TEST_DECLARE (loop_alive)
TEST_DECLARE (loop_close)
TEST_DECLARE (loop_stop)
TEST_DECLARE (loop_update_time)
+TEST_DECLARE (loop_backend_timeout)
TEST_DECLARE (barrier_1)
TEST_DECLARE (barrier_2)
TEST_DECLARE (barrier_3)
@@ -56,6 +57,7 @@ TEST_DECLARE (delayed_accept)
TEST_DECLARE (multiple_listen)
TEST_DECLARE (tcp_writealot)
TEST_DECLARE (tcp_try_write)
+TEST_DECLARE (tcp_write_queue_order)
TEST_DECLARE (tcp_open)
TEST_DECLARE (tcp_connect_error_after_write)
TEST_DECLARE (tcp_shutdown_after_write)
@@ -71,7 +73,9 @@ TEST_DECLARE (tcp_connect_error_fault)
TEST_DECLARE (tcp_connect_timeout)
TEST_DECLARE (tcp_close_while_connecting)
TEST_DECLARE (tcp_close)
+#ifndef _WIN32
TEST_DECLARE (tcp_close_accept)
+#endif
TEST_DECLARE (tcp_flags)
TEST_DECLARE (tcp_write_to_half_open_connection)
TEST_DECLARE (tcp_unexpected_read)
@@ -84,6 +88,7 @@ TEST_DECLARE (tcp_bind6_localhost_ok)
TEST_DECLARE (udp_bind)
TEST_DECLARE (udp_bind_reuseaddr)
TEST_DECLARE (udp_send_and_recv)
+TEST_DECLARE (udp_send_immediate)
TEST_DECLARE (udp_multicast_join)
TEST_DECLARE (udp_multicast_join6)
TEST_DECLARE (udp_multicast_ttl)
@@ -95,6 +100,7 @@ TEST_DECLARE (udp_ipv6_only)
TEST_DECLARE (udp_options)
TEST_DECLARE (udp_no_autobind)
TEST_DECLARE (udp_open)
+TEST_DECLARE (udp_try_send)
TEST_DECLARE (pipe_bind_error_addrinuse)
TEST_DECLARE (pipe_bind_error_addrnotavail)
TEST_DECLARE (pipe_bind_error_inval)
@@ -186,6 +192,7 @@ TEST_DECLARE (spawn_stdout_to_file)
TEST_DECLARE (spawn_stdout_and_stderr_to_file)
TEST_DECLARE (spawn_auto_unref)
TEST_DECLARE (spawn_closed_process_io)
+TEST_DECLARE (spawn_reads_child_path)
TEST_DECLARE (fs_poll)
TEST_DECLARE (fs_poll_getpath)
TEST_DECLARE (kill)
@@ -197,6 +204,7 @@ TEST_DECLARE (fs_file_sync)
TEST_DECLARE (fs_file_write_null_buffer)
TEST_DECLARE (fs_async_dir)
TEST_DECLARE (fs_async_sendfile)
+TEST_DECLARE (fs_mkdtemp)
TEST_DECLARE (fs_fstat)
TEST_DECLARE (fs_chmod)
TEST_DECLARE (fs_chown)
@@ -254,6 +262,7 @@ TEST_DECLARE (listen_with_simultaneous_accepts)
TEST_DECLARE (listen_no_simultaneous_accepts)
TEST_DECLARE (fs_stat_root)
TEST_DECLARE (spawn_with_an_odd_path)
+TEST_DECLARE (ipc_listen_after_bind_twice)
#else
TEST_DECLARE (emfile)
TEST_DECLARE (close_fd)
@@ -286,6 +295,7 @@ TASK_LIST_START
TEST_ENTRY (loop_close)
TEST_ENTRY (loop_stop)
TEST_ENTRY (loop_update_time)
+ TEST_ENTRY (loop_backend_timeout)
TEST_ENTRY (barrier_1)
TEST_ENTRY (barrier_2)
TEST_ENTRY (barrier_3)
@@ -330,6 +340,8 @@ TASK_LIST_START
TEST_ENTRY (tcp_try_write)
+ TEST_ENTRY (tcp_write_queue_order)
+
TEST_ENTRY (tcp_open)
TEST_HELPER (tcp_open, tcp4_echo_server)
@@ -349,7 +361,9 @@ TASK_LIST_START
TEST_ENTRY (tcp_connect_timeout)
TEST_ENTRY (tcp_close_while_connecting)
TEST_ENTRY (tcp_close)
+#ifndef _WIN32
TEST_ENTRY (tcp_close_accept)
+#endif
TEST_ENTRY (tcp_flags)
TEST_ENTRY (tcp_write_to_half_open_connection)
TEST_ENTRY (tcp_unexpected_read)
@@ -366,6 +380,7 @@ TASK_LIST_START
TEST_ENTRY (udp_bind)
TEST_ENTRY (udp_bind_reuseaddr)
TEST_ENTRY (udp_send_and_recv)
+ TEST_ENTRY (udp_send_immediate)
TEST_ENTRY (udp_dgram_too_big)
TEST_ENTRY (udp_dual_stack)
TEST_ENTRY (udp_ipv6_only)
@@ -376,6 +391,7 @@ TASK_LIST_START
TEST_ENTRY (udp_multicast_join)
TEST_ENTRY (udp_multicast_join6)
TEST_ENTRY (udp_multicast_ttl)
+ TEST_ENTRY (udp_try_send)
TEST_ENTRY (udp_open)
TEST_HELPER (udp_open, udp4_echo_server)
@@ -505,6 +521,7 @@ TASK_LIST_START
TEST_ENTRY (spawn_stdout_and_stderr_to_file)
TEST_ENTRY (spawn_auto_unref)
TEST_ENTRY (spawn_closed_process_io)
+ TEST_ENTRY (spawn_reads_child_path)
TEST_ENTRY (fs_poll)
TEST_ENTRY (fs_poll_getpath)
TEST_ENTRY (kill)
@@ -518,6 +535,7 @@ TASK_LIST_START
TEST_ENTRY (listen_no_simultaneous_accepts)
TEST_ENTRY (fs_stat_root)
TEST_ENTRY (spawn_with_an_odd_path)
+ TEST_ENTRY (ipc_listen_after_bind_twice)
#else
TEST_ENTRY (emfile)
TEST_ENTRY (close_fd)
@@ -541,6 +559,7 @@ TASK_LIST_START
TEST_ENTRY (fs_file_write_null_buffer)
TEST_ENTRY (fs_async_dir)
TEST_ENTRY (fs_async_sendfile)
+ TEST_ENTRY (fs_mkdtemp)
TEST_ENTRY (fs_fstat)
TEST_ENTRY (fs_chmod)
TEST_ENTRY (fs_chown)
diff --git a/deps/uv/test/test-loop-time.c b/deps/uv/test/test-loop-time.c
index 49dc79b2c3..a2db42ccee 100644
--- a/deps/uv/test/test-loop-time.c
+++ b/deps/uv/test/test-loop-time.c
@@ -30,5 +30,34 @@ TEST_IMPL(loop_update_time) {
while (uv_now(uv_default_loop()) - start < 1000)
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_NOWAIT));
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+static void cb(uv_timer_t* timer) {
+ uv_close((uv_handle_t*)timer, NULL);
+}
+
+TEST_IMPL(loop_backend_timeout) {
+ uv_loop_t *loop = uv_default_loop();
+ uv_timer_t timer;
+ int r;
+
+ r = uv_timer_init(loop, &timer);
+ ASSERT(r == 0);
+
+ ASSERT(!uv_loop_alive(loop));
+ ASSERT(uv_backend_timeout(loop) == 0);
+
+ r = uv_timer_start(&timer, cb, 1000, 0); /* 1 sec */
+ ASSERT(r == 0);
+ ASSERT(uv_backend_timeout(loop) > 100); /* 0.1 sec */
+ ASSERT(uv_backend_timeout(loop) <= 1000); /* 1 sec */
+
+ r = uv_run(loop, UV_RUN_DEFAULT);
+ ASSERT(r == 0);
+ ASSERT(uv_backend_timeout(loop) == 0);
+
+ MAKE_VALGRIND_HAPPY();
return 0;
}
diff --git a/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c
index c75f1ca2fd..57f0862f94 100644
--- a/deps/uv/test/test-spawn.c
+++ b/deps/uv/test/test-spawn.c
@@ -31,6 +31,7 @@
# include <basetyps.h>
# endif
# include <shellapi.h>
+# include <wchar.h>
#else
# include <unistd.h>
#endif
@@ -897,45 +898,110 @@ TEST_IMPL(environment_creation) {
"SYSTEM=ROOT", /* substring of a supplied var name */
"SYSTEMROOTED=OMG", /* supplied var name is a substring */
"TEMP=C:\\Temp",
+ "INVALID",
"BAZ=QUX",
+ "B_Z=QUX",
+ "B\xe2\x82\xacZ=QUX",
+ "B\xf0\x90\x80\x82Z=QUX",
+ "B\xef\xbd\xa1Z=QUX",
+ "B\xf0\xa3\x91\x96Z=QUX",
+ "BAZ", /* repeat, invalid variable */
NULL
};
-
- WCHAR expected[512];
- WCHAR* ptr = expected;
+ WCHAR* wenvironment[] = {
+ L"BAZ=QUX",
+ L"B_Z=QUX",
+ L"B\x20acZ=QUX",
+ L"B\xd800\xdc02Z=QUX",
+ L"B\xd84d\xdc56Z=QUX",
+ L"B\xff61Z=QUX",
+ L"FOO=BAR",
+ L"SYSTEM=ROOT", /* substring of a supplied var name */
+ L"SYSTEMROOTED=OMG", /* supplied var name is a substring */
+ L"TEMP=C:\\Temp",
+ };
+ WCHAR* from_env[] = {
+ /* list should be kept in sync with list
+ * in process.c, minus variables in wenvironment */
+ L"HOMEDRIVE",
+ L"HOMEPATH",
+ L"LOGONSERVER",
+ L"PATH",
+ L"USERDOMAIN",
+ L"USERNAME",
+ L"USERPROFILE",
+ L"SYSTEMDRIVE",
+ L"SYSTEMROOT",
+ L"WINDIR",
+ /* test for behavior in the absence of a
+ * required-environment variable: */
+ L"ZTHIS_ENV_VARIABLE_DOES_NOT_EXIST",
+ };
+ int found_in_loc_env[ARRAY_SIZE(wenvironment)] = {0};
+ int found_in_usr_env[ARRAY_SIZE(from_env)] = {0};
+ WCHAR *expected[ARRAY_SIZE(from_env)];
int result;
WCHAR* str;
+ WCHAR* prev;
WCHAR* env;
- for (i = 0; i < sizeof(environment) / sizeof(environment[0]) - 1; i++) {
- ptr += uv_utf8_to_utf16(environment[i],
- ptr,
- expected + sizeof(expected) - ptr);
+ for (i = 0; i < ARRAY_SIZE(from_env); i++) {
+ /* copy expected additions to environment locally */
+ size_t len = GetEnvironmentVariableW(from_env[i], NULL, 0);
+ if (len == 0) {
+ found_in_usr_env[i] = 1;
+ str = malloc(1 * sizeof(WCHAR));
+ *str = 0;
+ expected[i] = str;
+ } else {
+ size_t name_len = wcslen(from_env[i]);
+ str = malloc((name_len+1+len) * sizeof(WCHAR));
+ wmemcpy(str, from_env[i], name_len);
+ expected[i] = str;
+ str += name_len;
+ *str++ = L'=';
+ GetEnvironmentVariableW(from_env[i], str, len);
+ }
}
- memcpy(ptr, L"SYSTEMROOT=", sizeof(L"SYSTEMROOT="));
- ptr += sizeof(L"SYSTEMROOT=")/sizeof(WCHAR) - 1;
- ptr += GetEnvironmentVariableW(L"SYSTEMROOT",
- ptr,
- expected + sizeof(expected) - ptr);
- ++ptr;
-
- memcpy(ptr, L"SYSTEMDRIVE=", sizeof(L"SYSTEMDRIVE="));
- ptr += sizeof(L"SYSTEMDRIVE=")/sizeof(WCHAR) - 1;
- ptr += GetEnvironmentVariableW(L"SYSTEMDRIVE",
- ptr,
- expected + sizeof(expected) - ptr);
- ++ptr;
- *ptr = '\0';
-
result = make_program_env(environment, &env);
ASSERT(result == 0);
- for (str = env; *str; str += wcslen(str) + 1) {
- wprintf(L"%s\n", str);
+ for (str = env, prev = NULL; *str; prev = str, str += wcslen(str) + 1) {
+ int found = 0;
+#if 0
+ _cputws(str);
+ putchar('\n');
+#endif
+ for (i = 0; i < ARRAY_SIZE(wenvironment) && !found; i++) {
+ if (!wcscmp(str, wenvironment[i])) {
+ ASSERT(!found_in_loc_env[i]);
+ found_in_loc_env[i] = 1;
+ found = 1;
+ }
+ }
+ for (i = 0; i < ARRAY_SIZE(expected) && !found; i++) {
+ if (!wcscmp(str, expected[i])) {
+ ASSERT(!found_in_usr_env[i]);
+ found_in_usr_env[i] = 1;
+ found = 1;
+ }
+ }
+ if (prev) { /* verify sort order -- requires Vista */
+#if _WIN32_WINNT >= 0x0600
+ ASSERT(CompareStringOrdinal(prev, -1, str, -1, TRUE) == 1);
+#endif
+ }
+ ASSERT(found); /* verify that we expected this variable */
}
- ASSERT(wcscmp(expected, env) == 0);
+ /* verify that we found all expected variables */
+ for (i = 0; i < ARRAY_SIZE(wenvironment); i++) {
+ ASSERT(found_in_loc_env[i]);
+ }
+ for (i = 0; i < ARRAY_SIZE(expected); i++) {
+ ASSERT(found_in_usr_env[i]);
+ }
return 0;
}
@@ -1225,3 +1291,38 @@ TEST_IMPL(closed_fd_events) {
return 0;
}
#endif /* !_WIN32 */
+
+TEST_IMPL(spawn_reads_child_path) {
+ int r;
+ int len;
+ char path[1024];
+ char *env[2] = {path, NULL};
+
+ /* Set up the process, but make sure that the file to run is relative and */
+ /* requires a lookup into PATH */
+ init_process_options("spawn_helper1", exit_cb);
+ options.file = "run-tests";
+ args[0] = "run-tests";
+
+ /* Set up the PATH env variable */
+ for (len = strlen(exepath);
+ exepath[len - 1] != '/' && exepath[len - 1] != '\\';
+ len--);
+ exepath[len] = 0;
+ strcpy(path, "PATH=");
+ strcpy(path + 5, exepath);
+
+ options.env = env;
+
+ r = uv_spawn(uv_default_loop(), &process, &options);
+ ASSERT(r == 0);
+
+ r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
+ ASSERT(r == 0);
+
+ ASSERT(exit_cb_called == 1);
+ ASSERT(close_cb_called == 1);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
diff --git a/deps/uv/test/test-tcp-close-accept.c b/deps/uv/test/test-tcp-close-accept.c
index 10f9d91964..5517aaf99e 100644
--- a/deps/uv/test/test-tcp-close-accept.c
+++ b/deps/uv/test/test-tcp-close-accept.c
@@ -19,6 +19,9 @@
* IN THE SOFTWARE.
*/
+/* this test is Unix only */
+#ifndef _WIN32
+
#include "uv.h"
#include "task.h"
@@ -181,3 +184,5 @@ TEST_IMPL(tcp_close_accept) {
MAKE_VALGRIND_HAPPY();
return 0;
}
+
+#endif /* !_WIN32 */
diff --git a/deps/uv/test/test-tcp-try-write.c b/deps/uv/test/test-tcp-try-write.c
index 00341e4169..baff6cf36c 100644
--- a/deps/uv/test/test-tcp-try-write.c
+++ b/deps/uv/test/test-tcp-try-write.c
@@ -54,21 +54,19 @@ static void close_cb(uv_handle_t* handle) {
static void connect_cb(uv_connect_t* req, int status) {
- static char zeroes[1024];
int r;
uv_buf_t buf;
ASSERT(status == 0);
connect_cb_called++;
do {
- buf = uv_buf_init(zeroes, sizeof(zeroes));
+ buf = uv_buf_init("PING", 4);
r = uv_try_write((uv_stream_t*) &client, &buf, 1);
- ASSERT(r >= 0);
- bytes_written += r;
-
- /* Partial write */
- if (r != (int) sizeof(zeroes))
+ ASSERT(r > 0 || r == UV_EAGAIN);
+ if (r > 0) {
+ bytes_written += r;
break;
+ }
} while (1);
uv_close((uv_handle_t*) &client, close_cb);
}
diff --git a/deps/uv/test/test-tcp-write-queue-order.c b/deps/uv/test/test-tcp-write-queue-order.c
new file mode 100644
index 0000000000..18e1f192b6
--- /dev/null
+++ b/deps/uv/test/test-tcp-write-queue-order.c
@@ -0,0 +1,137 @@
+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "uv.h"
+#include "task.h"
+
+#define REQ_COUNT 100000
+
+static uv_timer_t timer;
+static uv_tcp_t server;
+static uv_tcp_t client;
+static uv_tcp_t incoming;
+static int connect_cb_called;
+static int close_cb_called;
+static int connection_cb_called;
+static int write_callbacks;
+static int write_cancelled_callbacks;
+static int write_error_callbacks;
+
+static uv_write_t write_requests[REQ_COUNT];
+
+
+static void close_cb(uv_handle_t* handle) {
+ close_cb_called++;
+}
+
+void timer_cb(uv_timer_t* handle) {
+ uv_close((uv_handle_t*) &client, close_cb);
+ uv_close((uv_handle_t*) &server, close_cb);
+ uv_close((uv_handle_t*) &incoming, close_cb);
+}
+
+void write_cb(uv_write_t* req, int status) {
+ if (status == 0)
+ write_callbacks++;
+ else if (status == UV_ECANCELED)
+ write_cancelled_callbacks++;
+ else
+ write_error_callbacks++;
+}
+
+static void connect_cb(uv_connect_t* req, int status) {
+ static char base[1024];
+ int r;
+ int i;
+ uv_buf_t buf;
+
+ ASSERT(status == 0);
+ connect_cb_called++;
+
+ buf = uv_buf_init(base, sizeof(base));
+
+ for (i = 0; i < REQ_COUNT; i++) {
+ r = uv_write(&write_requests[i],
+ req->handle,
+ &buf,
+ 1,
+ write_cb);
+ ASSERT(r == 0);
+ }
+}
+
+
+static void connection_cb(uv_stream_t* tcp, int status) {
+ ASSERT(status == 0);
+
+ ASSERT(0 == uv_tcp_init(tcp->loop, &incoming));
+ ASSERT(0 == uv_accept(tcp, (uv_stream_t*) &incoming));
+
+ connection_cb_called++;
+}
+
+
+static void start_server(void) {
+ struct sockaddr_in addr;
+
+ ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
+
+ ASSERT(0 == uv_tcp_init(uv_default_loop(), &server));
+ ASSERT(0 == uv_tcp_bind(&server, (struct sockaddr*) &addr, 0));
+ ASSERT(0 == uv_listen((uv_stream_t*) &server, 128, connection_cb));
+}
+
+
+TEST_IMPL(tcp_write_queue_order) {
+ uv_connect_t connect_req;
+ struct sockaddr_in addr;
+
+ start_server();
+
+ ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
+
+ ASSERT(0 == uv_tcp_init(uv_default_loop(), &client));
+ ASSERT(0 == uv_tcp_connect(&connect_req,
+ &client,
+ (struct sockaddr*) &addr,
+ connect_cb));
+
+ ASSERT(0 == uv_timer_init(uv_default_loop(), &timer));
+ ASSERT(0 == uv_timer_start(&timer, timer_cb, 100, 0));
+
+ ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
+
+ ASSERT(connect_cb_called == 1);
+ ASSERT(connection_cb_called == 1);
+ ASSERT(write_callbacks > 0);
+ ASSERT(write_cancelled_callbacks > 0);
+ ASSERT(write_callbacks +
+ write_error_callbacks +
+ write_cancelled_callbacks == REQ_COUNT);
+ ASSERT(close_cb_called == 3);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
diff --git a/deps/uv/test/test-udp-multicast-interface.c b/deps/uv/test/test-udp-multicast-interface.c
index 643df31802..f0679c578e 100644
--- a/deps/uv/test/test-udp-multicast-interface.c
+++ b/deps/uv/test/test-udp-multicast-interface.c
@@ -91,6 +91,9 @@ TEST_IMPL(udp_multicast_interface) {
ASSERT(sv_send_cb_called == 1);
ASSERT(close_cb_called == 1);
+ ASSERT(client.send_queue_size == 0);
+ ASSERT(server.send_queue_size == 0);
+
MAKE_VALGRIND_HAPPY();
return 0;
}
diff --git a/deps/uv/test/test-udp-open.c b/deps/uv/test/test-udp-open.c
index 9a97303f12..b2b6117784 100644
--- a/deps/uv/test/test-udp-open.c
+++ b/deps/uv/test/test-udp-open.c
@@ -159,6 +159,8 @@ TEST_IMPL(udp_open) {
ASSERT(send_cb_called == 1);
ASSERT(close_cb_called == 1);
+ ASSERT(client.send_queue_size == 0);
+
MAKE_VALGRIND_HAPPY();
return 0;
}
diff --git a/deps/uv/test/test-udp-send-and-recv.c b/deps/uv/test/test-udp-send-and-recv.c
index 3020ded7bf..633a16727b 100644
--- a/deps/uv/test/test-udp-send-and-recv.c
+++ b/deps/uv/test/test-udp-send-and-recv.c
@@ -206,6 +206,9 @@ TEST_IMPL(udp_send_and_recv) {
ASSERT(sv_recv_cb_called == 1);
ASSERT(close_cb_called == 2);
+ ASSERT(client.send_queue_size == 0);
+ ASSERT(server.send_queue_size == 0);
+
MAKE_VALGRIND_HAPPY();
return 0;
}
diff --git a/deps/uv/test/test-udp-send-immediate.c b/deps/uv/test/test-udp-send-immediate.c
new file mode 100644
index 0000000000..0999f6b342
--- /dev/null
+++ b/deps/uv/test/test-udp-send-immediate.c
@@ -0,0 +1,148 @@
+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "task.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define CHECK_HANDLE(handle) \
+ ASSERT((uv_udp_t*)(handle) == &server || (uv_udp_t*)(handle) == &client)
+
+static uv_udp_t server;
+static uv_udp_t client;
+
+static int cl_send_cb_called;
+static int sv_recv_cb_called;
+static int close_cb_called;
+
+
+static void alloc_cb(uv_handle_t* handle,
+ size_t suggested_size,
+ uv_buf_t* buf) {
+ static char slab[65536];
+ CHECK_HANDLE(handle);
+ ASSERT(suggested_size <= sizeof(slab));
+ buf->base = slab;
+ buf->len = sizeof(slab);
+}
+
+
+static void close_cb(uv_handle_t* handle) {
+ CHECK_HANDLE(handle);
+ ASSERT(1 == uv_is_closing(handle));
+ close_cb_called++;
+}
+
+
+static void cl_send_cb(uv_udp_send_t* req, int status) {
+ ASSERT(req != NULL);
+ ASSERT(status == 0);
+ CHECK_HANDLE(req->handle);
+
+ cl_send_cb_called++;
+}
+
+
+static void sv_recv_cb(uv_udp_t* handle,
+ ssize_t nread,
+ const uv_buf_t* rcvbuf,
+ const struct sockaddr* addr,
+ unsigned flags) {
+ if (nread < 0) {
+ ASSERT(0 && "unexpected error");
+ }
+
+ if (nread == 0) {
+ /* Returning unused buffer */
+ /* Don't count towards sv_recv_cb_called */
+ ASSERT(addr == NULL);
+ return;
+ }
+
+ CHECK_HANDLE(handle);
+ ASSERT(flags == 0);
+
+ ASSERT(addr != NULL);
+ ASSERT(nread == 4);
+ ASSERT(memcmp("PING", rcvbuf->base, nread) == 0 ||
+ memcmp("PANG", rcvbuf->base, nread) == 0);
+
+ if (++sv_recv_cb_called == 2) {
+ uv_close((uv_handle_t*) &server, close_cb);
+ uv_close((uv_handle_t*) &client, close_cb);
+ }
+}
+
+
+TEST_IMPL(udp_send_immediate) {
+ struct sockaddr_in addr;
+ uv_udp_send_t req1, req2;
+ uv_buf_t buf;
+ int r;
+
+ ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
+
+ r = uv_udp_init(uv_default_loop(), &server);
+ ASSERT(r == 0);
+
+ r = uv_udp_bind(&server, (const struct sockaddr*) &addr, 0);
+ ASSERT(r == 0);
+
+ r = uv_udp_recv_start(&server, alloc_cb, sv_recv_cb);
+ ASSERT(r == 0);
+
+ ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
+
+ r = uv_udp_init(uv_default_loop(), &client);
+ ASSERT(r == 0);
+
+ /* client sends "PING", then "PANG" */
+ buf = uv_buf_init("PING", 4);
+
+ r = uv_udp_send(&req1,
+ &client,
+ &buf,
+ 1,
+ (const struct sockaddr*) &addr,
+ cl_send_cb);
+ ASSERT(r == 0);
+
+ buf = uv_buf_init("PANG", 4);
+
+ r = uv_udp_send(&req2,
+ &client,
+ &buf,
+ 1,
+ (const struct sockaddr*) &addr,
+ cl_send_cb);
+
+ uv_run(uv_default_loop(), UV_RUN_DEFAULT);
+
+ ASSERT(cl_send_cb_called == 2);
+ ASSERT(sv_recv_cb_called == 2);
+ ASSERT(close_cb_called == 2);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
diff --git a/deps/uv/test/test-udp-try-send.c b/deps/uv/test/test-udp-try-send.c
new file mode 100644
index 0000000000..7b6de36548
--- /dev/null
+++ b/deps/uv/test/test-udp-try-send.c
@@ -0,0 +1,133 @@
+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "task.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef _WIN32
+
+TEST_IMPL(udp_try_send) {
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+#else /* !_WIN32 */
+
+#define CHECK_HANDLE(handle) \
+ ASSERT((uv_udp_t*)(handle) == &server || (uv_udp_t*)(handle) == &client)
+
+static uv_udp_t server;
+static uv_udp_t client;
+
+static int sv_recv_cb_called;
+
+static int close_cb_called;
+
+
+static void alloc_cb(uv_handle_t* handle,
+ size_t suggested_size,
+ uv_buf_t* buf) {
+ static char slab[65536];
+ CHECK_HANDLE(handle);
+ ASSERT(suggested_size <= sizeof(slab));
+ buf->base = slab;
+ buf->len = sizeof(slab);
+}
+
+
+static void close_cb(uv_handle_t* handle) {
+ CHECK_HANDLE(handle);
+ ASSERT(uv_is_closing(handle));
+ close_cb_called++;
+}
+
+
+static void sv_recv_cb(uv_udp_t* handle,
+ ssize_t nread,
+ const uv_buf_t* rcvbuf,
+ const struct sockaddr* addr,
+ unsigned flags) {
+ ASSERT(nread > 0);
+
+ if (nread == 0) {
+ ASSERT(addr == NULL);
+ return;
+ }
+
+ ASSERT(nread == 4);
+ ASSERT(addr != NULL);
+
+ ASSERT(memcmp("EXIT", rcvbuf->base, nread) == 0);
+ uv_close((uv_handle_t*) handle, close_cb);
+ uv_close((uv_handle_t*) &client, close_cb);
+
+ sv_recv_cb_called++;
+}
+
+
+TEST_IMPL(udp_try_send) {
+ struct sockaddr_in addr;
+ static char buffer[64 * 1024];
+ uv_buf_t buf;
+ int r;
+
+ ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
+
+ r = uv_udp_init(uv_default_loop(), &server);
+ ASSERT(r == 0);
+
+ r = uv_udp_bind(&server, (const struct sockaddr*) &addr, 0);
+ ASSERT(r == 0);
+
+ r = uv_udp_recv_start(&server, alloc_cb, sv_recv_cb);
+ ASSERT(r == 0);
+
+ ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
+
+ r = uv_udp_init(uv_default_loop(), &client);
+ ASSERT(r == 0);
+
+ buf = uv_buf_init(buffer, sizeof(buffer));
+ r = uv_udp_try_send(&client, &buf, 1, (const struct sockaddr*) &addr);
+ ASSERT(r == UV_EMSGSIZE);
+
+ buf = uv_buf_init("EXIT", 4);
+ r = uv_udp_try_send(&client, &buf, 1, (const struct sockaddr*) &addr);
+ ASSERT(r == 4);
+
+ uv_run(uv_default_loop(), UV_RUN_DEFAULT);
+
+ ASSERT(close_cb_called == 2);
+ ASSERT(sv_recv_cb_called == 1);
+
+ ASSERT(client.send_queue_size == 0);
+ ASSERT(server.send_queue_size == 0);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+#endif /* !_WIN32 */
diff --git a/deps/uv/test/test-watcher-cross-stop.c b/deps/uv/test/test-watcher-cross-stop.c
index 9284a1291f..bf765cb00c 100644
--- a/deps/uv/test/test-watcher-cross-stop.c
+++ b/deps/uv/test/test-watcher-cross-stop.c
@@ -91,7 +91,7 @@ TEST_IMPL(watcher_cross_stop) {
for (i = 0; i < ARRAY_SIZE(sockets); i++)
uv_close((uv_handle_t*) &sockets[i], close_cb);
- ASSERT(0 < recv_cb_called && recv_cb_called <= ARRAY_SIZE(sockets));
+ ASSERT(recv_cb_called > 0);
ASSERT(ARRAY_SIZE(sockets) == send_cb_called);
uv_run(loop, UV_RUN_DEFAULT);
diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp
index 147fc06c3a..5b4d69a924 100644
--- a/deps/uv/uv.gyp
+++ b/deps/uv/uv.gyp
@@ -61,11 +61,13 @@
'include/uv.h',
'include/tree.h',
'include/uv-errno.h',
+ 'include/uv-threadpool.h',
'include/uv-version.h',
'src/fs-poll.c',
'src/heap-inl.h',
'src/inet.c',
'src/queue.h',
+ 'src/threadpool.c',
'src/uv-common.c',
'src/uv-common.h',
'src/version.c'
@@ -103,7 +105,6 @@
'src/win/stream-inl.h',
'src/win/tcp.c',
'src/win/tty.c',
- 'src/win/threadpool.c',
'src/win/timer.c',
'src/win/udp.c',
'src/win/util.c',
@@ -114,11 +115,11 @@
],
'link_settings': {
'libraries': [
- '-ladvapi32.lib',
- '-liphlpapi.lib',
- '-lpsapi.lib',
- '-lshell32.lib',
- '-lws2_32.lib'
+ '-ladvapi32',
+ '-liphlpapi',
+ '-lpsapi',
+ '-lshell32',
+ '-lws2_32'
],
},
}, { # Not Windows i.e. POSIX
@@ -136,6 +137,7 @@
'include/uv-sunos.h',
'include/uv-darwin.h',
'include/uv-bsd.h',
+ 'include/uv-aix.h',
'src/unix/async.c',
'src/unix/atomic-ops.h',
'src/unix/core.c',
@@ -154,7 +156,6 @@
'src/unix/stream.c',
'src/unix/tcp.c',
'src/unix/thread.c',
- 'src/unix/threadpool.c',
'src/unix/timer.c',
'src/unix/tty.c',
'src/unix/udp.c',
@@ -245,6 +246,7 @@
'defines': [
'_ALL_SOURCE',
'_XOPEN_SOURCE=500',
+ '_LINUX_SOURCE_COMPAT',
],
'link_settings': {
'libraries': [
@@ -378,6 +380,7 @@
'test/test-tcp-try-write.c',
'test/test-tcp-unexpected-read.c',
'test/test-tcp-read-stop.c',
+ 'test/test-tcp-write-queue-order.c',
'test/test-threadpool.c',
'test/test-threadpool-cancel.c',
'test/test-mutexes.c',
@@ -394,6 +397,7 @@
'test/test-udp-open.c',
'test/test-udp-options.c',
'test/test-udp-send-and-recv.c',
+ 'test/test-udp-send-immediate.c',
'test/test-udp-multicast-join.c',
'test/test-udp-multicast-join6.c',
'test/test-dlerror.c',
@@ -402,6 +406,7 @@
'test/test-ip6-addr.c',
'test/test-udp-multicast-interface.c',
'test/test-udp-multicast-interface6.c',
+ 'test/test-udp-try-send.c',
],
'conditions': [
[ 'OS=="win"', {
@@ -409,7 +414,7 @@
'test/runner-win.c',
'test/runner-win.h'
],
- 'libraries': [ 'ws2_32.lib' ]
+ 'libraries': [ '-lws2_32' ]
}, { # POSIX
'defines': [ '_GNU_SOURCE' ],
'sources': [
@@ -473,7 +478,7 @@
'test/runner-win.c',
'test/runner-win.h',
],
- 'libraries': [ 'ws2_32.lib' ]
+ 'libraries': [ '-lws2_32' ]
}, { # POSIX
'defines': [ '_GNU_SOURCE' ],
'sources': [