mirror of
https://github.com/zebrajr/node.git
synced 2025-12-06 00:20:08 +01:00
deps: update libuv to v0.11.28
This commit is contained in:
parent
aa3b4b4d10
commit
e49429ebd2
4
deps/uv/.mailmap
vendored
4
deps/uv/.mailmap
vendored
|
|
@ -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>
|
||||
|
|
|
|||
9
deps/uv/AUTHORS
vendored
9
deps/uv/AUTHORS
vendored
|
|
@ -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>
|
||||
|
|
|
|||
91
deps/uv/ChangeLog
vendored
91
deps/uv/ChangeLog
vendored
|
|
@ -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:
|
||||
|
||||
|
|
|
|||
12
deps/uv/Makefile.am
vendored
12
deps/uv/Makefile.am
vendored
|
|
@ -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
|
||||
|
||||
|
|
|
|||
3
deps/uv/Makefile.mingw
vendored
3
deps/uv/Makefile.mingw
vendored
|
|
@ -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 \
|
||||
|
|
|
|||
7
deps/uv/README.md
vendored
7
deps/uv/README.md
vendored
|
|
@ -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
|
||||
|
|
|
|||
2
deps/uv/configure.ac
vendored
2
deps/uv/configure.ac
vendored
|
|
@ -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])
|
||||
|
|
|
|||
12
deps/uv/gyp_uv.py
vendored
12
deps/uv/gyp_uv.py
vendored
|
|
@ -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)
|
||||
|
|
|
|||
BIN
deps/uv/img/banner.png
vendored
Normal file
BIN
deps/uv/img/banner.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 43 KiB |
152
deps/uv/img/logos.svg
vendored
Normal file
152
deps/uv/img/logos.svg
vendored
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 64 KiB |
32
deps/uv/include/uv-aix.h
vendored
Normal file
32
deps/uv/include/uv-aix.h
vendored
Normal file
|
|
@ -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 */
|
||||
37
deps/uv/include/uv-threadpool.h
vendored
Normal file
37
deps/uv/include/uv-threadpool.h
vendored
Normal file
|
|
@ -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_ */
|
||||
13
deps/uv/include/uv-unix.h
vendored
13
deps/uv/include/uv-unix.h
vendored
|
|
@ -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; \
|
||||
|
|
|
|||
2
deps/uv/include/uv-version.h
vendored
2
deps/uv/include/uv-version.h
vendored
|
|
@ -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 */
|
||||
|
|
|
|||
22
deps/uv/include/uv-win.h
vendored
22
deps/uv/include/uv-win.h
vendored
|
|
@ -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 { \
|
||||
|
|
|
|||
412
deps/uv/include/uv.h
vendored
412
deps/uv/include/uv.h
vendored
|
|
@ -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.
|
||||
* 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 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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
878
deps/uv/src/unix/aix.c
vendored
878
deps/uv/src/unix/aix.c
vendored
|
|
@ -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 ((buffer == NULL) || (size == NULL))
|
||||
return -EINVAL;
|
||||
|
||||
if (size == NULL)
|
||||
return (-1);
|
||||
snprintf(pp, sizeof(pp), "/proc/%lu/psinfo", (unsigned long) getpid());
|
||||
|
||||
(void) snprintf(pp, sizeof(pp), "/proc/%lu/cwd", (unsigned long) getpid());
|
||||
|
||||
res = readlink(pp, cwdl, sizeof(cwdl) - 1);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
cwdl[res] = '\0';
|
||||
|
||||
(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;
|
||||
}
|
||||
|
|
|
|||
7
deps/uv/src/unix/core.c
vendored
7
deps/uv/src/unix/core.c
vendored
|
|
@ -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;
|
||||
|
|
|
|||
30
deps/uv/src/unix/fs.c
vendored
30
deps/uv/src/unix/fs.c
vendored
|
|
@ -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,
|
||||
|
|
|
|||
15
deps/uv/src/unix/internal.h
vendored
15
deps/uv/src/unix/internal.h
vendored
|
|
@ -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);
|
||||
|
|
|
|||
4
deps/uv/src/unix/loop.c
vendored
4
deps/uv/src/unix/loop.c
vendored
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
30
deps/uv/src/unix/openbsd.c
vendored
30
deps/uv/src/unix/openbsd.c
vendored
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
65
deps/uv/src/unix/stream.c
vendored
65
deps/uv/src/unix/stream.c
vendored
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
217
deps/uv/src/unix/udp.c
vendored
217
deps/uv/src/unix/udp.c
vendored
|
|
@ -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,23 +64,20 @@ 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);
|
||||
|
||||
if (req->bufs != req->bufsml)
|
||||
free(req->bufs);
|
||||
req->bufs = NULL;
|
||||
|
||||
if (req->send_cb != NULL)
|
||||
req->send_cb(req, -ECANCELED);
|
||||
req->status = -ECANCELED;
|
||||
QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue);
|
||||
}
|
||||
|
||||
uv__udp_run_completed(handle);
|
||||
|
||||
assert(handle->send_queue_size == 0);
|
||||
assert(handle->send_queue_count == 0);
|
||||
|
||||
/* Now tear down the handle. */
|
||||
handle->recv_cb = NULL;
|
||||
handle->alloc_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) {
|
||||
if (revents & UV__POLLIN)
|
||||
uv__udp_recvmsg(loop, w, revents);
|
||||
uv_udp_t* handle;
|
||||
|
||||
if (revents & UV__POLLOUT)
|
||||
uv__udp_sendmsg(loop, w, revents);
|
||||
handle = container_of(w, uv_udp_t, io_watcher);
|
||||
assert(handle->type == UV_UDP);
|
||||
|
||||
if (revents & UV__POLLIN)
|
||||
uv__udp_recvmsg(handle);
|
||||
|
||||
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,35 +204,44 @@ 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);
|
||||
|
||||
assert(!QUEUE_EMPTY(&handle->write_queue)
|
||||
|| !QUEUE_EMPTY(&handle->write_completed_queue));
|
||||
req = QUEUE_DATA(q, uv_udp_send_t, queue);
|
||||
assert(req != NULL);
|
||||
|
||||
/* Write out pending data first. */
|
||||
uv__udp_run_pending(handle);
|
||||
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;
|
||||
|
||||
/* Drain 'request completed' queue. */
|
||||
uv__udp_run_completed(handle);
|
||||
do {
|
||||
size = sendmsg(handle->io_watcher.fd, &h, 0);
|
||||
} while (size == -1 && errno == EINTR);
|
||||
|
||||
if (!QUEUE_EMPTY(&handle->write_completed_queue)) {
|
||||
/* Schedule completion callbacks. */
|
||||
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);
|
||||
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);
|
||||
|
||||
if (!uv__io_active(&handle->io_watcher, UV__POLLIN))
|
||||
uv__handle_stop(handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
33
deps/uv/src/uv-common.c
vendored
33
deps/uv/src/uv-common.c
vendored
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
15
deps/uv/src/uv-common.h
vendored
15
deps/uv/src/uv-common.h
vendored
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
161
deps/uv/src/win/core.c
vendored
161
deps/uv/src/win/core.c
vendored
|
|
@ -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);
|
||||
|
|
|
|||
1
deps/uv/src/win/error.c
vendored
1
deps/uv/src/win/error.c
vendored
|
|
@ -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;
|
||||
|
|
|
|||
177
deps/uv/src/win/fs.c
vendored
177
deps/uv/src/win/fs.c
vendored
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
63
deps/uv/src/win/getaddrinfo.c
vendored
63
deps/uv/src/win/getaddrinfo.c
vendored
|
|
@ -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;
|
||||
static void uv__getaddrinfo_work(struct uv__work* w) {
|
||||
uv_getaddrinfo_t* req;
|
||||
int err;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
|||
59
deps/uv/src/win/getnameinfo.c
vendored
59
deps/uv/src/win/getnameinfo.c
vendored
|
|
@ -27,23 +27,31 @@
|
|||
#include "internal.h"
|
||||
#include "req-inl.h"
|
||||
|
||||
#ifndef GetNameInfo
|
||||
int WSAAPI GetNameInfoW(
|
||||
const SOCKADDR *pSockaddr,
|
||||
socklen_t SockaddrLength,
|
||||
PWCHAR pNodeBuffer,
|
||||
DWORD NodeBufferSize,
|
||||
PWCHAR pServiceBuffer,
|
||||
DWORD ServiceBufferSize,
|
||||
INT Flags
|
||||
);
|
||||
#endif
|
||||
|
||||
/* 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;
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
35
deps/uv/src/win/internal.h
vendored
35
deps/uv/src/win/internal.h
vendored
|
|
@ -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);
|
||||
|
||||
|
|
@ -285,29 +293,10 @@ void uv_process_endgame(uv_loop_t* loop, uv_process_t* handle);
|
|||
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);
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
|||
64
deps/uv/src/win/pipe.c
vendored
64
deps/uv/src/win/pipe.c
vendored
|
|
@ -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, ¤t_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) {
|
||||
|
|
|
|||
288
deps/uv/src/win/process.c
vendored
288
deps/uv/src/win/process.c
vendored
|
|
@ -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();
|
||||
}
|
||||
|
||||
env_len += len;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(required_vars); ++i) {
|
||||
if (!required_vars[i].supplied) {
|
||||
env_len += required_vars[i].len;
|
||||
var_size = GetEnvironmentVariableW(required_vars[i].wide, NULL, 0);
|
||||
if (var_size == 0) {
|
||||
if (strchr(*env, '=')) {
|
||||
len = MultiByteToWideChar(CP_UTF8,
|
||||
0,
|
||||
*env,
|
||||
-1,
|
||||
NULL,
|
||||
0);
|
||||
if (len <= 0) {
|
||||
return GetLastError();
|
||||
}
|
||||
required_vars[i].value_len = var_size;
|
||||
env_len += var_size;
|
||||
env_len += len;
|
||||
env_block_count++;
|
||||
}
|
||||
}
|
||||
|
||||
dst = malloc(env_len * sizeof(WCHAR));
|
||||
/* 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*));
|
||||
|
||||
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);
|
||||
required_vars_value_len[i] = var_size;
|
||||
if (var_size != 0) {
|
||||
env_len += required_vars[i].len;
|
||||
env_len += var_size;
|
||||
}
|
||||
i++;
|
||||
} else {
|
||||
ptr_copy++;
|
||||
if (cmp == 0)
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
|
|
|||
16
deps/uv/src/win/req-inl.h
vendored
16
deps/uv/src/win/req-inl.h
vendored
|
|
@ -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;
|
||||
|
|
|
|||
11
deps/uv/src/win/stream-inl.h
vendored
11
deps/uv/src/win/stream-inl.h
vendored
|
|
@ -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_ */
|
||||
|
|
|
|||
65
deps/uv/src/win/tcp.c
vendored
65
deps/uv/src/win/tcp.c
vendored
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
81
deps/uv/src/win/threadpool.c
vendored
81
deps/uv/src/win/threadpool.c
vendored
|
|
@ -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);
|
||||
}
|
||||
50
deps/uv/src/win/timer.c
vendored
50
deps/uv/src/win/timer.c
vendored
|
|
@ -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 */
|
||||
|
|
|
|||
4
deps/uv/src/win/tty.c
vendored
4
deps/uv/src/win/tty.c
vendored
|
|
@ -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"
|
||||
|
|
|
|||
27
deps/uv/src/win/udp.c
vendored
27
deps/uv/src/win/udp.c
vendored
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
5
deps/uv/test/run-tests.c
vendored
5
deps/uv/test/run-tests.c
vendored
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
29
deps/uv/test/test-barrier.c
vendored
29
deps/uv/test/test-barrier.c
vendored
|
|
@ -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;
|
||||
|
|
|
|||
67
deps/uv/test/test-fs.c
vendored
67
deps/uv/test/test-fs.c
vendored
|
|
@ -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) || \
|
||||
|
|
|
|||
3
deps/uv/test/test-getsockname.c
vendored
3
deps/uv/test/test-getsockname.c
vendored
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
125
deps/uv/test/test-ipc.c
vendored
125
deps/uv/test/test-ipc.c
vendored
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
19
deps/uv/test/test-list.h
vendored
19
deps/uv/test/test-list.h
vendored
|
|
@ -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)
|
||||
|
|
|
|||
29
deps/uv/test/test-loop-time.c
vendored
29
deps/uv/test/test-loop-time.c
vendored
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
151
deps/uv/test/test-spawn.c
vendored
151
deps/uv/test/test-spawn.c
vendored
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
5
deps/uv/test/test-tcp-close-accept.c
vendored
5
deps/uv/test/test-tcp-close-accept.c
vendored
|
|
@ -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 */
|
||||
|
|
|
|||
12
deps/uv/test/test-tcp-try-write.c
vendored
12
deps/uv/test/test-tcp-try-write.c
vendored
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
137
deps/uv/test/test-tcp-write-queue-order.c
vendored
Normal file
137
deps/uv/test/test-tcp-write-queue-order.c
vendored
Normal file
|
|
@ -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;
|
||||
}
|
||||
3
deps/uv/test/test-udp-multicast-interface.c
vendored
3
deps/uv/test/test-udp-multicast-interface.c
vendored
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
2
deps/uv/test/test-udp-open.c
vendored
2
deps/uv/test/test-udp-open.c
vendored
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
3
deps/uv/test/test-udp-send-and-recv.c
vendored
3
deps/uv/test/test-udp-send-and-recv.c
vendored
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
148
deps/uv/test/test-udp-send-immediate.c
vendored
Normal file
148
deps/uv/test/test-udp-send-immediate.c
vendored
Normal file
|
|
@ -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;
|
||||
}
|
||||
133
deps/uv/test/test-udp-try-send.c
vendored
Normal file
133
deps/uv/test/test-udp-try-send.c
vendored
Normal file
|
|
@ -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 */
|
||||
2
deps/uv/test/test-watcher-cross-stop.c
vendored
2
deps/uv/test/test-watcher-cross-stop.c
vendored
|
|
@ -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);
|
||||
|
|
|
|||
23
deps/uv/uv.gyp
vendored
23
deps/uv/uv.gyp
vendored
|
|
@ -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': [
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user