Upgrade libuv to f1859eb841be2fe48512bc10e64556383f408b01
This commit is contained in:
parent
06d14f3a1c
commit
fdeb5ba304
62 changed files with 1619 additions and 355 deletions
|
|
@ -40,17 +40,17 @@ do
|
|||
|
||||
# Comment out the gyp auto regeneration
|
||||
for os in mac unix win; do
|
||||
sed -i "" \
|
||||
sed -i \
|
||||
-e 's/^\(Makefile: $(srcdir)\/src\/rt\/libuv\/uv\.gyp\)/#\1/' \
|
||||
mk/libuv/$ARCH/$os/Makefile
|
||||
|
||||
sed -i "" \
|
||||
sed -i \
|
||||
-e 's/^\( $(call do_cmd,regen_makefile)\)/#\1/' \
|
||||
mk/libuv/$ARCH/$os/Makefile
|
||||
done
|
||||
done
|
||||
|
||||
# On Mac, GYP hardcodes a -arch i386 into the output. Fix that.
|
||||
sed -i "" \
|
||||
sed -i \
|
||||
-e 's/-arch i386/-arch x86_64/' \
|
||||
mk/libuv/x86_64/mac/src/rt/libuv/*.mk
|
||||
|
|
|
|||
20
src/rt/libuv/build/gcc_version.py
Normal file
20
src/rt/libuv/build/gcc_version.py
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
def DoMain(*args):
|
||||
cc = os.environ.get('CC', 'gcc')
|
||||
stdin, stderr = os.pipe()
|
||||
subprocess.call([cc, '-v'], stderr=stderr)
|
||||
output = os.read(stdin, 4096)
|
||||
match = re.search("\ngcc version (\d+\.\d+\.\d+)", output)
|
||||
if match:
|
||||
print(match.group(1))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
DoMain(*sys.argv)
|
||||
|
|
@ -114,9 +114,11 @@
|
|||
],
|
||||
}],
|
||||
[ 'OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', {
|
||||
'cflags': [ '-Wall', '-pthread', ],
|
||||
'variables': {
|
||||
'gcc_version%': '<!(python build/gcc_version.py)>)',
|
||||
},
|
||||
'cflags': [ '-Wall' ],
|
||||
'cflags_cc': [ '-fno-rtti', '-fno-exceptions' ],
|
||||
'ldflags': [ '-pthread', ],
|
||||
'conditions': [
|
||||
[ 'host_arch != target_arch and target_arch=="ia32"', {
|
||||
'cflags': [ '-m32' ],
|
||||
|
|
@ -125,7 +127,14 @@
|
|||
[ 'OS=="linux"', {
|
||||
'cflags': [ '-ansi' ],
|
||||
}],
|
||||
[ 'visibility=="hidden"', {
|
||||
[ 'OS=="solaris"', {
|
||||
'cflags': [ '-pthreads' ],
|
||||
'ldflags': [ '-pthreads' ],
|
||||
}, {
|
||||
'cflags': [ '-pthread' ],
|
||||
'ldflags': [ '-pthread' ],
|
||||
}],
|
||||
[ 'visibility=="hidden" and gcc_version >= "4.0.0"', {
|
||||
'cflags': [ '-fvisibility=hidden' ],
|
||||
}],
|
||||
],
|
||||
|
|
@ -143,7 +152,6 @@
|
|||
'GCC_INLINES_ARE_PRIVATE_EXTERN': 'YES',
|
||||
'GCC_SYMBOLS_PRIVATE_EXTERN': 'YES', # -fvisibility=hidden
|
||||
'GCC_THREADSAFE_STATICS': 'NO', # -fno-threadsafe-statics
|
||||
'GCC_VERSION': '4.2',
|
||||
'GCC_WARN_ABOUT_MISSING_NEWLINE': 'YES', # -Wnewline-eof
|
||||
'MACOSX_DEPLOYMENT_TARGET': '10.4', # -mmacosx-version-min=10.4
|
||||
'PREBINDING': 'NO', # No -Wl,-prebind
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ CPPFLAGS += -D_LARGEFILE_SOURCE
|
|||
CPPFLAGS += -D_FILE_OFFSET_BITS=64
|
||||
|
||||
OBJS += src/unix/core.o
|
||||
OBJS += src/unix/dl.o
|
||||
OBJS += src/unix/fs.o
|
||||
OBJS += src/unix/cares.o
|
||||
OBJS += src/unix/udp.o
|
||||
|
|
|
|||
|
|
@ -43,6 +43,10 @@ typedef struct {
|
|||
|
||||
typedef int uv_file;
|
||||
|
||||
/* Platform-specific definitions for uv_dlopen support. */
|
||||
typedef void* uv_lib_t;
|
||||
#define UV_DYNAMIC /* empty */
|
||||
|
||||
#define UV_LOOP_PRIVATE_FIELDS \
|
||||
ares_channel channel; \
|
||||
/* \
|
||||
|
|
@ -195,6 +199,16 @@ typedef int uv_file;
|
|||
uv_fs_event_cb cb; \
|
||||
int fflags; \
|
||||
|
||||
#elif defined(__sun)
|
||||
|
||||
#include <sys/port.h>
|
||||
#include <port.h>
|
||||
|
||||
#define UV_FS_EVENT_PRIVATE_FIELDS \
|
||||
ev_io event_watcher; \
|
||||
uv_fs_event_cb cb; \
|
||||
file_obj_t fo; \
|
||||
|
||||
#else
|
||||
|
||||
/* Stub for platforms where the file watcher isn't implemented yet. */
|
||||
|
|
|
|||
|
|
@ -137,6 +137,10 @@ typedef struct uv_buf_t {
|
|||
|
||||
typedef int uv_file;
|
||||
|
||||
/* Platform-specific definitions for uv_dlopen support. */
|
||||
typedef HMODULE uv_lib_t;
|
||||
#define UV_DYNAMIC FAR WINAPI
|
||||
|
||||
RB_HEAD(uv_timer_tree_s, uv_timer_s);
|
||||
|
||||
#define UV_LOOP_PRIVATE_FIELDS \
|
||||
|
|
@ -243,6 +247,7 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
|
|||
|
||||
#define uv_tcp_server_fields \
|
||||
uv_tcp_accept_t* accept_reqs; \
|
||||
unsigned int processed_accepts; \
|
||||
uv_tcp_accept_t* pending_accepts; \
|
||||
LPFN_ACCEPTEX func_acceptex;
|
||||
|
||||
|
|
|
|||
|
|
@ -27,10 +27,29 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
/* Windows - set up dll import/export decorators. */
|
||||
# if defined(BUILDING_UV_SHARED)
|
||||
/* Building shared library. Export everything from c-ares as well. */
|
||||
# define UV_EXTERN __declspec(dllexport)
|
||||
# define CARES_BUILDING_LIBRARY 1
|
||||
# elif defined(USING_UV_SHARED)
|
||||
/* Using shared library. Use shared c-ares as well. */
|
||||
# define UV_EXTERN __declspec(dllimport)
|
||||
# else
|
||||
/* Building static library. Build c-ares statically as well. */
|
||||
# define UV_EXTERN /* nothing */
|
||||
# define CARES_STATICLIB 1
|
||||
# endif
|
||||
#else
|
||||
/* Unix. TODO: symbol hiding */
|
||||
# define UV_EXTERN /* nothing */
|
||||
#endif
|
||||
|
||||
|
||||
#define UV_VERSION_MAJOR 0
|
||||
#define UV_VERSION_MINOR 1
|
||||
|
||||
#define CARES_STATICLIB 1
|
||||
|
||||
#include <stdint.h> /* int64_t */
|
||||
#include <sys/types.h> /* size_t */
|
||||
|
|
@ -52,7 +71,8 @@ typedef enum {
|
|||
UV_UNKNOWN = -1,
|
||||
UV_OK = 0,
|
||||
UV_EOF,
|
||||
UV_EACCESS,
|
||||
UV_EADDRINFO,
|
||||
UV_EACCES,
|
||||
UV_EAGAIN,
|
||||
UV_EADDRINUSE,
|
||||
UV_EADDRNOTAVAIL,
|
||||
|
|
@ -77,6 +97,7 @@ typedef enum {
|
|||
UV_ENOBUFS,
|
||||
UV_ENOMEM,
|
||||
UV_ENOTDIR,
|
||||
UV_EISDIR,
|
||||
UV_ENONET,
|
||||
UV_ENOPROTOOPT,
|
||||
UV_ENOTCONN,
|
||||
|
|
@ -170,30 +191,30 @@ typedef struct uv_work_s uv_work_t;
|
|||
* All callbacks in libuv are made asynchronously. That is they are never
|
||||
* made by the function that takes them as a parameter.
|
||||
*/
|
||||
uv_loop_t* uv_loop_new();
|
||||
void uv_loop_delete(uv_loop_t*);
|
||||
UV_EXTERN uv_loop_t* uv_loop_new(void);
|
||||
UV_EXTERN void uv_loop_delete(uv_loop_t*);
|
||||
|
||||
|
||||
/*
|
||||
* Returns the default loop.
|
||||
*/
|
||||
uv_loop_t* uv_default_loop();
|
||||
UV_EXTERN uv_loop_t* uv_default_loop(void);
|
||||
|
||||
/*
|
||||
* This function starts the event loop. It blocks until the reference count
|
||||
* of the loop drops to zero.
|
||||
*/
|
||||
int uv_run(uv_loop_t*);
|
||||
UV_EXTERN int uv_run (uv_loop_t*);
|
||||
|
||||
/*
|
||||
* Manually modify the event loop's reference count. Useful if the user wants
|
||||
* to have a handle or timeout that doesn't keep the loop alive.
|
||||
*/
|
||||
void uv_ref(uv_loop_t*);
|
||||
void uv_unref(uv_loop_t*);
|
||||
UV_EXTERN void uv_ref(uv_loop_t*);
|
||||
UV_EXTERN void uv_unref(uv_loop_t*);
|
||||
|
||||
void uv_update_time(uv_loop_t*);
|
||||
int64_t uv_now(uv_loop_t*);
|
||||
UV_EXTERN void uv_update_time(uv_loop_t*);
|
||||
UV_EXTERN int64_t uv_now(uv_loop_t*);
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -260,9 +281,9 @@ struct uv_err_s {
|
|||
* On error the user should then call uv_last_error() to determine
|
||||
* the error code.
|
||||
*/
|
||||
uv_err_t uv_last_error(uv_loop_t*);
|
||||
char* uv_strerror(uv_err_t err);
|
||||
const char* uv_err_name(uv_err_t err);
|
||||
UV_EXTERN uv_err_t uv_last_error(uv_loop_t*);
|
||||
UV_EXTERN const char* uv_strerror(uv_err_t err);
|
||||
UV_EXTERN const char* uv_err_name(uv_err_t err);
|
||||
|
||||
|
||||
#define UV_REQ_FIELDS \
|
||||
|
|
@ -291,7 +312,8 @@ UV_PRIVATE_REQ_TYPES
|
|||
* initialized stream. req should be an uninitalized shutdown request
|
||||
* struct. The cb is a called after shutdown is complete.
|
||||
*/
|
||||
int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb);
|
||||
UV_EXTERN int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle,
|
||||
uv_shutdown_cb cb);
|
||||
|
||||
struct uv_shutdown_s {
|
||||
UV_REQ_FIELDS
|
||||
|
|
@ -320,7 +342,7 @@ struct uv_handle_s {
|
|||
* Returns 1 if the prepare/check/idle handle has been started, 0 otherwise.
|
||||
* For other handle types this always returns 1.
|
||||
*/
|
||||
int uv_is_active(uv_handle_t* handle);
|
||||
UV_EXTERN int uv_is_active(uv_handle_t* handle);
|
||||
|
||||
/*
|
||||
* Request handle to be closed. close_cb will be called asynchronously after
|
||||
|
|
@ -330,7 +352,7 @@ int uv_is_active(uv_handle_t* handle);
|
|||
* close_cb will still be deferred to the next iteration of the event loop.
|
||||
* It gives you a chance to free up any resources associated with the handle.
|
||||
*/
|
||||
void uv_close(uv_handle_t* handle, uv_close_cb close_cb);
|
||||
UV_EXTERN void uv_close(uv_handle_t* handle, uv_close_cb close_cb);
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -339,7 +361,7 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb);
|
|||
* 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.
|
||||
*/
|
||||
uv_buf_t uv_buf_init(char* base, size_t len);
|
||||
UV_EXTERN uv_buf_t uv_buf_init(char* base, size_t len);
|
||||
|
||||
|
||||
#define UV_STREAM_FIELDS \
|
||||
|
|
@ -364,7 +386,7 @@ struct uv_stream_s {
|
|||
UV_STREAM_FIELDS
|
||||
};
|
||||
|
||||
int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb);
|
||||
UV_EXTERN int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb);
|
||||
|
||||
/*
|
||||
* This call is used in conjunction with uv_listen() to accept incoming
|
||||
|
|
@ -377,7 +399,7 @@ int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb);
|
|||
* once, it may fail. It is suggested to only call uv_accept once per
|
||||
* uv_connection_cb call.
|
||||
*/
|
||||
int uv_accept(uv_stream_t* server, uv_stream_t* client);
|
||||
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
|
||||
|
|
@ -389,15 +411,17 @@ int uv_accept(uv_stream_t* server, uv_stream_t* client);
|
|||
* eof; it happens when libuv requested a buffer through the alloc callback
|
||||
* but then decided that it didn't need that buffer.
|
||||
*/
|
||||
int uv_read_start(uv_stream_t*, uv_alloc_cb alloc_cb, uv_read_cb read_cb);
|
||||
UV_EXTERN int uv_read_start(uv_stream_t*, uv_alloc_cb alloc_cb,
|
||||
uv_read_cb read_cb);
|
||||
|
||||
int uv_read_stop(uv_stream_t*);
|
||||
UV_EXTERN int uv_read_stop(uv_stream_t*);
|
||||
|
||||
/*
|
||||
* Extended read methods for receiving handles over a pipe. The pipe must be
|
||||
* initialized with ipc == 1.
|
||||
*/
|
||||
int uv_read2_start(uv_stream_t*, uv_alloc_cb alloc_cb, uv_read2_cb read_cb);
|
||||
UV_EXTERN int uv_read2_start(uv_stream_t*, uv_alloc_cb alloc_cb,
|
||||
uv_read2_cb read_cb);
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -418,11 +442,11 @@ int uv_read2_start(uv_stream_t*, uv_alloc_cb alloc_cb, uv_read2_cb read_cb);
|
|||
* uv_write(req, stream, b, 2);
|
||||
*
|
||||
*/
|
||||
int uv_write(uv_write_t* req, uv_stream_t* handle, uv_buf_t bufs[], int bufcnt,
|
||||
uv_write_cb cb);
|
||||
UV_EXTERN int uv_write(uv_write_t* req, uv_stream_t* handle,
|
||||
uv_buf_t bufs[], int bufcnt, uv_write_cb cb);
|
||||
|
||||
int uv_write2(uv_write_t* req, uv_stream_t* handle, uv_buf_t bufs[], int bufcnt,
|
||||
uv_stream_t* send_handle, uv_write_cb cb);
|
||||
UV_EXTERN int uv_write2(uv_write_t* req, uv_stream_t* handle, uv_buf_t bufs[],
|
||||
int bufcnt, uv_stream_t* send_handle, uv_write_cb cb);
|
||||
|
||||
/* uv_write_t is a subclass of uv_req_t */
|
||||
struct uv_write_s {
|
||||
|
|
@ -446,21 +470,34 @@ struct uv_tcp_s {
|
|||
UV_TCP_PRIVATE_FIELDS
|
||||
};
|
||||
|
||||
int uv_tcp_init(uv_loop_t*, uv_tcp_t* handle);
|
||||
UV_EXTERN int uv_tcp_init(uv_loop_t*, uv_tcp_t* handle);
|
||||
|
||||
/* Enable/disable Nagle's algorithm. */
|
||||
int uv_tcp_nodelay(uv_tcp_t* handle, int enable);
|
||||
UV_EXTERN int uv_tcp_nodelay(uv_tcp_t* handle, int enable);
|
||||
|
||||
/* Enable/disable TCP keep-alive.
|
||||
*
|
||||
* `ms` is the initial delay in seconds, ignored when `enable` is zero.
|
||||
*/
|
||||
int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay);
|
||||
UV_EXTERN int uv_tcp_keepalive(uv_tcp_t* handle, int enable,
|
||||
unsigned int delay);
|
||||
|
||||
int uv_tcp_bind(uv_tcp_t* handle, struct sockaddr_in);
|
||||
int uv_tcp_bind6(uv_tcp_t* handle, struct sockaddr_in6);
|
||||
int uv_tcp_getsockname(uv_tcp_t* handle, struct sockaddr* name, int* namelen);
|
||||
int uv_tcp_getpeername(uv_tcp_t* handle, struct sockaddr* name, int* namelen);
|
||||
/*
|
||||
* This setting applies to Windows only.
|
||||
* 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).
|
||||
*/
|
||||
UV_EXTERN int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable);
|
||||
|
||||
UV_EXTERN int uv_tcp_bind(uv_tcp_t* handle, struct sockaddr_in);
|
||||
UV_EXTERN int uv_tcp_bind6(uv_tcp_t* handle, struct sockaddr_in6);
|
||||
UV_EXTERN int uv_tcp_getsockname(uv_tcp_t* handle, struct sockaddr* name,
|
||||
int* namelen);
|
||||
UV_EXTERN int uv_tcp_getpeername(uv_tcp_t* handle, struct sockaddr* name,
|
||||
int* namelen);
|
||||
|
||||
/*
|
||||
* uv_tcp_connect, uv_tcp_connect6
|
||||
|
|
@ -468,9 +505,9 @@ int uv_tcp_getpeername(uv_tcp_t* handle, struct sockaddr* name, int* namelen);
|
|||
* initialized TCP handle and an uninitialized uv_connect_t*. The callback
|
||||
* will be made when the connection is estabished.
|
||||
*/
|
||||
int uv_tcp_connect(uv_connect_t* req, uv_tcp_t* handle,
|
||||
UV_EXTERN int uv_tcp_connect(uv_connect_t* req, uv_tcp_t* handle,
|
||||
struct sockaddr_in address, uv_connect_cb cb);
|
||||
int uv_tcp_connect6(uv_connect_t* req, uv_tcp_t* handle,
|
||||
UV_EXTERN int uv_tcp_connect6(uv_connect_t* req, uv_tcp_t* handle,
|
||||
struct sockaddr_in6 address, uv_connect_cb cb);
|
||||
|
||||
/* uv_connect_t is a subclass of uv_req_t */
|
||||
|
|
@ -537,7 +574,7 @@ struct uv_udp_send_s {
|
|||
* Initialize a new UDP handle. The actual socket is created lazily.
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
int uv_udp_init(uv_loop_t*, uv_udp_t* handle);
|
||||
UV_EXTERN int uv_udp_init(uv_loop_t*, uv_udp_t* handle);
|
||||
|
||||
/*
|
||||
* Bind to a IPv4 address and port.
|
||||
|
|
@ -550,7 +587,8 @@ int uv_udp_init(uv_loop_t*, uv_udp_t* handle);
|
|||
* Returns:
|
||||
* 0 on success, -1 on error.
|
||||
*/
|
||||
int uv_udp_bind(uv_udp_t* handle, struct sockaddr_in addr, unsigned flags);
|
||||
UV_EXTERN int uv_udp_bind(uv_udp_t* handle, struct sockaddr_in addr,
|
||||
unsigned flags);
|
||||
|
||||
/*
|
||||
* Bind to a IPv6 address and port.
|
||||
|
|
@ -563,14 +601,17 @@ int uv_udp_bind(uv_udp_t* handle, struct sockaddr_in addr, unsigned flags);
|
|||
* Returns:
|
||||
* 0 on success, -1 on error.
|
||||
*/
|
||||
int uv_udp_bind6(uv_udp_t* handle, struct sockaddr_in6 addr, unsigned flags);
|
||||
int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name, int* namelen);
|
||||
UV_EXTERN int uv_udp_bind6(uv_udp_t* handle, struct sockaddr_in6 addr,
|
||||
unsigned flags);
|
||||
UV_EXTERN int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name,
|
||||
int* namelen);
|
||||
|
||||
/*
|
||||
* Set membership for a multicast address
|
||||
*
|
||||
* Arguments:
|
||||
* handle UDP handle. Should have been initialized with `uv_udp_init`.
|
||||
* 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
|
||||
|
|
@ -578,8 +619,9 @@ int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name, int* namelen);
|
|||
* Returns:
|
||||
* 0 on success, -1 on error.
|
||||
*/
|
||||
int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr,
|
||||
const char* interface_addr, uv_membership membership);
|
||||
UV_EXTERN int uv_udp_set_membership(uv_udp_t* handle,
|
||||
const char* multicast_addr, const char* interface_addr,
|
||||
uv_membership membership);
|
||||
|
||||
/*
|
||||
* Send data. If the socket has not previously been bound with `uv_udp_bind`
|
||||
|
|
@ -597,8 +639,9 @@ int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr,
|
|||
* Returns:
|
||||
* 0 on success, -1 on error.
|
||||
*/
|
||||
int uv_udp_send(uv_udp_send_t* req, uv_udp_t* handle, uv_buf_t bufs[],
|
||||
int bufcnt, struct sockaddr_in addr, uv_udp_send_cb send_cb);
|
||||
UV_EXTERN int uv_udp_send(uv_udp_send_t* req, uv_udp_t* handle,
|
||||
uv_buf_t bufs[], int bufcnt, struct sockaddr_in addr,
|
||||
uv_udp_send_cb send_cb);
|
||||
|
||||
/*
|
||||
* Send data. If the socket has not previously been bound with `uv_udp_bind6`,
|
||||
|
|
@ -615,8 +658,9 @@ int uv_udp_send(uv_udp_send_t* req, uv_udp_t* handle, uv_buf_t bufs[],
|
|||
* Returns:
|
||||
* 0 on success, -1 on error.
|
||||
*/
|
||||
int uv_udp_send6(uv_udp_send_t* req, uv_udp_t* handle, uv_buf_t bufs[],
|
||||
int bufcnt, struct sockaddr_in6 addr, uv_udp_send_cb send_cb);
|
||||
UV_EXTERN int uv_udp_send6(uv_udp_send_t* req, uv_udp_t* handle,
|
||||
uv_buf_t bufs[], int bufcnt, struct sockaddr_in6 addr,
|
||||
uv_udp_send_cb send_cb);
|
||||
|
||||
/*
|
||||
* Receive data. If the socket has not previously been bound with `uv_udp_bind`
|
||||
|
|
@ -631,7 +675,7 @@ int uv_udp_send6(uv_udp_send_t* req, uv_udp_t* handle, uv_buf_t bufs[],
|
|||
* Returns:
|
||||
* 0 on success, -1 on error.
|
||||
*/
|
||||
int uv_udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb,
|
||||
UV_EXTERN int uv_udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb,
|
||||
uv_udp_recv_cb recv_cb);
|
||||
|
||||
/*
|
||||
|
|
@ -643,7 +687,7 @@ int uv_udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb,
|
|||
* Returns:
|
||||
* 0 on success, -1 on error.
|
||||
*/
|
||||
int uv_udp_recv_stop(uv_udp_t* handle);
|
||||
UV_EXTERN int uv_udp_recv_stop(uv_udp_t* handle);
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -668,23 +712,23 @@ struct uv_tty_s {
|
|||
*
|
||||
* TTY streams which are not readable have blocking writes.
|
||||
*/
|
||||
int uv_tty_init(uv_loop_t*, uv_tty_t*, uv_file fd, int readable);
|
||||
UV_EXTERN int uv_tty_init(uv_loop_t*, uv_tty_t*, uv_file fd, int readable);
|
||||
|
||||
/*
|
||||
* Set mode. 0 for normal, 1 for raw.
|
||||
*/
|
||||
int uv_tty_set_mode(uv_tty_t*, int mode);
|
||||
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.
|
||||
*/
|
||||
void uv_tty_reset_mode();
|
||||
UV_EXTERN void uv_tty_reset_mode();
|
||||
|
||||
/*
|
||||
* Gets the current Window size. On success zero is returned.
|
||||
*/
|
||||
int uv_tty_get_winsize(uv_tty_t*, int* width, int* height);
|
||||
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
|
||||
|
|
@ -692,7 +736,7 @@ int uv_tty_get_winsize(uv_tty_t*, int* width, int* height);
|
|||
* type of the stdio streams.
|
||||
* For isatty() functionality use this function and test for UV_TTY.
|
||||
*/
|
||||
uv_handle_type uv_guess_handle(uv_file file);
|
||||
UV_EXTERN uv_handle_type uv_guess_handle(uv_file file);
|
||||
|
||||
/*
|
||||
* uv_pipe_t is a subclass of uv_stream_t
|
||||
|
|
@ -711,16 +755,16 @@ struct uv_pipe_s {
|
|||
* Initialize a pipe. The last argument is a boolean to indicate if
|
||||
* this pipe will be used for handle passing between processes.
|
||||
*/
|
||||
int uv_pipe_init(uv_loop_t*, uv_pipe_t* handle, int ipc);
|
||||
UV_EXTERN int uv_pipe_init(uv_loop_t*, uv_pipe_t* handle, int ipc);
|
||||
|
||||
/*
|
||||
* Opens an existing file descriptor or HANDLE as a pipe.
|
||||
*/
|
||||
void uv_pipe_open(uv_pipe_t*, uv_file file);
|
||||
UV_EXTERN void uv_pipe_open(uv_pipe_t*, uv_file file);
|
||||
|
||||
int uv_pipe_bind(uv_pipe_t* handle, const char* name);
|
||||
UV_EXTERN int uv_pipe_bind(uv_pipe_t* handle, const char* name);
|
||||
|
||||
int uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
|
||||
UV_EXTERN void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
|
||||
const char* name, uv_connect_cb cb);
|
||||
|
||||
|
||||
|
|
@ -736,11 +780,11 @@ struct uv_prepare_s {
|
|||
UV_PREPARE_PRIVATE_FIELDS
|
||||
};
|
||||
|
||||
int uv_prepare_init(uv_loop_t*, uv_prepare_t* prepare);
|
||||
UV_EXTERN int uv_prepare_init(uv_loop_t*, uv_prepare_t* prepare);
|
||||
|
||||
int uv_prepare_start(uv_prepare_t* prepare, uv_prepare_cb cb);
|
||||
UV_EXTERN int uv_prepare_start(uv_prepare_t* prepare, uv_prepare_cb cb);
|
||||
|
||||
int uv_prepare_stop(uv_prepare_t* prepare);
|
||||
UV_EXTERN int uv_prepare_stop(uv_prepare_t* prepare);
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -754,11 +798,11 @@ struct uv_check_s {
|
|||
UV_CHECK_PRIVATE_FIELDS
|
||||
};
|
||||
|
||||
int uv_check_init(uv_loop_t*, uv_check_t* check);
|
||||
UV_EXTERN int uv_check_init(uv_loop_t*, uv_check_t* check);
|
||||
|
||||
int uv_check_start(uv_check_t* check, uv_check_cb cb);
|
||||
UV_EXTERN int uv_check_start(uv_check_t* check, uv_check_cb cb);
|
||||
|
||||
int uv_check_stop(uv_check_t* check);
|
||||
UV_EXTERN int uv_check_stop(uv_check_t* check);
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -774,11 +818,11 @@ struct uv_idle_s {
|
|||
UV_IDLE_PRIVATE_FIELDS
|
||||
};
|
||||
|
||||
int uv_idle_init(uv_loop_t*, uv_idle_t* idle);
|
||||
UV_EXTERN int uv_idle_init(uv_loop_t*, uv_idle_t* idle);
|
||||
|
||||
int uv_idle_start(uv_idle_t* idle, uv_idle_cb cb);
|
||||
UV_EXTERN int uv_idle_start(uv_idle_t* idle, uv_idle_cb cb);
|
||||
|
||||
int uv_idle_stop(uv_idle_t* idle);
|
||||
UV_EXTERN int uv_idle_stop(uv_idle_t* idle);
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -796,14 +840,15 @@ struct uv_async_s {
|
|||
UV_ASYNC_PRIVATE_FIELDS
|
||||
};
|
||||
|
||||
int uv_async_init(uv_loop_t*, uv_async_t* async, uv_async_cb async_cb);
|
||||
UV_EXTERN int uv_async_init(uv_loop_t*, uv_async_t* async,
|
||||
uv_async_cb async_cb);
|
||||
|
||||
/*
|
||||
* This can be called from other threads to wake up a libuv thread.
|
||||
*
|
||||
* libuv is single threaded at the moment.
|
||||
*/
|
||||
int uv_async_send(uv_async_t* async);
|
||||
UV_EXTERN int uv_async_send(uv_async_t* async);
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -817,19 +862,19 @@ struct uv_timer_s {
|
|||
UV_TIMER_PRIVATE_FIELDS
|
||||
};
|
||||
|
||||
int uv_timer_init(uv_loop_t*, uv_timer_t* timer);
|
||||
UV_EXTERN int uv_timer_init(uv_loop_t*, uv_timer_t* timer);
|
||||
|
||||
int uv_timer_start(uv_timer_t* timer, uv_timer_cb cb, int64_t timeout,
|
||||
int64_t repeat);
|
||||
UV_EXTERN int uv_timer_start(uv_timer_t* timer, uv_timer_cb cb,
|
||||
int64_t timeout, int64_t repeat);
|
||||
|
||||
int uv_timer_stop(uv_timer_t* timer);
|
||||
UV_EXTERN int uv_timer_stop(uv_timer_t* timer);
|
||||
|
||||
/*
|
||||
* Stop the timer, and if it is repeating restart it using the repeat value
|
||||
* as the timeout. If the timer has never been started before it returns -1 and
|
||||
* sets the error to UV_EINVAL.
|
||||
*/
|
||||
int uv_timer_again(uv_timer_t* timer);
|
||||
UV_EXTERN int uv_timer_again(uv_timer_t* timer);
|
||||
|
||||
/*
|
||||
* Set the repeat value. Note that if the repeat value is set from a timer
|
||||
|
|
@ -837,19 +882,17 @@ int uv_timer_again(uv_timer_t* timer);
|
|||
* before, it will have been stopped. If it was repeating, then the old repeat
|
||||
* value will have been used to schedule the next timeout.
|
||||
*/
|
||||
void uv_timer_set_repeat(uv_timer_t* timer, int64_t repeat);
|
||||
UV_EXTERN void uv_timer_set_repeat(uv_timer_t* timer, int64_t repeat);
|
||||
|
||||
int64_t uv_timer_get_repeat(uv_timer_t* timer);
|
||||
UV_EXTERN int64_t uv_timer_get_repeat(uv_timer_t* timer);
|
||||
|
||||
|
||||
/* c-ares integration initialize and terminate */
|
||||
int uv_ares_init_options(uv_loop_t*,
|
||||
ares_channel *channelptr,
|
||||
struct ares_options *options,
|
||||
int optmask);
|
||||
UV_EXTERN int uv_ares_init_options(uv_loop_t*,
|
||||
ares_channel *channelptr, struct ares_options *options, int optmask);
|
||||
|
||||
/* TODO remove the loop argument from this function? */
|
||||
void uv_ares_destroy(uv_loop_t*, ares_channel channel);
|
||||
UV_EXTERN void uv_ares_destroy(uv_loop_t*, ares_channel channel);
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -877,14 +920,11 @@ struct uv_getaddrinfo_s {
|
|||
*
|
||||
* On error NXDOMAIN the status code will be non-zero and UV_ENOENT returned.
|
||||
*/
|
||||
int uv_getaddrinfo(uv_loop_t*,
|
||||
uv_getaddrinfo_t* handle,
|
||||
uv_getaddrinfo_cb getaddrinfo_cb,
|
||||
const char* node,
|
||||
const char* service,
|
||||
const struct addrinfo* hints);
|
||||
UV_EXTERN int uv_getaddrinfo(uv_loop_t*, uv_getaddrinfo_t* handle,
|
||||
uv_getaddrinfo_cb getaddrinfo_cb, const char* node, const char* service,
|
||||
const struct addrinfo* hints);
|
||||
|
||||
void uv_freeaddrinfo(struct addrinfo* ai);
|
||||
UV_EXTERN void uv_freeaddrinfo(struct addrinfo* ai);
|
||||
|
||||
/* uv_spawn() options */
|
||||
typedef struct uv_process_options_s {
|
||||
|
|
@ -934,13 +974,18 @@ struct uv_process_s {
|
|||
};
|
||||
|
||||
/* Initializes uv_process_t and starts the process. */
|
||||
int uv_spawn(uv_loop_t*, uv_process_t*, uv_process_options_t options);
|
||||
UV_EXTERN int uv_spawn(uv_loop_t*, uv_process_t*,
|
||||
uv_process_options_t options);
|
||||
|
||||
/*
|
||||
* Kills the process with the specified signal. The user must still
|
||||
* call uv_close on the process.
|
||||
*/
|
||||
int uv_process_kill(uv_process_t*, int signum);
|
||||
UV_EXTERN int uv_process_kill(uv_process_t*, int signum);
|
||||
|
||||
|
||||
/* Kills the process with the specified signal. */
|
||||
UV_EXTERN uv_err_t uv_kill(int pid, int signum);
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -955,8 +1000,8 @@ struct uv_work_s {
|
|||
};
|
||||
|
||||
/* Queues a work request to execute asynchronously on the thread pool. */
|
||||
int uv_queue_work(uv_loop_t* loop, uv_work_t* req, uv_work_cb work_cb,
|
||||
uv_after_work_cb after_work_cb);
|
||||
UV_EXTERN int uv_queue_work(uv_loop_t* loop, uv_work_t* req,
|
||||
uv_work_cb work_cb, uv_after_work_cb after_work_cb);
|
||||
|
||||
|
||||
|
||||
|
|
@ -1018,58 +1063,66 @@ struct uv_fs_s {
|
|||
UV_FS_PRIVATE_FIELDS
|
||||
};
|
||||
|
||||
void uv_fs_req_cleanup(uv_fs_t* req);
|
||||
UV_EXTERN void uv_fs_req_cleanup(uv_fs_t* req);
|
||||
|
||||
int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb);
|
||||
UV_EXTERN int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file,
|
||||
uv_fs_cb cb);
|
||||
|
||||
int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
|
||||
UV_EXTERN int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
||||
int flags, int mode, uv_fs_cb cb);
|
||||
|
||||
UV_EXTERN int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file,
|
||||
void* buf, size_t length, off_t offset, uv_fs_cb cb);
|
||||
|
||||
UV_EXTERN int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
||||
uv_fs_cb cb);
|
||||
|
||||
UV_EXTERN int uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file file,
|
||||
void* buf, size_t length, off_t offset, uv_fs_cb cb);
|
||||
|
||||
UV_EXTERN int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
||||
int mode, uv_fs_cb cb);
|
||||
|
||||
int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file, void* buf,
|
||||
size_t length, off_t offset, uv_fs_cb cb);
|
||||
|
||||
int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
|
||||
|
||||
int uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file file, void* buf,
|
||||
size_t length, off_t offset, uv_fs_cb cb);
|
||||
|
||||
int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
|
||||
UV_EXTERN int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
||||
uv_fs_cb cb);
|
||||
|
||||
int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
|
||||
UV_EXTERN int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req,
|
||||
const char* path, int flags, uv_fs_cb cb);
|
||||
|
||||
int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
|
||||
UV_EXTERN int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
||||
uv_fs_cb cb);
|
||||
|
||||
int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
|
||||
UV_EXTERN int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file,
|
||||
uv_fs_cb cb);
|
||||
|
||||
int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb);
|
||||
|
||||
int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
||||
UV_EXTERN int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
||||
const char* new_path, uv_fs_cb cb);
|
||||
|
||||
int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb);
|
||||
|
||||
int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb);
|
||||
|
||||
int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file file,
|
||||
off_t offset, uv_fs_cb cb);
|
||||
|
||||
int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file out_fd,
|
||||
uv_file in_fd, off_t in_offset, size_t length, uv_fs_cb cb);
|
||||
|
||||
int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
|
||||
UV_EXTERN int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file,
|
||||
uv_fs_cb cb);
|
||||
|
||||
int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime,
|
||||
double mtime, uv_fs_cb cb);
|
||||
UV_EXTERN int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file,
|
||||
uv_fs_cb cb);
|
||||
|
||||
int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime,
|
||||
double mtime, uv_fs_cb cb);
|
||||
UV_EXTERN int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file file,
|
||||
off_t offset, uv_fs_cb cb);
|
||||
|
||||
int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
|
||||
UV_EXTERN int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file out_fd,
|
||||
uv_file in_fd, off_t in_offset, size_t length, uv_fs_cb cb);
|
||||
|
||||
int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
||||
UV_EXTERN int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
||||
int mode, uv_fs_cb cb);
|
||||
|
||||
UV_EXTERN int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
||||
double atime, double mtime, uv_fs_cb cb);
|
||||
|
||||
UV_EXTERN int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file,
|
||||
double atime, double mtime, uv_fs_cb cb);
|
||||
|
||||
UV_EXTERN int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
||||
uv_fs_cb cb);
|
||||
|
||||
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);
|
||||
|
||||
/*
|
||||
|
|
@ -1078,20 +1131,20 @@ int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
|||
*/
|
||||
#define UV_FS_SYMLINK_DIR 0x0001
|
||||
|
||||
int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
||||
UV_EXTERN int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
||||
const char* new_path, int flags, uv_fs_cb cb);
|
||||
|
||||
int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
||||
UV_EXTERN int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
||||
uv_fs_cb cb);
|
||||
|
||||
int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file, int mode,
|
||||
uv_fs_cb cb);
|
||||
UV_EXTERN int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file,
|
||||
int mode, uv_fs_cb cb);
|
||||
|
||||
int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, int uid,
|
||||
int gid, uv_fs_cb cb);
|
||||
UV_EXTERN int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
||||
int uid, int gid, uv_fs_cb cb);
|
||||
|
||||
int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file, int uid,
|
||||
int gid, uv_fs_cb cb);
|
||||
UV_EXTERN int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file,
|
||||
int uid, int gid, uv_fs_cb cb);
|
||||
|
||||
|
||||
enum uv_fs_event {
|
||||
|
|
@ -1112,32 +1165,52 @@ struct uv_fs_event_s {
|
|||
* See: http://en.wikipedia.org/wiki/Load_(computing)
|
||||
* (Returns [0,0,0] for windows and cygwin)
|
||||
*/
|
||||
void uv_loadavg(double avg[3]);
|
||||
UV_EXTERN void uv_loadavg(double avg[3]);
|
||||
|
||||
|
||||
/*
|
||||
* If filename is a directory then we will watch for all events in that
|
||||
* directory. If filename is a file - we will only get events from that
|
||||
* file. Subdirectories are not watched.
|
||||
*/
|
||||
int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle,
|
||||
const char* filename, uv_fs_event_cb cb);
|
||||
* Flags to be passed to uv_fs_event_init.
|
||||
*/
|
||||
enum uv_fs_event_flags {
|
||||
/*
|
||||
* By default, if the fs event watcher is given a directory name, we will
|
||||
* watch for all events in that directory. This flags overrides this behavior
|
||||
* and makes fs_event report only changes to the directory entry itself. This
|
||||
* flag does not affect individual files watched.
|
||||
* This flag is currently not implemented yet on any backend.
|
||||
*/
|
||||
UV_FS_EVENT_WATCH_ENTRY = 1,
|
||||
|
||||
/*
|
||||
* By default uv_fs_event will try to use a kernel interface such as inotify
|
||||
* or kqueue to detect events. This may not work on remote filesystems such
|
||||
* as NFS mounts. This flag makes fs_event fall back to calling stat() on a
|
||||
* regular interval.
|
||||
* This flag is currently not implemented yet on any backend.
|
||||
*/
|
||||
UV_FS_EVENT_STAT = 2
|
||||
};
|
||||
|
||||
|
||||
UV_EXTERN int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle,
|
||||
const char* filename, uv_fs_event_cb cb, int flags);
|
||||
|
||||
/* Utility */
|
||||
|
||||
/* Convert string ip addresses to binary structures */
|
||||
struct sockaddr_in uv_ip4_addr(const char* ip, int port);
|
||||
struct sockaddr_in6 uv_ip6_addr(const char* ip, int port);
|
||||
UV_EXTERN struct sockaddr_in uv_ip4_addr(const char* ip, int port);
|
||||
UV_EXTERN struct sockaddr_in6 uv_ip6_addr(const char* ip, int port);
|
||||
|
||||
/* Convert binary addresses to strings */
|
||||
int uv_ip4_name(struct sockaddr_in* src, char* dst, size_t size);
|
||||
int uv_ip6_name(struct sockaddr_in6* src, char* dst, size_t size);
|
||||
UV_EXTERN int uv_ip4_name(struct sockaddr_in* src, char* dst, size_t size);
|
||||
UV_EXTERN int uv_ip6_name(struct sockaddr_in6* src, char* dst, size_t size);
|
||||
|
||||
/* Gets the executable path */
|
||||
int uv_exepath(char* buffer, size_t* size);
|
||||
UV_EXTERN int uv_exepath(char* buffer, size_t* size);
|
||||
|
||||
/* Gets memory info in bytes */
|
||||
uint64_t uv_get_free_memory(void);
|
||||
uint64_t uv_get_total_memory(void);
|
||||
UV_EXTERN uint64_t uv_get_free_memory(void);
|
||||
UV_EXTERN uint64_t uv_get_total_memory(void);
|
||||
|
||||
/*
|
||||
* Returns the current high-resolution real time. This is expressed in
|
||||
|
|
@ -1148,7 +1221,20 @@ uint64_t uv_get_total_memory(void);
|
|||
* Note not every platform can support nanosecond resolution; however, this
|
||||
* value will always be in nanoseconds.
|
||||
*/
|
||||
extern uint64_t uv_hrtime(void);
|
||||
UV_EXTERN extern uint64_t uv_hrtime(void);
|
||||
|
||||
|
||||
/*
|
||||
* Opens a shared library. The filename is in utf-8. On success, -1 is
|
||||
* and the variable pointed by library receives a handle to the library.
|
||||
*/
|
||||
UV_EXTERN uv_err_t uv_dlopen(const char* filename, uv_lib_t* library);
|
||||
UV_EXTERN uv_err_t uv_dlclose(uv_lib_t library);
|
||||
|
||||
/*
|
||||
* Retrieves a data pointer from a dynamic library.
|
||||
*/
|
||||
UV_EXTERN uv_err_t uv_dlsym(uv_lib_t library, const char* name, void** ptr);
|
||||
|
||||
|
||||
/* the presence of these unions force similar struct layout */
|
||||
|
|
|
|||
|
|
@ -4,9 +4,6 @@
|
|||
/* when building c-ares library */
|
||||
#define CARES_BUILDING_LIBRARY 1
|
||||
|
||||
/* when not building a shared library */
|
||||
#define CARES_STATICLIB 1
|
||||
|
||||
/* Copyright (C) 2004 - 2008 by Daniel Stenberg et al
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
|
|
|
|||
|
|
@ -38,18 +38,22 @@
|
|||
#include <limits.h> /* PATH_MAX */
|
||||
#include <sys/uio.h> /* writev */
|
||||
|
||||
#ifdef __linux__
|
||||
# include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#ifdef __sun
|
||||
# include <sys/types.h>
|
||||
# include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <mach-o/dyld.h> /* _NSGetExecutablePath */
|
||||
#ifdef __APPLE__
|
||||
# include <mach-o/dyld.h> /* _NSGetExecutablePath */
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/wait.h>
|
||||
#ifdef __FreeBSD__
|
||||
# include <sys/sysctl.h>
|
||||
# include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
static uv_loop_t default_loop_struct;
|
||||
|
|
@ -154,7 +158,7 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
|
|||
}
|
||||
|
||||
|
||||
uv_loop_t* uv_loop_new() {
|
||||
uv_loop_t* uv_loop_new(void) {
|
||||
uv_loop_t* loop = calloc(1, sizeof(uv_loop_t));
|
||||
loop->ev = ev_loop_new(0);
|
||||
ev_set_userdata(loop->ev, loop);
|
||||
|
|
@ -169,7 +173,7 @@ void uv_loop_delete(uv_loop_t* loop) {
|
|||
}
|
||||
|
||||
|
||||
uv_loop_t* uv_default_loop() {
|
||||
uv_loop_t* uv_default_loop(void) {
|
||||
if (!default_loop_ptr) {
|
||||
default_loop_ptr = &default_loop_struct;
|
||||
#if HAVE_KQUEUE
|
||||
|
|
@ -593,9 +597,17 @@ static int uv_getaddrinfo_done(eio_req* req) {
|
|||
free(handle->service);
|
||||
free(handle->hostname);
|
||||
|
||||
if (handle->retcode != 0) {
|
||||
/* TODO how to display gai error strings? */
|
||||
uv__set_sys_error(handle->loop, handle->retcode);
|
||||
if (handle->retcode == 0) {
|
||||
/* OK */
|
||||
#if EAI_NODATA /* FreeBSD deprecated EAI_NODATA */
|
||||
} else if (handle->retcode == EAI_NONAME || handle->retcode == EAI_NODATA) {
|
||||
#else
|
||||
} else if (handle->retcode == EAI_NONAME) {
|
||||
#endif
|
||||
uv__set_sys_error(handle->loop, ENOENT); /* FIXME compatibility hack */
|
||||
} else {
|
||||
handle->loop->last_err.code = UV_EADDRINFO;
|
||||
handle->loop->last_err.sys_errno_ = handle->retcode;
|
||||
}
|
||||
|
||||
handle->cb(handle, handle->retcode, res);
|
||||
|
|
@ -734,6 +746,9 @@ int uv__close(int fd) {
|
|||
|
||||
|
||||
int uv__nonblock(int fd, int set) {
|
||||
#if FIONBIO
|
||||
return ioctl(fd, FIONBIO, &set);
|
||||
#else
|
||||
int flags;
|
||||
|
||||
if ((flags = fcntl(fd, F_GETFL)) == -1) {
|
||||
|
|
@ -751,10 +766,17 @@ int uv__nonblock(int fd, int set) {
|
|||
}
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int uv__cloexec(int fd, int set) {
|
||||
#if __linux__
|
||||
/* Linux knows only FD_CLOEXEC so we can safely omit the fcntl(F_GETFD)
|
||||
* syscall. CHECKME: That's probably true for other Unices as well.
|
||||
*/
|
||||
return fcntl(fd, F_SETFD, set ? FD_CLOEXEC : 0);
|
||||
#else
|
||||
int flags;
|
||||
|
||||
if ((flags = fcntl(fd, F_GETFD)) == -1) {
|
||||
|
|
@ -772,6 +794,7 @@ int uv__cloexec(int fd, int set) {
|
|||
}
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -69,7 +69,8 @@ uint64_t uv_get_total_memory(void) {
|
|||
int uv_fs_event_init(uv_loop_t* loop,
|
||||
uv_fs_event_t* handle,
|
||||
const char* filename,
|
||||
uv_fs_event_cb cb) {
|
||||
uv_fs_event_cb cb,
|
||||
int flags) {
|
||||
uv__set_sys_error(loop, ENOSYS);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
57
src/rt/libuv/src/unix/dl.c
Normal file
57
src/rt/libuv/src/unix/dl.c
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/* 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 "internal.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
uv_err_t uv_dlopen(const char* filename, uv_lib_t* library) {
|
||||
void* handle = dlopen(filename, RTLD_LAZY);
|
||||
if (handle == NULL) {
|
||||
return uv__new_sys_error(errno);
|
||||
}
|
||||
|
||||
*library = handle;
|
||||
return uv_ok_;
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_dlclose(uv_lib_t library) {
|
||||
if (dlclose(library) != 0) {
|
||||
return uv__new_sys_error(errno);
|
||||
}
|
||||
|
||||
return uv_ok_;
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_dlsym(uv_lib_t library, const char* name, void** ptr) {
|
||||
void* address = dlsym(library, name);
|
||||
if (address == NULL) {
|
||||
return uv__new_sys_error(errno);
|
||||
}
|
||||
|
||||
*ptr = (void*) address;
|
||||
return uv_ok_;
|
||||
}
|
||||
|
|
@ -59,8 +59,10 @@ void uv_fatal_error(const int errorno, const char* syscall) {
|
|||
static int uv__translate_lib_error(int code) {
|
||||
switch (code) {
|
||||
case UV_ENOSYS: return ENOSYS;
|
||||
case UV_ENOTSOCK: return ENOTSOCK;
|
||||
case UV_ENOENT: return ENOENT;
|
||||
case UV_EACCESS: return EACCES;
|
||||
case UV_EACCES: return EACCES;
|
||||
case UV_EAFNOSUPPORT: return EAFNOSUPPORT;
|
||||
case UV_EBADF: return EBADF;
|
||||
case UV_EPIPE: return EPIPE;
|
||||
case UV_EAGAIN: return EAGAIN;
|
||||
|
|
@ -73,8 +75,10 @@ static int uv__translate_lib_error(int code) {
|
|||
case UV_EADDRINUSE: return EADDRINUSE;
|
||||
case UV_EADDRNOTAVAIL: return EADDRNOTAVAIL;
|
||||
case UV_ENOTDIR: return ENOTDIR;
|
||||
case UV_EISDIR: return EISDIR;
|
||||
case UV_ENOTCONN: return ENOTCONN;
|
||||
case UV_EEXIST: return EEXIST;
|
||||
case UV_EHOSTUNREACH: return EHOSTUNREACH;
|
||||
default: return -1;
|
||||
}
|
||||
|
||||
|
|
@ -87,8 +91,10 @@ uv_err_code uv_translate_sys_error(int sys_errno) {
|
|||
switch (sys_errno) {
|
||||
case 0: return UV_OK;
|
||||
case ENOSYS: return UV_ENOSYS;
|
||||
case ENOTSOCK: return UV_ENOTSOCK;
|
||||
case ENOENT: return UV_ENOENT;
|
||||
case EACCES: return UV_EACCESS;
|
||||
case EACCES: return UV_EACCES;
|
||||
case EAFNOSUPPORT: return UV_EAFNOSUPPORT;
|
||||
case EBADF: return UV_EBADF;
|
||||
case EPIPE: return UV_EPIPE;
|
||||
case EAGAIN: return UV_EAGAIN;
|
||||
|
|
@ -101,8 +107,10 @@ uv_err_code uv_translate_sys_error(int sys_errno) {
|
|||
case EADDRINUSE: return UV_EADDRINUSE;
|
||||
case EADDRNOTAVAIL: return UV_EADDRNOTAVAIL;
|
||||
case ENOTDIR: return UV_ENOTDIR;
|
||||
case EISDIR: return UV_EISDIR;
|
||||
case ENOTCONN: return UV_ENOTCONN;
|
||||
case EEXIST: return UV_EEXIST;
|
||||
case EHOSTUNREACH: return UV_EHOSTUNREACH;
|
||||
case EAI_NONAME: return UV_ENOENT;
|
||||
default: return UV_UNKNOWN;
|
||||
}
|
||||
|
|
@ -116,7 +124,7 @@ uv_err_code uv_translate_sys_error(int sys_errno) {
|
|||
* a) rely on what the system provides us
|
||||
* b) reverse-map the error codes
|
||||
*/
|
||||
char* uv_strerror(uv_err_t err) {
|
||||
const char* uv_strerror(uv_err_t err) {
|
||||
int errorno;
|
||||
|
||||
if (err.sys_errno_)
|
||||
|
|
@ -124,6 +132,9 @@ char* uv_strerror(uv_err_t err) {
|
|||
else
|
||||
errorno = uv__translate_lib_error(err.code);
|
||||
|
||||
if (err.code == UV_EADDRINFO)
|
||||
return gai_strerror(errorno);
|
||||
|
||||
if (errorno == -1)
|
||||
return "Unknown error";
|
||||
else
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ epoll_init (EV_P_ int flags)
|
|||
#ifdef EPOLL_CLOEXEC
|
||||
backend_fd = epoll_create1 (EPOLL_CLOEXEC);
|
||||
|
||||
if (backend_fd <= 0)
|
||||
if (backend_fd < 0)
|
||||
#endif
|
||||
backend_fd = epoll_create (256);
|
||||
|
||||
|
|
|
|||
|
|
@ -86,9 +86,13 @@ void uv__kqueue_hack(EV_P_ int fflags, ev_io *w) {
|
|||
int uv_fs_event_init(uv_loop_t* loop,
|
||||
uv_fs_event_t* handle,
|
||||
const char* filename,
|
||||
uv_fs_event_cb cb) {
|
||||
uv_fs_event_cb cb,
|
||||
int flags) {
|
||||
int fd;
|
||||
|
||||
/* We don't support any flags yet. */
|
||||
assert(!flags);
|
||||
|
||||
if (cb == NULL) {
|
||||
uv__set_sys_error(loop, EINVAL);
|
||||
return -1;
|
||||
|
|
@ -122,7 +126,8 @@ void uv__fs_event_destroy(uv_fs_event_t* handle) {
|
|||
int uv_fs_event_init(uv_loop_t* loop,
|
||||
uv_fs_event_t* handle,
|
||||
const char* filename,
|
||||
uv_fs_event_cb cb) {
|
||||
uv_fs_event_cb cb,
|
||||
int flags) {
|
||||
uv__set_sys_error(loop, ENOSYS);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,10 +156,14 @@ static void uv__inotify_read(EV_P_ ev_io* w, int revents) {
|
|||
int uv_fs_event_init(uv_loop_t* loop,
|
||||
uv_fs_event_t* handle,
|
||||
const char* filename,
|
||||
uv_fs_event_cb cb) {
|
||||
int flags;
|
||||
uv_fs_event_cb cb,
|
||||
int flags) {
|
||||
int events;
|
||||
int fd;
|
||||
|
||||
/* We don't support any flags yet. */
|
||||
assert(!flags);
|
||||
|
||||
/*
|
||||
* TODO share a single inotify fd across the event loop?
|
||||
* We'll run into fs.inotify.max_user_instances if we
|
||||
|
|
@ -170,15 +174,15 @@ int uv_fs_event_init(uv_loop_t* loop,
|
|||
return -1;
|
||||
}
|
||||
|
||||
flags = IN_ATTRIB
|
||||
| IN_CREATE
|
||||
| IN_MODIFY
|
||||
| IN_DELETE
|
||||
| IN_DELETE_SELF
|
||||
| IN_MOVED_FROM
|
||||
| IN_MOVED_TO;
|
||||
events = IN_ATTRIB
|
||||
| IN_CREATE
|
||||
| IN_MODIFY
|
||||
| IN_DELETE
|
||||
| IN_DELETE_SELF
|
||||
| IN_MOVED_FROM
|
||||
| IN_MOVED_TO;
|
||||
|
||||
if (inotify_add_watch(fd, filename, flags) == -1) {
|
||||
if (inotify_add_watch(fd, filename, events) == -1) {
|
||||
uv__set_sys_error(loop, errno);
|
||||
uv__close(fd);
|
||||
return -1;
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ void uv_pipe_open(uv_pipe_t* handle, uv_file fd) {
|
|||
}
|
||||
|
||||
|
||||
int uv_pipe_connect(uv_connect_t* req,
|
||||
void uv_pipe_connect(uv_connect_t* req,
|
||||
uv_pipe_t* handle,
|
||||
const char* name,
|
||||
uv_connect_cb cb) {
|
||||
|
|
@ -209,7 +209,7 @@ int uv_pipe_connect(uv_connect_t* req,
|
|||
while (r == -1 && errno == EINTR);
|
||||
|
||||
if (r == -1) {
|
||||
uv__set_sys_error(handle->loop, errno);
|
||||
status = errno;
|
||||
uv__close(sockfd);
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -237,7 +237,6 @@ out:
|
|||
* return 0 and let the callback handle errors.
|
||||
*/
|
||||
errno = saved_errno;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -300,3 +300,14 @@ int uv_process_kill(uv_process_t* process, int signum) {
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_kill(int pid, int signum) {
|
||||
int r = kill(pid, signum);
|
||||
|
||||
if (r) {
|
||||
return uv__new_sys_error(errno);
|
||||
} else {
|
||||
return uv_ok_;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ void uv__stream_init(uv_loop_t* loop,
|
|||
stream->accepted_fd = -1;
|
||||
stream->fd = -1;
|
||||
stream->delayed_error = 0;
|
||||
stream->blocking = 0;
|
||||
ngx_queue_init(&stream->write_queue);
|
||||
ngx_queue_init(&stream->write_completed_queue);
|
||||
stream->write_queue_size = 0;
|
||||
|
|
@ -340,9 +341,9 @@ static void uv__write(uv_stream_t* stream) {
|
|||
int iovcnt;
|
||||
ssize_t n;
|
||||
|
||||
assert(stream->fd >= 0);
|
||||
start:
|
||||
|
||||
/* TODO: should probably while(1) here until EAGAIN */
|
||||
assert(stream->fd >= 0);
|
||||
|
||||
/* Get the request at the head of the queue. */
|
||||
req = uv_write_queue_head(stream);
|
||||
|
|
@ -353,14 +354,16 @@ static void uv__write(uv_stream_t* stream) {
|
|||
|
||||
assert(req->handle == stream);
|
||||
|
||||
/* Cast to iovec. We had to have our own uv_buf_t instead of iovec
|
||||
/*
|
||||
* Cast to iovec. We had to have our own uv_buf_t instead of iovec
|
||||
* because Windows's WSABUF is not an iovec.
|
||||
*/
|
||||
assert(sizeof(uv_buf_t) == sizeof(struct iovec));
|
||||
iov = (struct iovec*) &(req->bufs[req->write_index]);
|
||||
iovcnt = req->bufcnt - req->write_index;
|
||||
|
||||
/* Now do the actual writev. Note that we've been updating the pointers
|
||||
/*
|
||||
* Now do the actual writev. Note that we've been updating the pointers
|
||||
* inside the iov each time we write. So there is no need to offset it.
|
||||
*/
|
||||
|
||||
|
|
@ -409,6 +412,9 @@ static void uv__write(uv_stream_t* stream) {
|
|||
stream->write_queue_size -= uv__write_req_size(req);
|
||||
uv__write_req_finish(req);
|
||||
return;
|
||||
} else if (stream->blocking) {
|
||||
/* If this is a blocking stream, try again. */
|
||||
goto start;
|
||||
}
|
||||
} else {
|
||||
/* Successful write */
|
||||
|
|
@ -426,8 +432,17 @@ static void uv__write(uv_stream_t* stream) {
|
|||
stream->write_queue_size -= n;
|
||||
n = 0;
|
||||
|
||||
/* There is more to write. Break and ensure the watcher is pending. */
|
||||
break;
|
||||
/* There is more to write. */
|
||||
if (stream->blocking) {
|
||||
/*
|
||||
* If we're blocking then we should not be enabling the write
|
||||
* watcher - instead we need to try again.
|
||||
*/
|
||||
goto start;
|
||||
} else {
|
||||
/* Break loop and ensure the watcher is pending. */
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Finished writing the buf at index req->write_index. */
|
||||
|
|
@ -453,6 +468,9 @@ static void uv__write(uv_stream_t* stream) {
|
|||
/* Either we've counted n down to zero or we've got EAGAIN. */
|
||||
assert(n == 0 || n == -1);
|
||||
|
||||
/* Only non-blocking streams should use the write_watcher. */
|
||||
assert(!stream->blocking);
|
||||
|
||||
/* We're not done. */
|
||||
ev_io_start(stream->loop->ev, &stream->write_watcher);
|
||||
}
|
||||
|
|
@ -862,6 +880,13 @@ int uv_write2(uv_write_t* req, uv_stream_t* stream, uv_buf_t bufs[], int bufcnt,
|
|||
if (empty_queue) {
|
||||
uv__write(stream);
|
||||
} else {
|
||||
/*
|
||||
* blocking streams should never have anything in the queue.
|
||||
* if this assert fires then somehow the blocking stream isn't being
|
||||
* sufficently flushed in uv__write.
|
||||
*/
|
||||
assert(!stream->blocking);
|
||||
|
||||
ev_io_start(stream->loop->ev, &stream->write_watcher);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,13 +23,17 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/loadavg.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/port.h>
|
||||
#include <unistd.h>
|
||||
#include <kstat.h>
|
||||
#include <port.h>
|
||||
|
||||
|
||||
uint64_t uv_hrtime() {
|
||||
|
|
@ -81,15 +85,91 @@ void uv_loadavg(double avg[3]) {
|
|||
}
|
||||
|
||||
|
||||
static void uv__fs_event_rearm(uv_fs_event_t *handle) {
|
||||
if (port_associate(handle->fd,
|
||||
PORT_SOURCE_FILE,
|
||||
(uintptr_t) &handle->fo,
|
||||
FILE_ATTRIB | FILE_MODIFIED,
|
||||
NULL) == -1) {
|
||||
uv__set_sys_error(handle->loop, errno);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void uv__fs_event_read(EV_P_ ev_io* w, int revents) {
|
||||
uv_fs_event_t *handle;
|
||||
timespec_t timeout;
|
||||
port_event_t pe;
|
||||
int events;
|
||||
int r;
|
||||
|
||||
handle = container_of(w, uv_fs_event_t, event_watcher);
|
||||
|
||||
do {
|
||||
/* TODO use port_getn() */
|
||||
do {
|
||||
memset(&timeout, 0, sizeof timeout);
|
||||
r = port_get(handle->fd, &pe, &timeout);
|
||||
}
|
||||
while (r == -1 && errno == EINTR);
|
||||
|
||||
if (r == -1 && errno == ETIME)
|
||||
break;
|
||||
|
||||
assert((r == 0) && "unexpected port_get() error");
|
||||
|
||||
events = 0;
|
||||
if (pe.portev_events & (FILE_ATTRIB | FILE_MODIFIED))
|
||||
events |= UV_CHANGE;
|
||||
if (pe.portev_events & ~(FILE_ATTRIB | FILE_MODIFIED))
|
||||
events |= UV_RENAME;
|
||||
assert(events != 0);
|
||||
|
||||
handle->cb(handle, NULL, events, 0);
|
||||
}
|
||||
while (handle->fd != -1);
|
||||
|
||||
if (handle->fd != -1)
|
||||
uv__fs_event_rearm(handle);
|
||||
}
|
||||
|
||||
|
||||
int uv_fs_event_init(uv_loop_t* loop,
|
||||
uv_fs_event_t* handle,
|
||||
const char* filename,
|
||||
uv_fs_event_cb cb) {
|
||||
uv__set_sys_error(loop, ENOSYS);
|
||||
return -1;
|
||||
uv_fs_event_cb cb,
|
||||
int flags) {
|
||||
int portfd;
|
||||
|
||||
/* We don't support any flags yet. */
|
||||
assert(!flags);
|
||||
|
||||
if ((portfd = port_create()) == -1) {
|
||||
uv__set_sys_error(loop, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT);
|
||||
handle->filename = strdup(filename);
|
||||
handle->fd = portfd;
|
||||
handle->cb = cb;
|
||||
|
||||
memset(&handle->fo, 0, sizeof handle->fo);
|
||||
handle->fo.fo_name = handle->filename;
|
||||
uv__fs_event_rearm(handle);
|
||||
|
||||
ev_io_init(&handle->event_watcher, uv__fs_event_read, portfd, EV_READ);
|
||||
ev_io_start(loop->ev, &handle->event_watcher);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uv__fs_event_destroy(uv_fs_event_t* handle) {
|
||||
assert(0 && "implement me");
|
||||
ev_io_stop(handle->loop->ev, &handle->event_watcher);
|
||||
uv__close(handle->fd);
|
||||
handle->fd = -1;
|
||||
free(handle->filename);
|
||||
handle->filename = NULL;
|
||||
handle->fo.fo_name = NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -319,3 +319,8 @@ int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) {
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) {
|
|||
uv__stream_open((uv_stream_t*)tty, fd, UV_READABLE);
|
||||
} else {
|
||||
/* Note: writable tty we set to blocking mode. */
|
||||
uv__nonblock(fd, 0);
|
||||
uv__stream_open((uv_stream_t*)tty, fd, UV_WRITABLE);
|
||||
tty->blocking = 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,12 +48,16 @@ uv_buf_t uv_buf_init(char* base, size_t len) {
|
|||
}
|
||||
|
||||
|
||||
const uv_err_t uv_ok_ = { UV_OK, 0 };
|
||||
|
||||
|
||||
const char* uv_err_name(uv_err_t err) {
|
||||
switch (err.code) {
|
||||
case UV_UNKNOWN: return "UNKNOWN";
|
||||
case UV_OK: return "OK";
|
||||
case UV_EOF: return "EOF";
|
||||
case UV_EACCESS: return "EACCESS";
|
||||
case UV_EADDRINFO: return "EADDRINFO";
|
||||
case UV_EACCES: return "EACCES";
|
||||
case UV_EAGAIN: return "EAGAIN";
|
||||
case UV_EADDRINUSE: return "EADDRINUSE";
|
||||
case UV_EADDRNOTAVAIL: return "EADDRNOTAVAIL";
|
||||
|
|
@ -71,6 +75,7 @@ const char* uv_err_name(uv_err_t err) {
|
|||
case UV_EINVAL: return "EINVAL";
|
||||
case UV_EISCONN: return "EISCONN";
|
||||
case UV_EMFILE: return "EMFILE";
|
||||
case UV_EMSGSIZE: return "EMSGSIZE";
|
||||
case UV_ENETDOWN: return "ENETDOWN";
|
||||
case UV_ENETUNREACH: return "ENETUNREACH";
|
||||
case UV_ENFILE: return "ENFILE";
|
||||
|
|
@ -89,6 +94,12 @@ const char* uv_err_name(uv_err_t err) {
|
|||
case UV_EPROTONOSUPPORT: return "EPROTONOSUPPORT";
|
||||
case UV_EPROTOTYPE: return "EPROTOTYPE";
|
||||
case UV_ETIMEDOUT: return "ETIMEDOUT";
|
||||
case UV_ECHARSET: return "ECHARSET";
|
||||
case UV_EAIFAMNOSUPPORT: return "EAIFAMNOSUPPORT";
|
||||
case UV_EAINONAME: return "EAINONAME";
|
||||
case UV_EAISERVICE: return "EAISERVICE";
|
||||
case UV_EAISOCKTYPE: return "EAISOCKTYPE";
|
||||
case UV_ESHUTDOWN: return "ESHUTDOWN";
|
||||
case UV_EEXIST: return "EEXIST";
|
||||
default:
|
||||
assert(0);
|
||||
|
|
@ -115,6 +126,14 @@ void uv__set_artificial_error(uv_loop_t* loop, uv_err_code code) {
|
|||
}
|
||||
|
||||
|
||||
uv_err_t uv__new_sys_error(int sys_error) {
|
||||
uv_err_t error;
|
||||
error.code = uv_translate_sys_error(sys_error);
|
||||
error.sys_errno_ = sys_error;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_last_error(uv_loop_t* loop) {
|
||||
return loop->last_err;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,10 +48,13 @@ void uv_add_ares_handle(uv_loop_t* loop, uv_ares_task_t* handle);
|
|||
|
||||
int uv_ares_handles_empty(uv_loop_t* loop);
|
||||
|
||||
extern const uv_err_t uv_ok_;
|
||||
|
||||
uv_err_code uv_translate_sys_error(int sys_errno);
|
||||
void uv__set_error(uv_loop_t* loop, uv_err_code code, int sys_error);
|
||||
void uv__set_sys_error(uv_loop_t* loop, int sys_error);
|
||||
void uv__set_artificial_error(uv_loop_t* loop, uv_err_code code);
|
||||
uv_err_t uv__new_sys_error(int sys_error);
|
||||
|
||||
int uv__tcp_bind(uv_tcp_t* handle, struct sockaddr_in addr);
|
||||
int uv__tcp_bind6(uv_tcp_t* handle, struct sockaddr_in6 addr);
|
||||
|
|
|
|||
|
|
@ -40,6 +40,10 @@ static uv_once_t uv_default_loop_init_guard_ = UV_ONCE_INIT;
|
|||
|
||||
|
||||
static void uv_init(void) {
|
||||
/* Tell Windows that we will handle critical errors. */
|
||||
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
|
||||
SEM_NOOPENFILEERRORBOX);
|
||||
|
||||
/* Initialize winsock */
|
||||
uv_winsock_init();
|
||||
|
||||
|
|
@ -95,12 +99,23 @@ static void uv_default_loop_init(void) {
|
|||
}
|
||||
|
||||
|
||||
uv_loop_t* uv_default_loop() {
|
||||
uv_loop_t* uv_default_loop(void) {
|
||||
uv_once(&uv_default_loop_init_guard_, uv_default_loop_init);
|
||||
return &uv_default_loop_;
|
||||
}
|
||||
|
||||
|
||||
uv_loop_t* uv_loop_new(void) {
|
||||
assert(0 && "implement me");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void uv_loop_delete(uv_loop_t* loop) {
|
||||
assert(0 && "implement me");
|
||||
}
|
||||
|
||||
|
||||
void uv_ref(uv_loop_t* loop) {
|
||||
loop->refs++;
|
||||
}
|
||||
|
|
@ -147,7 +162,7 @@ static void uv_poll_ex(uv_loop_t* loop, int block) {
|
|||
BOOL success;
|
||||
DWORD timeout;
|
||||
uv_req_t* req;
|
||||
OVERLAPPED_ENTRY overlappeds[64];
|
||||
OVERLAPPED_ENTRY overlappeds[128];
|
||||
ULONG count;
|
||||
ULONG i;
|
||||
|
||||
|
|
|
|||
63
src/rt/libuv/src/win/dl.c
Normal file
63
src/rt/libuv/src/win/dl.c
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/* 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 "internal.h"
|
||||
|
||||
|
||||
uv_err_t uv_dlopen(const char* filename, uv_lib_t* library) {
|
||||
wchar_t filename_w[32768];
|
||||
HMODULE handle;
|
||||
|
||||
if (!uv_utf8_to_utf16(filename,
|
||||
filename_w,
|
||||
sizeof(filename_w) / sizeof(wchar_t))) {
|
||||
return uv__new_sys_error(GetLastError());
|
||||
}
|
||||
|
||||
handle = LoadLibraryW(filename_w);
|
||||
if (handle == NULL) {
|
||||
return uv__new_sys_error(GetLastError());
|
||||
}
|
||||
|
||||
*library = handle;
|
||||
return uv_ok_;
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_dlclose(uv_lib_t library) {
|
||||
if (!FreeLibrary(library)) {
|
||||
return uv__new_sys_error(GetLastError());
|
||||
}
|
||||
|
||||
return uv_ok_;
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_dlsym(uv_lib_t library, const char* name, void** ptr) {
|
||||
FARPROC proc = GetProcAddress(library, name);
|
||||
if (proc == NULL) {
|
||||
return uv__new_sys_error(GetLastError());
|
||||
}
|
||||
|
||||
*ptr = (void*) proc;
|
||||
return uv_ok_;
|
||||
}
|
||||
|
|
@ -30,9 +30,6 @@
|
|||
#include "internal.h"
|
||||
|
||||
|
||||
const uv_err_t uv_ok_ = { UV_OK, ERROR_SUCCESS };
|
||||
|
||||
|
||||
/*
|
||||
* Display an error message and abort the event loop.
|
||||
*/
|
||||
|
|
@ -70,7 +67,7 @@ void uv_fatal_error(const int errorno, const char* syscall) {
|
|||
/* TODO: thread safety */
|
||||
static char* last_err_str_ = NULL;
|
||||
|
||||
char* uv_strerror(uv_err_t err) {
|
||||
const char* uv_strerror(uv_err_t err) {
|
||||
if (last_err_str_ != NULL) {
|
||||
LocalFree(last_err_str_);
|
||||
}
|
||||
|
|
@ -93,8 +90,8 @@ uv_err_code uv_translate_sys_error(int sys_errno) {
|
|||
case ERROR_SUCCESS: return UV_OK;
|
||||
case ERROR_FILE_NOT_FOUND: return UV_ENOENT;
|
||||
case ERROR_PATH_NOT_FOUND: return UV_ENOENT;
|
||||
case ERROR_NOACCESS: return UV_EACCESS;
|
||||
case WSAEACCES: return UV_EACCESS;
|
||||
case ERROR_NOACCESS: return UV_EACCES;
|
||||
case WSAEACCES: return UV_EACCES;
|
||||
case ERROR_ADDRESS_ALREADY_ASSOCIATED: return UV_EADDRINUSE;
|
||||
case WSAEADDRINUSE: return UV_EADDRINUSE;
|
||||
case WSAEADDRNOTAVAIL: return UV_EADDRNOTAVAIL;
|
||||
|
|
|
|||
|
|
@ -133,12 +133,15 @@ static int uv_split_path(const wchar_t* filename, wchar_t** dir,
|
|||
|
||||
|
||||
int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle,
|
||||
const char* filename, uv_fs_event_cb cb) {
|
||||
const char* filename, uv_fs_event_cb cb, int flags) {
|
||||
int name_size;
|
||||
DWORD attr, last_error;
|
||||
wchar_t* dir = NULL, *dir_to_watch, *filenamew;
|
||||
wchar_t short_path[MAX_PATH];
|
||||
|
||||
/* We don't support any flags yet. */
|
||||
assert(!flags);
|
||||
|
||||
uv_fs_event_init_handle(loop, handle, filename, cb);
|
||||
|
||||
/* Convert name to UTF16. */
|
||||
|
|
@ -353,7 +356,9 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
|
|||
offset = file_info->NextEntryOffset;
|
||||
} while(offset);
|
||||
} else {
|
||||
handle->cb(handle, NULL, UV_CHANGE, 0);
|
||||
if (!(handle->flags & UV_HANDLE_CLOSING)) {
|
||||
handle->cb(handle, NULL, UV_CHANGE, 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uv__set_sys_error(loop, GET_REQ_ERROR(req));
|
||||
|
|
|
|||
|
|
@ -173,19 +173,24 @@ void fs__open(uv_fs_t* req, const wchar_t* path, int flags, int mode) {
|
|||
/* convert flags and mode to CreateFile parameters */
|
||||
switch (flags & (_O_RDONLY | _O_WRONLY | _O_RDWR)) {
|
||||
case _O_RDONLY:
|
||||
access = GENERIC_READ;
|
||||
access = FILE_GENERIC_READ;
|
||||
break;
|
||||
case _O_WRONLY:
|
||||
access = GENERIC_WRITE;
|
||||
access = FILE_GENERIC_WRITE;
|
||||
break;
|
||||
case _O_RDWR:
|
||||
access = GENERIC_READ | GENERIC_WRITE;
|
||||
access = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
|
||||
break;
|
||||
default:
|
||||
result = -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (flags & _O_APPEND) {
|
||||
access &= ~FILE_WRITE_DATA;
|
||||
access |= FILE_APPEND_DATA;
|
||||
}
|
||||
|
||||
/*
|
||||
* Here is where we deviate significantly from what CRT's _open()
|
||||
* does. We indiscriminately use all the sharing modes, to match
|
||||
|
|
|
|||
|
|
@ -44,30 +44,35 @@ void uv_process_timers(uv_loop_t* loop);
|
|||
*/
|
||||
|
||||
/* Private uv_handle flags */
|
||||
#define UV_HANDLE_CLOSING 0x000001
|
||||
#define UV_HANDLE_CLOSED 0x000002
|
||||
#define UV_HANDLE_BOUND 0x000004
|
||||
#define UV_HANDLE_LISTENING 0x000008
|
||||
#define UV_HANDLE_CONNECTION 0x000010
|
||||
#define UV_HANDLE_CONNECTED 0x000020
|
||||
#define UV_HANDLE_READING 0x000040
|
||||
#define UV_HANDLE_ACTIVE 0x000040
|
||||
#define UV_HANDLE_EOF 0x000080
|
||||
#define UV_HANDLE_SHUTTING 0x000100
|
||||
#define UV_HANDLE_SHUT 0x000200
|
||||
#define UV_HANDLE_ENDGAME_QUEUED 0x000400
|
||||
#define UV_HANDLE_BIND_ERROR 0x001000
|
||||
#define UV_HANDLE_IPV6 0x002000
|
||||
#define UV_HANDLE_PIPESERVER 0x004000
|
||||
#define UV_HANDLE_READ_PENDING 0x008000
|
||||
#define UV_HANDLE_UV_ALLOCED 0x010000
|
||||
#define UV_HANDLE_SYNC_BYPASS_IOCP 0x020000
|
||||
#define UV_HANDLE_ZERO_READ 0x040000
|
||||
#define UV_HANDLE_TTY_RAW 0x080000
|
||||
#define UV_HANDLE_EMULATE_IOCP 0x100000
|
||||
#define UV_HANDLE_NON_OVERLAPPED_PIPE 0x200000
|
||||
#define UV_HANDLE_TTY_SAVED_POSITION 0x400000
|
||||
#define UV_HANDLE_TTY_SAVED_ATTRIBUTES 0x800000
|
||||
#define UV_HANDLE_CLOSING 0x00000001
|
||||
#define UV_HANDLE_CLOSED 0x00000002
|
||||
#define UV_HANDLE_BOUND 0x00000004
|
||||
#define UV_HANDLE_LISTENING 0x00000008
|
||||
#define UV_HANDLE_CONNECTION 0x00000010
|
||||
#define UV_HANDLE_CONNECTED 0x00000020
|
||||
#define UV_HANDLE_READING 0x00000040
|
||||
#define UV_HANDLE_ACTIVE 0x00000040
|
||||
#define UV_HANDLE_EOF 0x00000080
|
||||
#define UV_HANDLE_SHUTTING 0x00000100
|
||||
#define UV_HANDLE_SHUT 0x00000200
|
||||
#define UV_HANDLE_ENDGAME_QUEUED 0x00000400
|
||||
#define UV_HANDLE_BIND_ERROR 0x00001000
|
||||
#define UV_HANDLE_IPV6 0x00002000
|
||||
#define UV_HANDLE_PIPESERVER 0x00004000
|
||||
#define UV_HANDLE_READ_PENDING 0x00008000
|
||||
#define UV_HANDLE_UV_ALLOCED 0x00010000
|
||||
#define UV_HANDLE_SYNC_BYPASS_IOCP 0x00020000
|
||||
#define UV_HANDLE_ZERO_READ 0x00040000
|
||||
#define UV_HANDLE_TTY_RAW 0x00080000
|
||||
#define UV_HANDLE_EMULATE_IOCP 0x00100000
|
||||
#define UV_HANDLE_NON_OVERLAPPED_PIPE 0x00200000
|
||||
#define UV_HANDLE_TTY_SAVED_POSITION 0x00400000
|
||||
#define UV_HANDLE_TTY_SAVED_ATTRIBUTES 0x00800000
|
||||
#define UV_HANDLE_SHARED_TCP_SERVER 0x01000000
|
||||
#define UV_HANDLE_TCP_NODELAY 0x02000000
|
||||
#define UV_HANDLE_TCP_KEEPALIVE 0x04000000
|
||||
#define UV_HANDLE_TCP_SINGLE_ACCEPT 0x08000000
|
||||
#define UV_HANDLE_TCP_ACCEPT_STATE_CHANGING 0x10000000
|
||||
|
||||
void uv_want_endgame(uv_loop_t* loop, uv_handle_t* handle);
|
||||
void uv_process_endgames(uv_loop_t* loop);
|
||||
|
|
@ -140,6 +145,9 @@ 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_duplicate_socket(uv_tcp_t* handle, int pid,
|
||||
LPWSAPROTOCOL_INFOW protocol_info);
|
||||
|
||||
|
||||
/*
|
||||
* UDP
|
||||
|
|
@ -278,11 +286,6 @@ void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle);
|
|||
int uv_parent_pid();
|
||||
|
||||
|
||||
/*
|
||||
* Error handling
|
||||
*/
|
||||
extern const uv_err_t uv_ok_;
|
||||
|
||||
void uv_fatal_error(const int errorno, const char* syscall);
|
||||
|
||||
uv_err_code uv_translate_sys_error(int sys_errno);
|
||||
|
|
|
|||
|
|
@ -362,7 +362,7 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
|
|||
if (errno == ERROR_ACCESS_DENIED) {
|
||||
uv__set_error(loop, UV_EADDRINUSE, errno);
|
||||
} else if (errno == ERROR_PATH_NOT_FOUND || errno == ERROR_INVALID_NAME) {
|
||||
uv__set_error(loop, UV_EACCESS, errno);
|
||||
uv__set_error(loop, UV_EACCES, errno);
|
||||
} else {
|
||||
uv__set_sys_error(loop, errno);
|
||||
}
|
||||
|
|
@ -443,7 +443,7 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) {
|
|||
}
|
||||
|
||||
|
||||
int uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
|
||||
void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
|
||||
const char* name, uv_connect_cb cb) {
|
||||
uv_loop_t* loop = handle->loop;
|
||||
int errno, nameSize;
|
||||
|
|
@ -488,7 +488,7 @@ int uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
|
|||
|
||||
handle->reqs_pending++;
|
||||
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
errno = GetLastError();
|
||||
|
|
@ -505,7 +505,7 @@ int uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
|
|||
SET_REQ_SUCCESS(req);
|
||||
uv_insert_pending_req(loop, (uv_req_t*) req);
|
||||
handle->reqs_pending++;
|
||||
return 0;
|
||||
return;
|
||||
|
||||
error:
|
||||
if (handle->name) {
|
||||
|
|
@ -516,8 +516,12 @@ error:
|
|||
if (pipeHandle != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(pipeHandle);
|
||||
}
|
||||
uv__set_sys_error(loop, errno);
|
||||
return -1;
|
||||
|
||||
/* Make this req pending reporting an error. */
|
||||
SET_REQ_ERROR(req, errno);
|
||||
uv_insert_pending_req(loop, (uv_req_t*) req);
|
||||
handle->reqs_pending++;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -956,7 +960,9 @@ static int uv_pipe_write_impl(uv_loop_t* loop, uv_write_t* req,
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (send_handle && send_handle->type != UV_TCP) {
|
||||
/* Only TCP server handles are supported for sharing. */
|
||||
if (send_handle && (send_handle->type != UV_TCP ||
|
||||
send_handle->flags & UV_HANDLE_CONNECTION)) {
|
||||
uv__set_artificial_error(loop, UV_ENOTSUP);
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -989,9 +995,9 @@ static int uv_pipe_write_impl(uv_loop_t* loop, uv_write_t* req,
|
|||
/* Use the IPC framing protocol. */
|
||||
if (send_handle) {
|
||||
tcp_send_handle = (uv_tcp_t*)send_handle;
|
||||
if (WSADuplicateSocketW(tcp_send_handle->socket, handle->ipc_pid,
|
||||
|
||||
if (uv_tcp_duplicate_socket(tcp_send_handle, handle->ipc_pid,
|
||||
&ipc_frame.socket_info)) {
|
||||
uv__set_sys_error(loop, WSAGetLastError());
|
||||
return -1;
|
||||
}
|
||||
ipc_frame.header.flags |= UV_IPC_UV_STREAM;
|
||||
|
|
|
|||
|
|
@ -26,8 +26,11 @@
|
|||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <windows.h>
|
||||
|
||||
#define SIGKILL 9
|
||||
|
||||
typedef struct env_var {
|
||||
const char* narrow;
|
||||
const wchar_t* wide;
|
||||
|
|
@ -265,6 +268,8 @@ static wchar_t* search_path(const wchar_t *file,
|
|||
wchar_t* result = NULL;
|
||||
wchar_t *file_name_start;
|
||||
wchar_t *dot;
|
||||
const wchar_t *dir_start, *dir_end, *dir_path;
|
||||
int dir_len;
|
||||
int name_has_ext;
|
||||
|
||||
int file_len = wcslen(file);
|
||||
|
|
@ -302,8 +307,7 @@ static wchar_t* search_path(const wchar_t *file,
|
|||
name_has_ext);
|
||||
|
||||
} else {
|
||||
const wchar_t *dir_start,
|
||||
*dir_end = path;
|
||||
dir_end = path;
|
||||
|
||||
/* The file is really only a name; look in cwd first, then scan path */
|
||||
result = path_search_walk_ext(L"", 0,
|
||||
|
|
@ -335,7 +339,20 @@ static wchar_t* search_path(const wchar_t *file,
|
|||
continue;
|
||||
}
|
||||
|
||||
result = path_search_walk_ext(dir_start, dir_end - dir_start,
|
||||
dir_path = dir_start;
|
||||
dir_len = dir_end - dir_start;
|
||||
|
||||
/* Adjust if the path is quoted. */
|
||||
if (dir_path[0] == '"' || dir_path[0] == '\'') {
|
||||
++dir_path;
|
||||
--dir_len;
|
||||
}
|
||||
|
||||
if (dir_path[dir_len - 1] == '"' || dir_path[dir_len - 1] == '\'') {
|
||||
--dir_len;
|
||||
}
|
||||
|
||||
result = path_search_walk_ext(dir_path, dir_len,
|
||||
file, file_len,
|
||||
cwd, cwd_len,
|
||||
name_has_ext);
|
||||
|
|
@ -1052,35 +1069,65 @@ done:
|
|||
}
|
||||
|
||||
|
||||
int uv_process_kill(uv_process_t* process, int signum) {
|
||||
static uv_err_t uv__kill(HANDLE process_handle, int signum) {
|
||||
DWORD status;
|
||||
uv_err_t err;
|
||||
|
||||
if (signum == SIGTERM || signum == SIGKILL || signum == SIGINT) {
|
||||
/* Kill the process. On Windows, killed processes normally return 1. */
|
||||
if (TerminateProcess(process_handle, 1)) {
|
||||
err = uv_ok_;
|
||||
} else {
|
||||
err = uv__new_sys_error(GetLastError());
|
||||
}
|
||||
} else if (signum == 0) {
|
||||
/* Health check: is the process still alive? */
|
||||
if (GetExitCodeProcess(process_handle, &status) &&
|
||||
status == STILL_ACTIVE) {
|
||||
err = uv_ok_;
|
||||
} else {
|
||||
err = uv__new_sys_error(GetLastError());
|
||||
}
|
||||
} else {
|
||||
err.code = UV_ENOSYS;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int uv_process_kill(uv_process_t* process, int signum) {
|
||||
uv_err_t err;
|
||||
|
||||
if (process->process_handle == INVALID_HANDLE_VALUE) {
|
||||
uv__set_artificial_error(process->loop, UV_EINVAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (signum) {
|
||||
/* Kill the process. On Windows, killed processes normally return 1. */
|
||||
if (TerminateProcess(process->process_handle, 1)) {
|
||||
process->exit_signal = signum;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
uv__set_sys_error(process->loop, GetLastError());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Health check: is the process still alive? */
|
||||
if (GetExitCodeProcess(process->process_handle, &status) && status == STILL_ACTIVE) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
uv__set_artificial_error(process->loop, UV_EINVAL);
|
||||
return -1;
|
||||
}
|
||||
err = uv__kill(process->process_handle, signum);
|
||||
|
||||
if (err.code != UV_OK) {
|
||||
uv__set_error(process->loop, err.code, err.sys_errno_);
|
||||
return -1;
|
||||
}
|
||||
|
||||
assert(0 && "unreachable");
|
||||
process->exit_signal = signum;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_kill(int pid, int signum) {
|
||||
uv_err_t err;
|
||||
HANDLE process_handle = OpenProcess(PROCESS_TERMINATE |
|
||||
PROCESS_QUERY_INFORMATION, FALSE, pid);
|
||||
|
||||
if (process_handle == INVALID_HANDLE_VALUE) {
|
||||
return uv__new_sys_error(GetLastError());
|
||||
}
|
||||
|
||||
err = uv__kill(process_handle, signum);
|
||||
CloseHandle(process_handle);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,42 @@ static char uv_zero_[] = "";
|
|||
static unsigned int active_tcp_streams = 0;
|
||||
|
||||
|
||||
static int uv__tcp_nodelay(uv_tcp_t* handle, SOCKET socket, int enable) {
|
||||
if (setsockopt(socket,
|
||||
IPPROTO_TCP,
|
||||
TCP_NODELAY,
|
||||
(const char*)&enable,
|
||||
sizeof enable) == -1) {
|
||||
uv__set_sys_error(handle->loop, errno);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int uv__tcp_keepalive(uv_tcp_t* handle, SOCKET socket, int enable, unsigned int delay) {
|
||||
if (setsockopt(socket,
|
||||
SOL_SOCKET,
|
||||
SO_KEEPALIVE,
|
||||
(const char*)&enable,
|
||||
sizeof enable) == -1) {
|
||||
uv__set_sys_error(handle->loop, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (enable && setsockopt(socket,
|
||||
IPPROTO_TCP,
|
||||
TCP_KEEPALIVE,
|
||||
(const char*)&delay,
|
||||
sizeof delay) == -1) {
|
||||
uv__set_sys_error(handle->loop, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle,
|
||||
SOCKET socket, int imported) {
|
||||
DWORD yes = 1;
|
||||
|
|
@ -89,6 +125,17 @@ static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle,
|
|||
}
|
||||
}
|
||||
|
||||
if ((handle->flags & UV_HANDLE_TCP_NODELAY) &&
|
||||
uv__tcp_nodelay(handle, socket, 1)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* TODO: Use stored delay. */
|
||||
if ((handle->flags & UV_HANDLE_TCP_KEEPALIVE) &&
|
||||
uv__tcp_keepalive(handle, socket, 1, 60)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
handle->socket = socket;
|
||||
|
||||
return 0;
|
||||
|
|
@ -105,6 +152,7 @@ int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* handle) {
|
|||
handle->reqs_pending = 0;
|
||||
handle->func_acceptex = NULL;
|
||||
handle->func_connectex = NULL;
|
||||
handle->processed_accepts = 0;
|
||||
|
||||
loop->counters.tcp_init++;
|
||||
|
||||
|
|
@ -392,7 +440,7 @@ static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) {
|
|||
|
||||
int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
|
||||
uv_loop_t* loop = handle->loop;
|
||||
unsigned int i;
|
||||
unsigned int i, simultaneous_accepts;
|
||||
uv_tcp_accept_t* req;
|
||||
|
||||
assert(backlog > 0);
|
||||
|
|
@ -402,13 +450,6 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (handle->flags & UV_HANDLE_LISTENING ||
|
||||
handle->flags & UV_HANDLE_READING) {
|
||||
/* Already listening. */
|
||||
uv__set_sys_error(loop, WSAEALREADY);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(handle->flags & UV_HANDLE_BOUND) &&
|
||||
uv_tcp_bind(handle, uv_addr_ip4_any_) < 0)
|
||||
return -1;
|
||||
|
|
@ -420,7 +461,8 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
|
|||
}
|
||||
}
|
||||
|
||||
if (listen(handle->socket, backlog) == SOCKET_ERROR) {
|
||||
if (!(handle->flags & UV_HANDLE_SHARED_TCP_SERVER) &&
|
||||
listen(handle->socket, backlog) == SOCKET_ERROR) {
|
||||
uv__set_sys_error(loop, WSAGetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -428,31 +470,35 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
|
|||
handle->flags |= UV_HANDLE_LISTENING;
|
||||
handle->connection_cb = cb;
|
||||
|
||||
assert(!handle->accept_reqs);
|
||||
handle->accept_reqs = (uv_tcp_accept_t*)
|
||||
malloc(uv_simultaneous_server_accepts * sizeof(uv_tcp_accept_t));
|
||||
if (!handle->accept_reqs) {
|
||||
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
|
||||
}
|
||||
simultaneous_accepts = handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT ? 1
|
||||
: uv_simultaneous_server_accepts;
|
||||
|
||||
for (i = 0; i < uv_simultaneous_server_accepts; i++) {
|
||||
req = &handle->accept_reqs[i];
|
||||
uv_req_init(loop, (uv_req_t*)req);
|
||||
req->type = UV_ACCEPT;
|
||||
req->accept_socket = INVALID_SOCKET;
|
||||
req->data = handle;
|
||||
|
||||
req->wait_handle = INVALID_HANDLE_VALUE;
|
||||
if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
|
||||
req->event_handle = CreateEvent(NULL, 0, 0, NULL);
|
||||
if (!req->event_handle) {
|
||||
uv_fatal_error(GetLastError(), "CreateEvent");
|
||||
}
|
||||
} else {
|
||||
req->event_handle = NULL;
|
||||
if(!handle->accept_reqs) {
|
||||
handle->accept_reqs = (uv_tcp_accept_t*)
|
||||
malloc(simultaneous_accepts * sizeof(uv_tcp_accept_t));
|
||||
if (!handle->accept_reqs) {
|
||||
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
|
||||
}
|
||||
|
||||
uv_tcp_queue_accept(handle, req);
|
||||
for (i = 0; i < simultaneous_accepts; i++) {
|
||||
req = &handle->accept_reqs[i];
|
||||
uv_req_init(loop, (uv_req_t*)req);
|
||||
req->type = UV_ACCEPT;
|
||||
req->accept_socket = INVALID_SOCKET;
|
||||
req->data = handle;
|
||||
|
||||
req->wait_handle = INVALID_HANDLE_VALUE;
|
||||
if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
|
||||
req->event_handle = CreateEvent(NULL, 0, 0, NULL);
|
||||
if (!req->event_handle) {
|
||||
uv_fatal_error(GetLastError(), "CreateEvent");
|
||||
}
|
||||
} else {
|
||||
req->event_handle = NULL;
|
||||
}
|
||||
|
||||
uv_tcp_queue_accept(handle, req);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -491,7 +537,26 @@ int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) {
|
|||
req->accept_socket = INVALID_SOCKET;
|
||||
|
||||
if (!(server->flags & UV_HANDLE_CLOSING)) {
|
||||
uv_tcp_queue_accept(server, req);
|
||||
/* Check if we're in a middle of changing the number of pending accepts. */
|
||||
if (!(server->flags & UV_HANDLE_TCP_ACCEPT_STATE_CHANGING)) {
|
||||
uv_tcp_queue_accept(server, req);
|
||||
} else {
|
||||
/* We better be switching to a single pending accept. */
|
||||
assert(server->flags & UV_HANDLE_TCP_SINGLE_ACCEPT);
|
||||
|
||||
server->processed_accepts++;
|
||||
|
||||
if (server->processed_accepts >= uv_simultaneous_server_accepts) {
|
||||
server->processed_accepts = 0;
|
||||
/*
|
||||
* All previously queued accept requests are now processed.
|
||||
* We now switch to queueing just a single accept.
|
||||
*/
|
||||
uv_tcp_queue_accept(server, &server->accept_reqs[0]);
|
||||
server->flags &= ~UV_HANDLE_TCP_ACCEPT_STATE_CHANGING;
|
||||
server->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
active_tcp_streams++;
|
||||
|
|
@ -759,9 +824,19 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
|
|||
/* An error occurred doing the read. */
|
||||
if ((handle->flags & UV_HANDLE_READING)) {
|
||||
handle->flags &= ~UV_HANDLE_READING;
|
||||
uv__set_sys_error(loop, GET_REQ_SOCK_ERROR(req));
|
||||
buf = (handle->flags & UV_HANDLE_ZERO_READ) ?
|
||||
uv_buf_init(NULL, 0) : handle->read_buffer;
|
||||
|
||||
err = GET_REQ_SOCK_ERROR(req);
|
||||
|
||||
if (err == WSAECONNABORTED) {
|
||||
/* Treat WSAECONNABORTED as connection closed. */
|
||||
handle->flags |= UV_HANDLE_EOF;
|
||||
uv__set_error(loop, UV_EOF, ERROR_SUCCESS);
|
||||
} else {
|
||||
uv__set_sys_error(loop, err);
|
||||
}
|
||||
|
||||
handle->read_cb((uv_stream_t*)handle, -1, buf);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -822,8 +897,14 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
|
|||
uv__set_sys_error(loop, WSAEWOULDBLOCK);
|
||||
handle->read_cb((uv_stream_t*)handle, 0, buf);
|
||||
} else {
|
||||
/* Ouch! serious error. */
|
||||
uv__set_sys_error(loop, err);
|
||||
if (err == WSAECONNABORTED) {
|
||||
/* Treat WSAECONNABORTED as connection closed. */
|
||||
handle->flags |= UV_HANDLE_EOF;
|
||||
uv__set_error(loop, UV_EOF, ERROR_SUCCESS);
|
||||
} else {
|
||||
/* Ouch! serious error. */
|
||||
uv__set_sys_error(loop, err);
|
||||
}
|
||||
handle->flags &= ~UV_HANDLE_READING;
|
||||
handle->read_cb((uv_stream_t*)handle, -1, buf);
|
||||
}
|
||||
|
|
@ -953,18 +1034,111 @@ int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info) {
|
|||
}
|
||||
|
||||
tcp->flags |= UV_HANDLE_BOUND;
|
||||
tcp->flags |= UV_HANDLE_SHARED_TCP_SERVER;
|
||||
|
||||
return uv_tcp_set_socket(tcp->loop, tcp, socket, 1);
|
||||
}
|
||||
|
||||
|
||||
int uv_tcp_nodelay(uv_tcp_t* handle, int enable) {
|
||||
uv__set_artificial_error(handle->loop, UV_ENOSYS);
|
||||
return -1;
|
||||
if (handle->socket != INVALID_SOCKET &&
|
||||
uv__tcp_nodelay(handle, handle->socket, enable)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
handle->flags |= UV_HANDLE_TCP_NODELAY;
|
||||
} else {
|
||||
handle->flags &= ~UV_HANDLE_TCP_NODELAY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) {
|
||||
uv__set_artificial_error(handle->loop, UV_ENOSYS);
|
||||
return -1;
|
||||
if (handle->socket != INVALID_SOCKET &&
|
||||
uv__tcp_keepalive(handle, handle->socket, enable, delay)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
handle->flags |= UV_HANDLE_TCP_KEEPALIVE;
|
||||
} else {
|
||||
handle->flags &= ~UV_HANDLE_TCP_KEEPALIVE;
|
||||
}
|
||||
|
||||
/* TODO: Store delay if handle->socket isn't created yet. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid,
|
||||
LPWSAPROTOCOL_INFOW protocol_info) {
|
||||
assert(!(handle->flags & UV_HANDLE_CONNECTION));
|
||||
|
||||
/*
|
||||
* We're about to share the socket with another process. Because
|
||||
* this is a listening socket, we assume that the other process will
|
||||
* be accepting conections on it. So, before sharing the socket
|
||||
* with another process, we call listen here in the parent process.
|
||||
* This needs to be modified if the socket is shared with
|
||||
* another process for anything other than accepting connections.
|
||||
*/
|
||||
|
||||
if (!(handle->flags & UV_HANDLE_LISTENING)) {
|
||||
if (!(handle->flags & UV_HANDLE_BOUND)) {
|
||||
uv__set_artificial_error(handle->loop, UV_EINVAL);
|
||||
return -1;
|
||||
}
|
||||
if (listen(handle->socket, SOMAXCONN) == SOCKET_ERROR) {
|
||||
uv__set_sys_error(handle->loop, WSAGetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
handle->flags |= UV_HANDLE_SHARED_TCP_SERVER;
|
||||
}
|
||||
|
||||
if (WSADuplicateSocketW(handle->socket, pid, protocol_info)) {
|
||||
uv__set_sys_error(handle->loop, WSAGetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {
|
||||
if (handle->flags & UV_HANDLE_CONNECTION) {
|
||||
uv__set_artificial_error(handle->loop, UV_EINVAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check if we're already in the desired mode. */
|
||||
if ((enable && !(handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT)) ||
|
||||
(!enable && handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Don't allow switching from single pending accept to many. */
|
||||
if (enable) {
|
||||
uv__set_artificial_error(handle->loop, UV_ENOTSUP);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check if we're in a middle of changing the number of pending accepts. */
|
||||
if (handle->flags & UV_HANDLE_TCP_ACCEPT_STATE_CHANGING) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
handle->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;
|
||||
|
||||
/* Flip the changing flag if we have already queueed multiple accepts. */
|
||||
if (handle->flags & UV_HANDLE_LISTENING) {
|
||||
handle->flags |= UV_HANDLE_TCP_ACCEPT_STATE_CHANGING;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -37,6 +37,10 @@
|
|||
# define SO_UPDATE_CONNECT_CONTEXT 0x7010
|
||||
#endif
|
||||
|
||||
#ifndef TCP_KEEPALIVE
|
||||
# define TCP_KEEPALIVE 3
|
||||
#endif
|
||||
|
||||
#ifndef IPV6_V6ONLY
|
||||
#define IPV6_V6ONLY 27
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -225,12 +225,7 @@ static void pipe_make_connect(conn_rec* p) {
|
|||
r = uv_pipe_init(loop, (uv_pipe_t*)&p->stream, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_pipe_connect(&((pipe_conn_rec*)p)->conn_req, (uv_pipe_t*)&p->stream, TEST_PIPENAME, connect_cb);
|
||||
if (r) {
|
||||
fprintf(stderr, "uv_tcp_connect error %s\n",
|
||||
uv_err_name(uv_last_error(loop)));
|
||||
ASSERT(0);
|
||||
}
|
||||
uv_pipe_connect(&((pipe_conn_rec*)p)->conn_req, (uv_pipe_t*)&p->stream, TEST_PIPENAME, connect_cb);
|
||||
|
||||
#if DEBUG
|
||||
printf("make connect %d\n", p->i);
|
||||
|
|
|
|||
|
|
@ -257,8 +257,7 @@ static void maybe_connect_some() {
|
|||
ASSERT(r == 0);
|
||||
|
||||
req = (uv_connect_t*) req_alloc();
|
||||
r = uv_pipe_connect(req, pipe, TEST_PIPENAME, connect_cb);
|
||||
ASSERT(r == 0);
|
||||
uv_pipe_connect(req, pipe, TEST_PIPENAME, connect_cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ static void ipc_on_connection(uv_stream_t* server, int status) {
|
|||
}
|
||||
|
||||
|
||||
static int ipc_helper() {
|
||||
static int ipc_helper(int listen_after_write) {
|
||||
/*
|
||||
* This is launched from test-ipc.c. stdin is a duplex channel that we
|
||||
* over which a handle will be transmitted. In this initial version only
|
||||
|
|
@ -135,14 +135,21 @@ static int ipc_helper() {
|
|||
r = uv_tcp_bind(&tcp_server, uv_ip4_addr("0.0.0.0", TEST_PORT));
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_listen((uv_stream_t*)&tcp_server, 12, ipc_on_connection);
|
||||
ASSERT(r == 0);
|
||||
if (!listen_after_write) {
|
||||
r = uv_listen((uv_stream_t*)&tcp_server, 12, ipc_on_connection);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
buf = uv_buf_init("hello\n", 6);
|
||||
r = uv_write2(&write_req, (uv_stream_t*)&channel, &buf, 1,
|
||||
(uv_stream_t*)&tcp_server, NULL);
|
||||
ASSERT(r == 0);
|
||||
|
||||
if (listen_after_write) {
|
||||
r = uv_listen((uv_stream_t*)&tcp_server, 12, ipc_on_connection);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
r = uv_run(uv_default_loop());
|
||||
ASSERT(r == 0);
|
||||
|
||||
|
|
@ -251,8 +258,12 @@ static int maybe_run_test(int argc, char **argv) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "ipc_helper") == 0) {
|
||||
return ipc_helper();
|
||||
if (strcmp(argv[1], "ipc_helper_listen_before_write") == 0) {
|
||||
return ipc_helper(0);
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "ipc_helper_listen_after_write") == 0) {
|
||||
return ipc_helper(1);
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "stdio_over_pipes_helper") == 0) {
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ TEST_IMPL(fs_event_watch_dir) {
|
|||
uv_fs_rmdir(loop, &fs_req, "watch_dir", NULL);
|
||||
create_dir(loop, "watch_dir");
|
||||
|
||||
r = uv_fs_event_init(loop, &fs_event, "watch_dir", fs_event_cb_dir);
|
||||
r = uv_fs_event_init(loop, &fs_event, "watch_dir", fs_event_cb_dir, 0);
|
||||
ASSERT(r != -1);
|
||||
r = uv_timer_init(loop, &timer);
|
||||
ASSERT(r != -1);
|
||||
|
|
@ -178,7 +178,7 @@ TEST_IMPL(fs_event_watch_file) {
|
|||
create_file(loop, "watch_dir/file1");
|
||||
create_file(loop, "watch_dir/file2");
|
||||
|
||||
r = uv_fs_event_init(loop, &fs_event, "watch_dir/file2", fs_event_cb_file);
|
||||
r = uv_fs_event_init(loop, &fs_event, "watch_dir/file2", fs_event_cb_file, 0);
|
||||
ASSERT(r != -1);
|
||||
r = uv_timer_init(loop, &timer);
|
||||
ASSERT(r != -1);
|
||||
|
|
@ -212,7 +212,7 @@ TEST_IMPL(fs_event_watch_file_current_dir) {
|
|||
create_file(loop, "watch_file");
|
||||
|
||||
r = uv_fs_event_init(loop, &fs_event, "watch_file",
|
||||
fs_event_cb_file_current_dir);
|
||||
fs_event_cb_file_current_dir, 0);
|
||||
ASSERT(r != -1);
|
||||
|
||||
r = uv_timer_init(loop, &timer);
|
||||
|
|
@ -235,3 +235,36 @@ TEST_IMPL(fs_event_watch_file_current_dir) {
|
|||
r = uv_fs_unlink(loop, &fs_req, "watch_file", NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(fs_event_no_callback_on_close) {
|
||||
uv_fs_t fs_req;
|
||||
uv_loop_t* loop = uv_default_loop();
|
||||
int r;
|
||||
|
||||
/* Setup */
|
||||
uv_fs_unlink(loop, &fs_req, "watch_dir/file1", NULL);
|
||||
uv_fs_rmdir(loop, &fs_req, "watch_dir", NULL);
|
||||
create_dir(loop, "watch_dir");
|
||||
create_file(loop, "watch_dir/file1");
|
||||
|
||||
r = uv_fs_event_init(loop,
|
||||
&fs_event,
|
||||
"watch_dir/file1",
|
||||
fs_event_cb_file,
|
||||
0);
|
||||
ASSERT(r != -1);
|
||||
|
||||
uv_close((uv_handle_t*)&fs_event, close_cb);
|
||||
|
||||
uv_run(loop);
|
||||
|
||||
ASSERT(fs_event_cb_called == 0);
|
||||
ASSERT(close_cb_called == 1);
|
||||
|
||||
/* Cleanup */
|
||||
r = uv_fs_unlink(loop, &fs_req, "watch_dir/file1", NULL);
|
||||
r = uv_fs_rmdir(loop, &fs_req, "watch_dir", NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1408,3 +1408,71 @@ TEST_IMPL(fs_open_dir) {
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(fs_file_open_append) {
|
||||
int r;
|
||||
|
||||
/* Setup. */
|
||||
unlink("test_file");
|
||||
|
||||
loop = uv_default_loop();
|
||||
|
||||
r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT,
|
||||
S_IWRITE | S_IREAD, NULL);
|
||||
ASSERT(r != -1);
|
||||
ASSERT(open_req1.result != -1);
|
||||
uv_fs_req_cleanup(&open_req1);
|
||||
|
||||
r = uv_fs_write(loop, &write_req, open_req1.result, test_buf,
|
||||
sizeof(test_buf), -1, NULL);
|
||||
ASSERT(r != -1);
|
||||
ASSERT(write_req.result != -1);
|
||||
uv_fs_req_cleanup(&write_req);
|
||||
|
||||
r = uv_fs_close(loop, &close_req, open_req1.result, NULL);
|
||||
ASSERT(r != -1);
|
||||
ASSERT(close_req.result != -1);
|
||||
uv_fs_req_cleanup(&close_req);
|
||||
|
||||
r = uv_fs_open(loop, &open_req1, "test_file", O_RDWR | O_APPEND, 0, NULL);
|
||||
ASSERT(r != -1);
|
||||
ASSERT(open_req1.result != -1);
|
||||
uv_fs_req_cleanup(&open_req1);
|
||||
|
||||
r = uv_fs_write(loop, &write_req, open_req1.result, test_buf,
|
||||
sizeof(test_buf), -1, NULL);
|
||||
ASSERT(r != -1);
|
||||
ASSERT(write_req.result != -1);
|
||||
uv_fs_req_cleanup(&write_req);
|
||||
|
||||
r = uv_fs_close(loop, &close_req, open_req1.result, NULL);
|
||||
ASSERT(r != -1);
|
||||
ASSERT(close_req.result != -1);
|
||||
uv_fs_req_cleanup(&close_req);
|
||||
|
||||
r = uv_fs_open(loop, &open_req1, "test_file", O_RDONLY, S_IREAD, NULL);
|
||||
ASSERT(r != -1);
|
||||
ASSERT(open_req1.result != -1);
|
||||
uv_fs_req_cleanup(&open_req1);
|
||||
|
||||
r = uv_fs_read(loop, &read_req, open_req1.result, buf, sizeof(buf), -1,
|
||||
NULL);
|
||||
printf("read = %d\n", r);
|
||||
ASSERT(r == 26);
|
||||
ASSERT(read_req.result == 26);
|
||||
ASSERT(memcmp(buf,
|
||||
"test-buffer\n\0test-buffer\n\0",
|
||||
sizeof("test-buffer\n\0test-buffer\n\0") - 1) == 0);
|
||||
uv_fs_req_cleanup(&read_req);
|
||||
|
||||
r = uv_fs_close(loop, &close_req, open_req1.result, NULL);
|
||||
ASSERT(r != -1);
|
||||
ASSERT(close_req.result != -1);
|
||||
uv_fs_req_cleanup(&close_req);
|
||||
|
||||
/* Cleanup */
|
||||
unlink("test_file");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ static void on_read(uv_pipe_t* pipe, ssize_t nread, uv_buf_t buf,
|
|||
}
|
||||
|
||||
|
||||
TEST_IMPL(ipc) {
|
||||
int run_ipc_test(const char* helper) {
|
||||
int r;
|
||||
uv_process_options_t options;
|
||||
uv_process_t process;
|
||||
|
|
@ -199,7 +199,7 @@ TEST_IMPL(ipc) {
|
|||
ASSERT(r == 0);
|
||||
exepath[exepath_size] = '\0';
|
||||
args[0] = exepath;
|
||||
args[1] = "ipc_helper";
|
||||
args[1] = (char*)helper;
|
||||
args[2] = NULL;
|
||||
options.file = exepath;
|
||||
options.args = args;
|
||||
|
|
@ -220,3 +220,59 @@ TEST_IMPL(ipc) {
|
|||
ASSERT(exit_cb_called == 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(ipc_listen_before_write) {
|
||||
return run_ipc_test("ipc_helper_listen_before_write");
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(ipc_listen_after_write) {
|
||||
return run_ipc_test("ipc_helper_listen_after_write");
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
TEST_IMPL(listen_with_simultaneous_accepts) {
|
||||
uv_tcp_t server;
|
||||
int r;
|
||||
struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", TEST_PORT);
|
||||
|
||||
r = uv_tcp_init(uv_default_loop(), &server);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_tcp_bind(&server, addr);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_tcp_simultaneous_accepts(&server, 1);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_listen((uv_stream_t*)&server, SOMAXCONN, NULL);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(server.reqs_pending == 32);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(listen_no_simultaneous_accepts) {
|
||||
uv_tcp_t server;
|
||||
int r;
|
||||
struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", TEST_PORT);
|
||||
|
||||
r = uv_tcp_init(uv_default_loop(), &server);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_tcp_bind(&server, addr);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_tcp_simultaneous_accepts(&server, 0);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_listen((uv_stream_t*)&server, SOMAXCONN, NULL);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(server.reqs_pending == 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -21,13 +21,15 @@
|
|||
|
||||
TEST_DECLARE (tty)
|
||||
TEST_DECLARE (stdio_over_pipes)
|
||||
TEST_DECLARE (ipc)
|
||||
TEST_DECLARE (ipc_listen_before_write)
|
||||
TEST_DECLARE (ipc_listen_after_write)
|
||||
TEST_DECLARE (tcp_ping_pong)
|
||||
TEST_DECLARE (tcp_ping_pong_v6)
|
||||
TEST_DECLARE (tcp_ref)
|
||||
TEST_DECLARE (tcp_ref2)
|
||||
TEST_DECLARE (pipe_ping_pong)
|
||||
TEST_DECLARE (delayed_accept)
|
||||
TEST_DECLARE (multiple_listen)
|
||||
TEST_DECLARE (tcp_writealot)
|
||||
TEST_DECLARE (tcp_bind_error_addrinuse)
|
||||
TEST_DECLARE (tcp_bind_error_addrnotavail_1)
|
||||
|
|
@ -39,6 +41,7 @@ TEST_DECLARE (tcp_listen_without_bind)
|
|||
TEST_DECLARE (tcp_close)
|
||||
TEST_DECLARE (tcp_flags)
|
||||
TEST_DECLARE (tcp_write_error)
|
||||
TEST_DECLARE (tcp_write_to_half_open_connection)
|
||||
TEST_DECLARE (tcp_bind6_error_addrinuse)
|
||||
TEST_DECLARE (tcp_bind6_error_addrnotavail)
|
||||
TEST_DECLARE (tcp_bind6_error_fault)
|
||||
|
|
@ -53,6 +56,7 @@ TEST_DECLARE (pipe_bind_error_addrinuse)
|
|||
TEST_DECLARE (pipe_bind_error_addrnotavail)
|
||||
TEST_DECLARE (pipe_bind_error_inval)
|
||||
TEST_DECLARE (pipe_listen_without_bind)
|
||||
TEST_DECLARE (pipe_connect_bad_name)
|
||||
TEST_DECLARE (connection_fail)
|
||||
TEST_DECLARE (connection_fail_doesnt_auto_close)
|
||||
TEST_DECLARE (shutdown_eof)
|
||||
|
|
@ -87,6 +91,7 @@ TEST_DECLARE (spawn_stdout)
|
|||
TEST_DECLARE (spawn_stdin)
|
||||
TEST_DECLARE (spawn_and_kill)
|
||||
TEST_DECLARE (spawn_and_ping)
|
||||
TEST_DECLARE (kill)
|
||||
TEST_DECLARE (fs_file_noent)
|
||||
TEST_DECLARE (fs_file_async)
|
||||
TEST_DECLARE (fs_file_sync)
|
||||
|
|
@ -99,10 +104,12 @@ TEST_DECLARE (fs_link)
|
|||
TEST_DECLARE (fs_symlink)
|
||||
TEST_DECLARE (fs_utime)
|
||||
TEST_DECLARE (fs_futime)
|
||||
TEST_DECLARE (fs_file_open_append)
|
||||
TEST_DECLARE (fs_stat_missing_path)
|
||||
TEST_DECLARE (fs_event_watch_dir)
|
||||
TEST_DECLARE (fs_event_watch_file)
|
||||
TEST_DECLARE (fs_event_watch_file_current_dir)
|
||||
TEST_DECLARE (fs_event_no_callback_on_close)
|
||||
TEST_DECLARE (fs_readdir_empty_dir)
|
||||
TEST_DECLARE (fs_readdir_file)
|
||||
TEST_DECLARE (fs_open_dir)
|
||||
|
|
@ -111,6 +118,8 @@ TEST_DECLARE (threadpool_queue_work_simple)
|
|||
TEST_DECLARE (spawn_detect_pipe_name_collisions_on_windows)
|
||||
TEST_DECLARE (argument_escaping)
|
||||
TEST_DECLARE (environment_creation)
|
||||
TEST_DECLARE (listen_with_simultaneous_accepts)
|
||||
TEST_DECLARE (listen_no_simultaneous_accepts)
|
||||
#endif
|
||||
HELPER_DECLARE (tcp4_echo_server)
|
||||
HELPER_DECLARE (tcp6_echo_server)
|
||||
|
|
@ -118,10 +127,12 @@ HELPER_DECLARE (pipe_echo_server)
|
|||
|
||||
|
||||
TASK_LIST_START
|
||||
TEST_ENTRY (pipe_connect_bad_name)
|
||||
|
||||
TEST_ENTRY (tty)
|
||||
TEST_ENTRY (stdio_over_pipes)
|
||||
TEST_ENTRY (ipc)
|
||||
|
||||
TEST_ENTRY (ipc_listen_before_write)
|
||||
TEST_ENTRY (ipc_listen_after_write)
|
||||
|
||||
TEST_ENTRY (tcp_ref)
|
||||
|
||||
|
|
@ -138,6 +149,7 @@ TASK_LIST_START
|
|||
TEST_HELPER (pipe_ping_pong, pipe_echo_server)
|
||||
|
||||
TEST_ENTRY (delayed_accept)
|
||||
TEST_ENTRY (multiple_listen)
|
||||
|
||||
TEST_ENTRY (tcp_writealot)
|
||||
TEST_HELPER (tcp_writealot, tcp4_echo_server)
|
||||
|
|
@ -152,6 +164,7 @@ TASK_LIST_START
|
|||
TEST_ENTRY (tcp_close)
|
||||
TEST_ENTRY (tcp_flags)
|
||||
TEST_ENTRY (tcp_write_error)
|
||||
TEST_ENTRY (tcp_write_to_half_open_connection)
|
||||
|
||||
TEST_ENTRY (tcp_bind6_error_addrinuse)
|
||||
TEST_ENTRY (tcp_bind6_error_addrnotavail)
|
||||
|
|
@ -222,10 +235,13 @@ TASK_LIST_START
|
|||
TEST_ENTRY (spawn_stdin)
|
||||
TEST_ENTRY (spawn_and_kill)
|
||||
TEST_ENTRY (spawn_and_ping)
|
||||
TEST_ENTRY (kill)
|
||||
#ifdef _WIN32
|
||||
TEST_ENTRY (spawn_detect_pipe_name_collisions_on_windows)
|
||||
TEST_ENTRY (argument_escaping)
|
||||
TEST_ENTRY (environment_creation)
|
||||
TEST_ENTRY (listen_with_simultaneous_accepts)
|
||||
TEST_ENTRY (listen_no_simultaneous_accepts)
|
||||
#endif
|
||||
|
||||
TEST_ENTRY (fs_file_noent)
|
||||
|
|
@ -240,9 +256,11 @@ TASK_LIST_START
|
|||
TEST_ENTRY (fs_futime)
|
||||
TEST_ENTRY (fs_symlink)
|
||||
TEST_ENTRY (fs_stat_missing_path)
|
||||
TEST_ENTRY (fs_file_open_append)
|
||||
TEST_ENTRY (fs_event_watch_dir)
|
||||
TEST_ENTRY (fs_event_watch_file)
|
||||
TEST_ENTRY (fs_event_watch_file_current_dir)
|
||||
TEST_ENTRY (fs_event_no_callback_on_close)
|
||||
TEST_ENTRY (fs_readdir_empty_dir)
|
||||
TEST_ENTRY (fs_readdir_file)
|
||||
TEST_ENTRY (fs_open_dir)
|
||||
|
|
|
|||
102
src/rt/libuv/test/test-multiple-listen.c
Normal file
102
src/rt/libuv/test/test-multiple-listen.c
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/* 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>
|
||||
|
||||
static int connection_cb_called = 0;
|
||||
static int close_cb_called = 0;
|
||||
static int connect_cb_called = 0;
|
||||
static uv_tcp_t server;
|
||||
static uv_tcp_t client;
|
||||
|
||||
|
||||
static void close_cb(uv_handle_t* handle) {
|
||||
ASSERT(handle != NULL);
|
||||
close_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void connection_cb(uv_stream_t* tcp, int status) {
|
||||
ASSERT(status == 0);
|
||||
uv_close((uv_handle_t*)&server, close_cb);
|
||||
connection_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void start_server() {
|
||||
struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", TEST_PORT);
|
||||
int r;
|
||||
|
||||
r = uv_tcp_init(uv_default_loop(), &server);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_tcp_bind(&server, addr);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_listen((uv_stream_t*)&server, 128, connection_cb);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_listen((uv_stream_t*)&server, 128, connection_cb);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
|
||||
static void connect_cb(uv_connect_t* req, int status) {
|
||||
ASSERT(req != NULL);
|
||||
ASSERT(status == 0);
|
||||
free(req);
|
||||
uv_close((uv_handle_t*)&client, close_cb);
|
||||
connect_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void client_connect() {
|
||||
struct sockaddr_in addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
|
||||
uv_connect_t* connect_req = malloc(sizeof *connect_req);
|
||||
int r;
|
||||
|
||||
ASSERT(connect_req != NULL);
|
||||
|
||||
r = uv_tcp_init(uv_default_loop(), &client);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_tcp_connect(connect_req, &client, addr, connect_cb);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST_IMPL(multiple_listen) {
|
||||
start_server();
|
||||
|
||||
client_connect();
|
||||
|
||||
uv_run(uv_default_loop());
|
||||
|
||||
ASSERT(connection_cb_called == 1);
|
||||
ASSERT(connect_cb_called == 1);
|
||||
ASSERT(close_cb_called == 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -211,9 +211,8 @@ static void pipe_pinger_new() {
|
|||
/* We are never doing multiple reads/connects at a time anyway. */
|
||||
/* so these handles can be pre-initialized. */
|
||||
|
||||
r = uv_pipe_connect(&pinger->connect_req, &pinger->stream.pipe, TEST_PIPENAME,
|
||||
uv_pipe_connect(&pinger->connect_req, &pinger->stream.pipe, TEST_PIPENAME,
|
||||
pinger_on_connect);
|
||||
ASSERT(!r);
|
||||
|
||||
/* Synchronous connect callbacks are not allowed. */
|
||||
ASSERT(pinger_on_connect_count == 0);
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ TEST_IMPL(pipe_bind_error_addrnotavail) {
|
|||
r = uv_pipe_bind(&server, BAD_PIPENAME);
|
||||
|
||||
ASSERT(r == -1);
|
||||
ASSERT(uv_last_error(uv_default_loop()).code == UV_EACCESS);
|
||||
ASSERT(uv_last_error(uv_default_loop()).code == UV_EACCES);
|
||||
|
||||
uv_close((uv_handle_t*)&server, close_cb);
|
||||
|
||||
|
|
|
|||
68
src/rt/libuv/test/test-pipe-connect-error.c
Normal file
68
src/rt/libuv/test/test-pipe-connect-error.c
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/* 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>
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
# define BAD_PIPENAME "bad-pipe"
|
||||
#else
|
||||
# define BAD_PIPENAME "/path/to/unix/socket/that/really/should/not/be/there"
|
||||
#endif
|
||||
|
||||
|
||||
static int close_cb_called = 0;
|
||||
static int connect_cb_called = 0;
|
||||
|
||||
|
||||
static void close_cb(uv_handle_t* handle) {
|
||||
ASSERT(handle != NULL);
|
||||
close_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void connect_cb(uv_connect_t* connect_req, int status) {
|
||||
ASSERT(status == -1);
|
||||
ASSERT(uv_last_error(uv_default_loop()).code == UV_ENOENT);
|
||||
uv_close((uv_handle_t*)connect_req->handle, close_cb);
|
||||
connect_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(pipe_connect_bad_name) {
|
||||
uv_pipe_t client;
|
||||
uv_connect_t req;
|
||||
int r;
|
||||
|
||||
r = uv_pipe_init(uv_default_loop(), &client, 0);
|
||||
ASSERT(r == 0);
|
||||
uv_pipe_connect(&req, &client, BAD_PIPENAME, connect_cb);
|
||||
|
||||
uv_run(uv_default_loop());
|
||||
|
||||
ASSERT(close_cb_called == 1);
|
||||
ASSERT(connect_cb_called == 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -33,6 +33,7 @@ static uv_process_options_t options;
|
|||
static char exepath[1024];
|
||||
static size_t exepath_size = 1024;
|
||||
static char* args[3];
|
||||
static int no_term_signal;
|
||||
|
||||
#define OUTPUT_SIZE 1024
|
||||
static char output[OUTPUT_SIZE];
|
||||
|
|
@ -55,6 +56,8 @@ static void exit_cb(uv_process_t* process, int exit_status, int term_signal) {
|
|||
|
||||
|
||||
static void kill_cb(uv_process_t* process, int exit_status, int term_signal) {
|
||||
uv_err_t err;
|
||||
|
||||
printf("exit_cb\n");
|
||||
exit_cb_called++;
|
||||
#ifdef _WIN32
|
||||
|
|
@ -62,8 +65,14 @@ static void kill_cb(uv_process_t* process, int exit_status, int term_signal) {
|
|||
#else
|
||||
ASSERT(exit_status == 0);
|
||||
#endif
|
||||
ASSERT(term_signal == 15);
|
||||
ASSERT(no_term_signal || term_signal == 15);
|
||||
uv_close((uv_handle_t*)process, close_cb);
|
||||
|
||||
/* Sending signum == 0 should check if the
|
||||
* child process is still alive, not kill it.
|
||||
*/
|
||||
err = uv_kill(process->pid, 0);
|
||||
ASSERT(err.code != UV_OK);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -261,6 +270,39 @@ TEST_IMPL(spawn_and_ping) {
|
|||
}
|
||||
|
||||
|
||||
TEST_IMPL(kill) {
|
||||
int r;
|
||||
uv_err_t err;
|
||||
|
||||
#ifdef _WIN32
|
||||
no_term_signal = 1;
|
||||
#endif
|
||||
|
||||
init_process_options("spawn_helper4", kill_cb);
|
||||
|
||||
r = uv_spawn(uv_default_loop(), &process, options);
|
||||
ASSERT(r == 0);
|
||||
|
||||
/* Sending signum == 0 should check if the
|
||||
* child process is still alive, not kill it.
|
||||
*/
|
||||
err = uv_kill(process.pid, 0);
|
||||
ASSERT(err.code == UV_OK);
|
||||
|
||||
/* Kill the process. */
|
||||
err = uv_kill(process.pid, /* SIGTERM */ 15);
|
||||
ASSERT(err.code == UV_OK);
|
||||
|
||||
r = uv_run(uv_default_loop());
|
||||
ASSERT(r == 0);
|
||||
|
||||
ASSERT(exit_cb_called == 1);
|
||||
ASSERT(close_cb_called == 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
TEST_IMPL(spawn_detect_pipe_name_collisions_on_windows) {
|
||||
int r;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@
|
|||
#include "uv.h"
|
||||
#include "task.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static char exepath[1024];
|
||||
static size_t exepath_size = 1024;
|
||||
|
|
|
|||
139
src/rt/libuv/test/test-tcp-write-to-half-open-connection.c
Normal file
139
src/rt/libuv/test/test-tcp-write-to-half-open-connection.c
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
/* 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>
|
||||
|
||||
static void connection_cb(uv_stream_t* server, int status);
|
||||
static void connect_cb(uv_connect_t* req, int status);
|
||||
static void write_cb(uv_write_t* req, int status);
|
||||
static void read_cb(uv_stream_t* stream, ssize_t nread, uv_buf_t buf);
|
||||
static uv_buf_t alloc_cb(uv_handle_t* handle, size_t suggested_size);
|
||||
|
||||
static uv_tcp_t tcp_server;
|
||||
static uv_tcp_t tcp_client;
|
||||
static uv_tcp_t tcp_peer; /* client socket as accept()-ed by server */
|
||||
static uv_connect_t connect_req;
|
||||
static uv_write_t write_req;
|
||||
|
||||
static int write_cb_called;
|
||||
static int read_cb_called;
|
||||
static int read_eof_cb_called;
|
||||
|
||||
|
||||
static void connection_cb(uv_stream_t* server, int status) {
|
||||
int r;
|
||||
uv_buf_t buf;
|
||||
|
||||
ASSERT(server == (uv_stream_t*)&tcp_server);
|
||||
ASSERT(status == 0);
|
||||
|
||||
r = uv_tcp_init(server->loop, &tcp_peer);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_accept(server, (uv_stream_t*)&tcp_peer);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_read_start((uv_stream_t*)&tcp_peer, alloc_cb, read_cb);
|
||||
ASSERT(r == 0);
|
||||
|
||||
buf.base = "hello\n";
|
||||
buf.len = 6;
|
||||
|
||||
r = uv_write(&write_req, (uv_stream_t*)&tcp_peer, &buf, 1, write_cb);
|
||||
ASSERT(r == 0);
|
||||
}
|
||||
|
||||
|
||||
static uv_buf_t alloc_cb(uv_handle_t* handle, size_t suggested_size) {
|
||||
static char slab[1024];
|
||||
return uv_buf_init(slab, sizeof slab);
|
||||
}
|
||||
|
||||
|
||||
static void read_cb(uv_stream_t* stream, ssize_t nread, uv_buf_t buf) {
|
||||
if (nread == -1) {
|
||||
fprintf(stderr, "read_cb error: %s\n", uv_err_name(uv_last_error(stream->loop)));
|
||||
ASSERT(uv_last_error(stream->loop).code == UV_EOF);
|
||||
|
||||
uv_close((uv_handle_t*)&tcp_server, NULL);
|
||||
uv_close((uv_handle_t*)&tcp_peer, NULL);
|
||||
|
||||
read_eof_cb_called++;
|
||||
}
|
||||
|
||||
read_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
static void connect_cb(uv_connect_t* req, int status) {
|
||||
ASSERT(req == &connect_req);
|
||||
ASSERT(status == 0);
|
||||
|
||||
/* Close the client. */
|
||||
uv_close((uv_handle_t*)&tcp_client, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void write_cb(uv_write_t* req, int status) {
|
||||
ASSERT(status == 0);
|
||||
write_cb_called++;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(tcp_write_to_half_open_connection) {
|
||||
uv_loop_t* loop;
|
||||
int r;
|
||||
|
||||
loop = uv_default_loop();
|
||||
ASSERT(loop != NULL);
|
||||
|
||||
r = uv_tcp_init(loop, &tcp_server);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_tcp_bind(&tcp_server, uv_ip4_addr("127.0.0.1", TEST_PORT));
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_listen((uv_stream_t*)&tcp_server, 1, connection_cb);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_tcp_init(loop, &tcp_client);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_tcp_connect(&connect_req,
|
||||
&tcp_client,
|
||||
uv_ip4_addr("127.0.0.1", TEST_PORT),
|
||||
connect_cb);
|
||||
ASSERT(r == 0);
|
||||
|
||||
r = uv_run(loop);
|
||||
ASSERT(r == 0);
|
||||
|
||||
ASSERT(write_cb_called > 0);
|
||||
ASSERT(read_cb_called > 0);
|
||||
ASSERT(read_eof_cb_called > 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -8,6 +8,15 @@
|
|||
'_GNU_SOURCE',
|
||||
'EIO_STACKSIZE=262144'
|
||||
],
|
||||
'conditions': [
|
||||
['OS=="solaris"', {
|
||||
'cflags': ['-pthreads'],
|
||||
'ldlags': ['-pthreads'],
|
||||
}, {
|
||||
'cflags': ['-pthread'],
|
||||
'ldlags': ['-pthread'],
|
||||
}],
|
||||
],
|
||||
}],
|
||||
],
|
||||
},
|
||||
|
|
@ -29,6 +38,7 @@
|
|||
'HAVE_CONFIG_H'
|
||||
],
|
||||
'sources': [
|
||||
'common.gypi',
|
||||
'include/ares.h',
|
||||
'include/ares_version.h',
|
||||
'include/uv.h',
|
||||
|
|
@ -120,6 +130,7 @@
|
|||
'src/win/async.c',
|
||||
'src/win/cares.c',
|
||||
'src/win/core.c',
|
||||
'src/win/dl.c',
|
||||
'src/win/error.c',
|
||||
'src/win/fs.c',
|
||||
'src/win/fs-event.c',
|
||||
|
|
@ -172,6 +183,7 @@
|
|||
'src/unix/tty.c',
|
||||
'src/unix/stream.c',
|
||||
'src/unix/cares.c',
|
||||
'src/unix/dl.c',
|
||||
'src/unix/error.c',
|
||||
'src/unix/process.c',
|
||||
'src/unix/internal.h',
|
||||
|
|
@ -280,9 +292,11 @@
|
|||
'test/test-ipc.c',
|
||||
'test/test-list.h',
|
||||
'test/test-loop-handles.c',
|
||||
'test/test-multiple-listen.c',
|
||||
'test/test-pass-always.c',
|
||||
'test/test-ping-pong.c',
|
||||
'test/test-pipe-bind-error.c',
|
||||
'test/test-pipe-connect-error.c',
|
||||
'test/test-ref.c',
|
||||
'test/test-shutdown-eof.c',
|
||||
'test/test-spawn.c',
|
||||
|
|
@ -294,6 +308,7 @@
|
|||
'test/test-tcp-connect-error.c',
|
||||
'test/test-tcp-connect6-error.c',
|
||||
'test/test-tcp-write-error.c',
|
||||
'test/test-tcp-write-to-half-open-connection.c',
|
||||
'test/test-tcp-writealot.c',
|
||||
'test/test-threadpool.c',
|
||||
'test/test-timer-again.c',
|
||||
|
|
@ -313,11 +328,10 @@
|
|||
'libraries': [ 'ws2_32.lib' ]
|
||||
}, { # POSIX
|
||||
'defines': [ '_GNU_SOURCE' ],
|
||||
'ldflags': [ '-pthread' ],
|
||||
'sources': [
|
||||
'test/runner-unix.c',
|
||||
'test/runner-unix.h',
|
||||
]
|
||||
],
|
||||
}],
|
||||
[ 'OS=="solaris"', { # make test-fs.c compile, needs _POSIX_C_SOURCE
|
||||
'defines': [
|
||||
|
|
@ -365,7 +379,6 @@
|
|||
'libraries': [ 'ws2_32.lib' ]
|
||||
}, { # POSIX
|
||||
'defines': [ '_GNU_SOURCE' ],
|
||||
'ldflags': [ '-pthread' ],
|
||||
'sources': [
|
||||
'test/runner-unix.c',
|
||||
'test/runner-unix.h',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue