John Marino <marino@FreeBSD.org>
Alexey Melnichuk <mimir@newmail.ru>
Johan Bergström <bugs@bergstroem.nu>
+Alex Mo <almosnow@gmail.com>
+Luis Martinez de Bartolome <lasote@gmail.com>
+2015.01.29, Version 1.3.0 (Stable), 165685b2a9a42cf96501d79cd6d48a18aaa16e3b
+
+Changes since version 1.2.1:
+
+* unix, windows: set non-block mode in uv_poll_init (Saúl Ibarra Corretgé)
+
+* doc: clarify which flags are supported in uv_fs_event_start (Saúl Ibarra
+ Corretgé)
+
+* win,unix: move loop functions which have identical implementations (Andrius
+ Bentkus)
+
+* doc: explain how the threadpool is allocated (Alex Mo)
+
+* doc: clarify uv_default_loop (Saúl Ibarra Corretgé)
+
+* unix: fix implicit declaration compiler warning (Ben Noordhuis)
+
+* unix: fix long line introduced in commit 94e628fa (Ben Noordhuis)
+
+* unix, win: add synchronous uv_get{addr,name}info (Saúl Ibarra Corretgé)
+
+* linux: fix epoll_pwait() regression with < 2.6.19 (Ben Noordhuis)
+
+* build: compile -D_GNU_SOURCE on linux (Ben Noordhuis)
+
+* build: use -fvisibility=hidden in autotools build (Ben Noordhuis)
+
+* fs, pipe: no trailing terminator in exact sized buffers (Andrius Bentkus)
+
+* style: rename buf to buffer and len to size for consistency (Andrius Bentkus)
+
+* test: fix test-spawn on MinGW32 (Luis Martinez de Bartolome)
+
+* win, pipe: fix assertion when destroying timer (Andrius Bentkus)
+
+* win, unix: add pipe_peername implementation (Andrius Bentkus)
+
+
+2015.01.29, Version 0.10.33 (Stable), 7a2253d33ad8215a26c1b34f1952aee7242dd687
+
+Changes since version 0.10.32:
+
+* linux: fix epoll_pwait() regression with < 2.6.19 (Ben Noordhuis)
+
+* test: back-port uv_loop_configure() test (Ben Noordhuis)
+
+
2015.01.15, Version 1.2.1 (Stable), 4ca78e989062a1099dc4b9ad182a98e8374134b1
Changes since version 1.2.0:
if LINUX
include_HEADERS += include/uv-linux.h
+libuv_la_CFLAGS += -D_GNU_SOURCE
libuv_la_SOURCES += src/unix/linux-core.c \
src/unix/linux-inotify.c \
src/unix/linux-syscalls.c \
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
AC_PREREQ(2.57)
-AC_INIT([libuv], [1.2.1], [https://github.com/libuv/libuv/issues])
+AC_INIT([libuv], [1.3.0], [https://github.com/libuv/libuv/issues])
AC_CONFIG_MACRO_DIR([m4])
m4_include([m4/libuv-extra-automake-flags.m4])
m4_include([m4/as_case.m4])
AC_ENABLE_STATIC
AC_PROG_CC
AM_PROG_CC_C_O
+CC_CHECK_CFLAGS_APPEND([-fvisibility=hidden])
CC_CHECK_CFLAGS_APPEND([-g])
CC_CHECK_CFLAGS_APPEND([-std=gnu89])
CC_CHECK_CFLAGS_APPEND([-pedantic])
Loop that started this getaddrinfo request and where completion will be
reported. Readonly.
+.. c:member:: struct addrinfo* uv_getaddrinfo_t.addrinfo
+
+ Pointer to a `struct addrinfo` containing the result. Must be freed by the user
+ with :c:func:`uv_freeaddrinfo`.
+
+ .. versionchanged:: 1.3.0 the field is declared as public.
+
.. c:member:: uv_loop_t* uv_getnameinfo_t.loop
Loop that started this getnameinfo request and where completion will be
Call :c:func:`uv_freeaddrinfo` to free the addrinfo structure.
+ .. versionchanged:: 1.3.0 the callback parameter is now allowed to be NULL,
+ in which case the request will run **synchronously**.
+
.. c:function:: void uv_freeaddrinfo(struct addrinfo* ai)
Free the struct addrinfo. Passing NULL is allowed and is a no-op.
callback will get called sometime in the future with the lookup result.
Consult `man -s 3 getnameinfo` for more details.
+ .. versionchanged:: 1.3.0 the callback parameter is now allowed to be NULL,
+ in which case the request will run **synchronously**.
+
.. seealso:: The :c:type:`uv_req_t` API functions also apply.
Start the handle with the given callback, which will watch the specified
`path` for changes. `flags` can be an ORed mask of :c:type:`uv_fs_event_flags`.
+ .. note:: Currently the only supported flag is ``UV_FS_EVENT_RECURSIVE`` and
+ only on OSX.
+
.. c:function:: int uv_fs_event_stop(uv_fs_event_t* handle)
Stop the handle, the callback will no longer be called.
-.. c:function:: int uv_fs_event_getpath(uv_fs_event_t* handle, char* buf, size_t* len)
+.. c:function:: int uv_fs_event_getpath(uv_fs_event_t* handle, char* buffer, size_t* size)
Get the path being monitored by the handle. The buffer must be preallocated
by the user. Returns 0 on success or an error code < 0 in case of failure.
- On success, `buf` will contain the path and `len` its length. If the buffer
+ On success, `buffer` will contain the path and `size` its length. If the buffer
is not big enough UV_ENOBUFS will be returned and len will be set to the
required size.
+ .. versionchanged:: 1.3.0 the returned length no longer includes the terminating null byte,
+ and the buffer is not null terminated.
+
.. seealso:: The :c:type:`uv_handle_t` API functions also apply.
Stop the handle, the callback will no longer be called.
-.. c:function:: int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buf, size_t* len)
+.. c:function:: int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buffer, size_t* size)
Get the path being monitored by the handle. The buffer must be preallocated
by the user. Returns 0 on success or an error code < 0 in case of failure.
- On success, `buf` will contain the path and `len` its length. If the buffer
+ On success, `buffer` will contain the path and `size` its length. If the buffer
is not big enough UV_ENOBUFS will be returned and len will be set to the
required size.
+ .. versionchanged:: 1.3.0 the returned length no longer includes the terminating null byte,
+ and the buffer is not null terminated.
+
.. seealso:: The :c:type:`uv_handle_t` API functions also apply.
Returns the initialized default loop. It may return NULL in case of
allocation failure.
+ This function is just a convenient way for having a global loop throughout
+ an application, the default loop is in no way different than the ones
+ initialized with :c:func:`uv_loop_init`. As such, the default loop can (and
+ should) be closed with :c:func:`uv_loop_close` so the resources associated
+ with it are freed.
+
.. c:function:: int uv_run(uv_loop_t* loop, uv_run_mode mode)
This function runs the event loop. It will act differently depending on the
Paths on Unix get truncated to ``sizeof(sockaddr_un.sun_path)`` bytes, typically between
92 and 108 bytes.
-.. c:function:: int uv_pipe_getsockname(const uv_pipe_t* handle, char* buf, size_t* len)
+.. c:function:: int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size)
Get the name of the Unix domain socket or the named pipe.
- A preallocated buffer must be provided. The len parameter holds the length
+ A preallocated buffer must be provided. The size parameter holds the length
of the buffer and it's set to the number of bytes written to the buffer on
output. If the buffer is not big enough ``UV_ENOBUFS`` will be returned and
len will contain the required size.
+ .. versionchanged:: 1.3.0 the returned length no longer includes the terminating null byte,
+ and the buffer is not null terminated.
+
+.. c:function:: int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size)
+
+ Get the name of the Unix domain socket or the named pipe to which the handle
+ is connected.
+
+ A preallocated buffer must be provided. The size parameter holds the length
+ of the buffer and it's set to the number of bytes written to the buffer on
+ output. If the buffer is not big enough ``UV_ENOBUFS`` will be returned and
+ len will contain the required size.
+
+ .. versionadded:: 1.3.0
+
.. c:function:: void uv_pipe_pending_instances(uv_pipe_t* handle, int count)
Set the number of pending pipe instance handles when the pipe server is
Initialize the handle using a file descriptor.
+ .. versionchanged:: 1.2.2 the file descriptor is set to non-blocking mode.
+
.. c:function:: int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle, uv_os_sock_t socket)
Initialize the handle using a socket descriptor. On Unix this is identical
to :c:func:`uv_poll_init`. On windows it takes a SOCKET handle.
+ .. versionchanged:: 1.2.2 the socket is set to non-blocking mode.
+
.. c:function:: int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb cb)
Starts polling the file descriptor. `events` is a bitmask consisting made up
``UV_THREADPOOL_SIZE`` environment variable to any value (the absolute maximum
is 128).
-The threadpool is global and shared across all event loops.
+The threadpool is global and shared across all event loops. When a particular
+function makes use of the threadpool (i.e. when using :c:func:`uv_queue_work`)
+libuv preallocates and initializes the maximum number of threads allowed by
+``UV_THREADPOOL_SIZE``. This causes a relatively minor memory overhead
+(~1MB for 128 threads) but increases the performance of threading at runtime.
Data types
struct addrinfo* hints; \
char* hostname; \
char* service; \
- struct addrinfo* res; \
+ struct addrinfo* addrinfo; \
int retcode;
#define UV_GETNAMEINFO_PRIVATE_FIELDS \
*/
#define UV_VERSION_MAJOR 1
-#define UV_VERSION_MINOR 2
-#define UV_VERSION_PATCH 1
+#define UV_VERSION_MINOR 3
+#define UV_VERSION_PATCH 0
#define UV_VERSION_IS_RELEASE 1
#define UV_VERSION_SUFFIX ""
void* alloc; \
WCHAR* node; \
WCHAR* service; \
- struct addrinfoW* hints; \
- struct addrinfoW* res; \
+ /* The addrinfoW field is used to store a pointer to the hints, and */ \
+ /* later on to store the result of GetAddrInfoW. The final result will */ \
+ /* be converted to struct addrinfo* and stored in the addrinfo field. */ \
+ struct addrinfoW* addrinfow; \
+ struct addrinfo* addrinfo; \
int retcode;
#define UV_GETNAMEINFO_PRIVATE_FIELDS \
const char* name,
uv_connect_cb cb);
UV_EXTERN int uv_pipe_getsockname(const uv_pipe_t* handle,
- char* buf,
- size_t* len);
+ char* buffer,
+ size_t* size);
+UV_EXTERN int uv_pipe_getpeername(const uv_pipe_t* handle,
+ char* buffer,
+ size_t* size);
UV_EXTERN void uv_pipe_pending_instances(uv_pipe_t* handle, int count);
UV_EXTERN int uv_pipe_pending_count(uv_pipe_t* handle);
UV_EXTERN uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle);
UV_REQ_FIELDS
/* read-only */
uv_loop_t* loop;
+ /* struct addrinfo* addrinfo is marked as private, but it really isn't. */
UV_GETADDRINFO_PRIVATE_FIELDS
};
const char* path,
unsigned int interval);
UV_EXTERN int uv_fs_poll_stop(uv_fs_poll_t* handle);
-UV_EXTERN int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buf, size_t* len);
+UV_EXTERN int uv_fs_poll_getpath(uv_fs_poll_t* handle,
+ char* buffer,
+ size_t* size);
struct uv_signal_s {
unsigned int flags);
UV_EXTERN int uv_fs_event_stop(uv_fs_event_t* handle);
UV_EXTERN int uv_fs_event_getpath(uv_fs_event_t* handle,
- char* buf,
- size_t* len);
+ char* buffer,
+ size_t* size);
UV_EXTERN int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr);
UV_EXTERN int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr);
}
-int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buf, size_t* len) {
+int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buffer, size_t* size) {
struct poll_ctx* ctx;
size_t required_len;
if (!uv__is_active(handle)) {
- *len = 0;
+ *size = 0;
return UV_EINVAL;
}
ctx = handle->poll_ctx;
assert(ctx != NULL);
- required_len = strlen(ctx->path) + 1;
- if (required_len > *len) {
- *len = required_len;
+ required_len = strlen(ctx->path);
+ if (required_len > *size) {
+ *size = required_len;
return UV_ENOBUFS;
}
- memcpy(buf, ctx->path, required_len);
- *len = required_len;
+ memcpy(buffer, ctx->path, required_len);
+ *size = required_len;
return 0;
}
#define RDWR_BUF_SIZE 4096
#define EQ(a,b) (strcmp(a,b) == 0)
-int uv__platform_loop_init(uv_loop_t* loop, int default_loop) {
+int uv__platform_loop_init(uv_loop_t* loop) {
loop->fs_fd = -1;
/* Passing maxfd of -1 should mean the limit is determined
#include <dlfcn.h>
#include <errno.h>
#include <stdlib.h>
+#include <string.h>
#include <TargetConditionals.h>
int err;
/* pthread_setname_np() first appeared in OS X 10.6 and iOS 3.2. */
- *(void **)(&dynamic_pthread_setname_np) = dlsym(RTLD_DEFAULT, "pthread_setname_np");
+ *(void **)(&dynamic_pthread_setname_np) =
+ dlsym(RTLD_DEFAULT, "pthread_setname_np");
+
if (dynamic_pthread_setname_np == NULL)
return -ENOSYS;
#include <unistd.h> /* sysconf */
-int uv__platform_loop_init(uv_loop_t* loop, int default_loop) {
+int uv__platform_loop_init(uv_loop_t* loop) {
loop->cf_state = NULL;
if (uv__kqueue_init(loop))
static char *process_title;
-int uv__platform_loop_init(uv_loop_t* loop, int default_loop) {
+int uv__platform_loop_init(uv_loop_t* loop) {
return uv__kqueue_init(loop);
}
int err;
req = container_of(w, uv_getaddrinfo_t, work_req);
- err = getaddrinfo(req->hostname, req->service, req->hints, &req->res);
+ err = getaddrinfo(req->hostname, req->service, req->hints, &req->addrinfo);
req->retcode = uv__getaddrinfo_translate_error(err);
}
static void uv__getaddrinfo_done(struct uv__work* w, int status) {
uv_getaddrinfo_t* req;
- struct addrinfo *res;
req = container_of(w, uv_getaddrinfo_t, work_req);
uv__req_unregister(req->loop, req);
- res = req->res;
- req->res = NULL;
-
/* See initialization in uv_getaddrinfo(). */
if (req->hints)
free(req->hints);
req->retcode = UV_EAI_CANCELED;
}
- req->cb(req, req->retcode, res);
+ if (req->cb)
+ req->cb(req, req->retcode, req->addrinfo);
}
size_t len;
char* buf;
- if (req == NULL || cb == NULL || (hostname == NULL && service == NULL))
+ if (req == NULL || (hostname == NULL && service == NULL))
return -EINVAL;
hostname_len = hostname ? strlen(hostname) + 1 : 0;
uv__req_init(loop, req, UV_GETADDRINFO);
req->loop = loop;
req->cb = cb;
- req->res = NULL;
+ req->addrinfo = NULL;
req->hints = NULL;
req->service = NULL;
req->hostname = NULL;
if (hostname)
req->hostname = memcpy(buf + len, hostname, hostname_len);
- uv__work_submit(loop,
- &req->work_req,
- uv__getaddrinfo_work,
- uv__getaddrinfo_done);
-
- return 0;
+ if (cb) {
+ uv__work_submit(loop,
+ &req->work_req,
+ uv__getaddrinfo_work,
+ uv__getaddrinfo_done);
+ return 0;
+ } else {
+ uv__getaddrinfo_work(&req->work_req);
+ uv__getaddrinfo_done(&req->work_req, 0);
+ return req->retcode;
+ }
}
service = req->service;
}
- req->getnameinfo_cb(req, req->retcode, host, service);
+ if (req->getnameinfo_cb)
+ req->getnameinfo_cb(req, req->retcode, host, service);
}
/*
uv_getnameinfo_cb getnameinfo_cb,
const struct sockaddr* addr,
int flags) {
- if (req == NULL || getnameinfo_cb == NULL || addr == NULL)
+ if (req == NULL || addr == NULL)
return UV_EINVAL;
if (addr->sa_family == AF_INET) {
req->loop = loop;
req->retcode = 0;
- uv__work_submit(loop,
- &req->work_req,
- uv__getnameinfo_work,
- uv__getnameinfo_done);
-
- return 0;
+ if (getnameinfo_cb) {
+ uv__work_submit(loop,
+ &req->work_req,
+ uv__getnameinfo_work,
+ uv__getnameinfo_done);
+ return 0;
+ } else {
+ uv__getnameinfo_work(&req->work_req);
+ uv__getnameinfo_done(&req->work_req, 0);
+ return req->retcode;
+ }
}
/* platform specific */
uint64_t uv__hrtime(uv_clocktype_t type);
int uv__kqueue_init(uv_loop_t* loop);
-int uv__platform_loop_init(uv_loop_t* loop, int default_loop);
+int uv__platform_loop_init(uv_loop_t* loop);
void uv__platform_loop_delete(uv_loop_t* loop);
void uv__platform_invalidate_fd(uv_loop_t* loop, int fd);
static unsigned long read_cpufreq(unsigned int cpunum);
-int uv__platform_loop_init(uv_loop_t* loop, int default_loop) {
+int uv__platform_loop_init(uv_loop_t* loop) {
int fd;
fd = uv__epoll_create1(UV__EPOLL_CLOEXEC);
void uv__io_poll(uv_loop_t* loop, int timeout) {
+ static int no_epoll_pwait;
+ static int no_epoll_wait;
struct uv__epoll_event events[1024];
struct uv__epoll_event* pe;
struct uv__epoll_event e;
QUEUE* q;
uv__io_t* w;
+ sigset_t sigset;
uint64_t sigmask;
uint64_t base;
uint64_t diff;
int fd;
int op;
int i;
- static int no_epoll_wait;
if (loop->nfds == 0) {
assert(QUEUE_EMPTY(&loop->watcher_queue));
}
sigmask = 0;
- if (loop->flags & UV_LOOP_BLOCK_SIGPROF)
+ if (loop->flags & UV_LOOP_BLOCK_SIGPROF) {
+ sigemptyset(&sigset);
+ sigaddset(&sigset, SIGPROF);
sigmask |= 1 << (SIGPROF - 1);
+ }
assert(timeout >= -1);
base = loop->time;
count = 48; /* Benchmarks suggest this gives the best throughput. */
for (;;) {
- if (no_epoll_wait || sigmask) {
+ if (sigmask != 0 && no_epoll_pwait != 0)
+ if (pthread_sigmask(SIG_BLOCK, &sigset, NULL))
+ abort();
+
+ if (sigmask != 0 && no_epoll_pwait == 0) {
nfds = uv__epoll_pwait(loop->backend_fd,
events,
ARRAY_SIZE(events),
timeout,
sigmask);
+ if (nfds == -1 && errno == ENOSYS)
+ no_epoll_pwait = 1;
} else {
nfds = uv__epoll_wait(loop->backend_fd,
events,
ARRAY_SIZE(events),
timeout);
- if (nfds == -1 && errno == ENOSYS) {
+ if (nfds == -1 && errno == ENOSYS)
no_epoll_wait = 1;
- continue;
- }
}
+ if (sigmask != 0 && no_epoll_pwait != 0)
+ if (pthread_sigmask(SIG_UNBLOCK, &sigset, NULL))
+ abort();
+
/* Update loop->time unconditionally. It's tempting to skip the update when
* timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the
* operating system didn't reschedule our process while in the syscall.
}
if (nfds == -1) {
+ if (errno == ENOSYS) {
+ /* epoll_wait() or epoll_pwait() failed, try the other system call. */
+ assert(no_epoll_wait == 0 || no_epoll_pwait == 0);
+ continue;
+ }
+
if (errno != EINTR)
abort();
#include <string.h>
#include <unistd.h>
-static int uv__loop_init(uv_loop_t* loop, int default_loop);
-static void uv__loop_close(uv_loop_t* loop);
-
-static uv_loop_t default_loop_struct;
-static uv_loop_t* default_loop_ptr;
-
-
-uv_loop_t* uv_default_loop(void) {
- if (default_loop_ptr != NULL)
- return default_loop_ptr;
-
- if (uv__loop_init(&default_loop_struct, /* default_loop? */ 1))
- return NULL;
-
- default_loop_ptr = &default_loop_struct;
- return default_loop_ptr;
-}
-
-
int uv_loop_init(uv_loop_t* loop) {
- return uv__loop_init(loop, /* default_loop? */ 0);
-}
-
-
-int uv_loop_close(uv_loop_t* loop) {
- QUEUE* q;
- uv_handle_t* h;
- if (!QUEUE_EMPTY(&(loop)->active_reqs))
- return -EBUSY;
- QUEUE_FOREACH(q, &loop->handle_queue) {
- h = QUEUE_DATA(q, uv_handle_t, handle_queue);
- if (!(h->flags & UV__HANDLE_INTERNAL))
- return -EBUSY;
- }
- uv__loop_close(loop);
-#ifndef NDEBUG
- memset(loop, -1, sizeof(*loop));
-#endif
- if (loop == default_loop_ptr)
- default_loop_ptr = NULL;
- return 0;
-}
-
-
-uv_loop_t* uv_loop_new(void) {
- uv_loop_t* loop;
-
- loop = malloc(sizeof(*loop));
- if (loop == NULL)
- return NULL;
-
- if (uv_loop_init(loop)) {
- free(loop);
- return NULL;
- }
-
- return loop;
-}
-
-
-void uv_loop_delete(uv_loop_t* loop) {
- uv_loop_t* default_loop;
- int err;
- default_loop = default_loop_ptr;
- err = uv_loop_close(loop);
- assert(err == 0);
- if (loop != default_loop)
- free(loop);
-}
-
-
-static int uv__loop_init(uv_loop_t* loop, int default_loop) {
int err;
uv__signal_global_once_init();
loop->timer_counter = 0;
loop->stop_flag = 0;
- err = uv__platform_loop_init(loop, default_loop);
+ err = uv__platform_loop_init(loop);
if (err)
return err;
}
-static void uv__loop_close(uv_loop_t* loop) {
+void uv__loop_close(uv_loop_t* loop) {
uv__signal_loop_cleanup(loop);
uv__platform_loop_delete(loop);
uv__async_stop(loop, &loop->async_watcher);
static char *process_title;
-int uv__platform_loop_init(uv_loop_t* loop, int default_loop) {
+int uv__platform_loop_init(uv_loop_t* loop) {
return uv__kqueue_init(loop);
}
static char *process_title;
-int uv__platform_loop_init(uv_loop_t* loop, int default_loop) {
+int uv__platform_loop_init(uv_loop_t* loop) {
return uv__kqueue_init(loop);
}
}
-int uv_pipe_getsockname(const uv_pipe_t* handle, char* buf, size_t* len) {
+typedef int (*uv__peersockfunc)(int, struct sockaddr*, socklen_t*);
+
+
+static int uv__pipe_getsockpeername(const uv_pipe_t* handle,
+ uv__peersockfunc func,
+ char* buffer,
+ size_t* size) {
struct sockaddr_un sa;
socklen_t addrlen;
int err;
addrlen = sizeof(sa);
memset(&sa, 0, addrlen);
- err = getsockname(uv__stream_fd(handle), (struct sockaddr*) &sa, &addrlen);
+ err = func(uv__stream_fd(handle), (struct sockaddr*) &sa, &addrlen);
if (err < 0) {
- *len = 0;
+ *size = 0;
return -errno;
}
+#if defined(__linux__)
if (sa.sun_path[0] == 0)
/* Linux abstract namespace */
addrlen -= offsetof(struct sockaddr_un, sun_path);
else
- addrlen = strlen(sa.sun_path) + 1;
+#endif
+ addrlen = strlen(sa.sun_path);
- if (addrlen > *len) {
- *len = addrlen;
+ if (addrlen > *size) {
+ *size = addrlen;
return UV_ENOBUFS;
}
- memcpy(buf, sa.sun_path, addrlen);
- *len = addrlen;
+ memcpy(buffer, sa.sun_path, addrlen);
+ *size = addrlen;
return 0;
}
+int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) {
+ return uv__pipe_getsockpeername(handle, getsockname, buffer, size);
+}
+
+
+int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) {
+ return uv__pipe_getsockpeername(handle, getpeername, buffer, size);
+}
+
+
void uv_pipe_pending_instances(uv_pipe_t* handle, int count) {
}
int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) {
+ int err;
+
+ err = uv__nonblock(fd, 1);
+ if (err)
+ return err;
+
uv__handle_init(loop, (uv_handle_t*) handle, UV_POLL);
uv__io_init(&handle->io_watcher, uv__poll_io, fd);
handle->poll_cb = NULL;
#endif
-int uv__platform_loop_init(uv_loop_t* loop, int default_loop) {
+int uv__platform_loop_init(uv_loop_t* loop) {
int err;
int fd;
return uv__socket_sockopt(handle, SO_SNDBUF, value);
}
-int uv_fs_event_getpath(uv_fs_event_t* handle, char* buf, size_t* len) {
+int uv_fs_event_getpath(uv_fs_event_t* handle, char* buffer, size_t* size) {
size_t required_len;
if (!uv__is_active(handle)) {
- *len = 0;
+ *size = 0;
return UV_EINVAL;
}
- required_len = strlen(handle->path) + 1;
- if (required_len > *len) {
- *len = required_len;
+ required_len = strlen(handle->path);
+ if (required_len > *size) {
+ *size = required_len;
return UV_ENOBUFS;
}
- memcpy(buf, handle->path, required_len);
- *len = required_len;
+ memcpy(buffer, handle->path, required_len);
+ *size = required_len;
return 0;
}
return err;
}
+
+
+static uv_loop_t default_loop_struct;
+static uv_loop_t* default_loop_ptr;
+
+
+uv_loop_t* uv_default_loop(void) {
+ if (default_loop_ptr != NULL)
+ return default_loop_ptr;
+
+ if (uv_loop_init(&default_loop_struct))
+ return NULL;
+
+ default_loop_ptr = &default_loop_struct;
+ return default_loop_ptr;
+}
+
+
+uv_loop_t* uv_loop_new(void) {
+ uv_loop_t* loop;
+
+ loop = malloc(sizeof(*loop));
+ if (loop == NULL)
+ return NULL;
+
+ if (uv_loop_init(loop)) {
+ free(loop);
+ return NULL;
+ }
+
+ return loop;
+}
+
+
+int uv_loop_close(uv_loop_t* loop) {
+ QUEUE* q;
+ uv_handle_t* h;
+
+ if (!QUEUE_EMPTY(&(loop)->active_reqs))
+ return UV_EBUSY;
+
+ QUEUE_FOREACH(q, &loop->handle_queue) {
+ h = QUEUE_DATA(q, uv_handle_t, handle_queue);
+ if (!(h->flags & UV__HANDLE_INTERNAL))
+ return UV_EBUSY;
+ }
+
+ uv__loop_close(loop);
+
+#ifndef NDEBUG
+ memset(loop, -1, sizeof(*loop));
+#endif
+ if (loop == default_loop_ptr)
+ default_loop_ptr = NULL;
+
+ return 0;
+}
+
+
+void uv_loop_delete(uv_loop_t* loop) {
+ uv_loop_t* default_loop;
+ int err;
+
+ default_loop = default_loop_ptr;
+
+ err = uv_loop_close(loop);
+ assert(err == 0);
+ if (loop != default_loop)
+ free(loop);
+}
int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap);
+void uv__loop_close(uv_loop_t* loop);
+
int uv__tcp_bind(uv_tcp_t* tcp,
const struct sockaddr* addr,
unsigned int addrlen,
}
-uv_loop_t* uv_default_loop(void) {
- if (default_loop_ptr != NULL)
- return default_loop_ptr;
-
- if (uv_loop_init(&default_loop_struct))
- return NULL;
-
- default_loop_ptr = &default_loop_struct;
- return default_loop_ptr;
-}
-
-
-static void uv__loop_close(uv_loop_t* loop) {
+void uv__loop_close(uv_loop_t* loop) {
size_t i;
/* close the async handle without needing an extra loop iteration */
}
-int uv_loop_close(uv_loop_t* loop) {
- QUEUE* q;
- uv_handle_t* h;
- if (!QUEUE_EMPTY(&(loop)->active_reqs))
- return UV_EBUSY;
- QUEUE_FOREACH(q, &loop->handle_queue) {
- h = QUEUE_DATA(q, uv_handle_t, handle_queue);
- if (!(h->flags & UV__HANDLE_INTERNAL))
- return UV_EBUSY;
- }
-
- uv__loop_close(loop);
-
-#ifndef NDEBUG
- memset(loop, -1, sizeof(*loop));
-#endif
- if (loop == default_loop_ptr)
- default_loop_ptr = NULL;
-
- return 0;
-}
-
-
-uv_loop_t* uv_loop_new(void) {
- uv_loop_t* loop;
-
- loop = (uv_loop_t*)malloc(sizeof(uv_loop_t));
- if (loop == NULL) {
- return NULL;
- }
-
- if (uv_loop_init(loop)) {
- free(loop);
- return NULL;
- }
-
- return loop;
-}
-
-
-void uv_loop_delete(uv_loop_t* loop) {
- uv_loop_t* default_loop;
- int err;
- default_loop = default_loop_ptr;
- err = uv_loop_close(loop);
- assert(err == 0);
- if (loop != default_loop)
- free(loop);
-}
-
-
int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap) {
return UV_ENOSYS;
}
static void uv__getaddrinfo_work(struct uv__work* w) {
uv_getaddrinfo_t* req;
+ struct addrinfoW* hints;
int err;
req = container_of(w, uv_getaddrinfo_t, work_req);
- err = GetAddrInfoW(req->node, req->service, req->hints, &req->res);
+ hints = req->addrinfow;
+ req->addrinfow = NULL;
+ err = GetAddrInfoW(req->node, req->service, hints, &req->addrinfow);
req->retcode = uv__getaddrinfo_translate_error(err);
}
if (status == UV_ECANCELED) {
assert(req->retcode == 0);
req->retcode = UV_EAI_CANCELED;
- if (req->res != NULL) {
- FreeAddrInfoW(req->res);
- req->res = NULL;
- }
goto complete;
}
if (req->retcode == 0) {
/* convert addrinfoW to addrinfo */
/* first calculate required length */
- addrinfow_ptr = req->res;
+ addrinfow_ptr = req->addrinfow;
while (addrinfow_ptr != NULL) {
addrinfo_len += addrinfo_struct_len +
ALIGNED_SIZE(addrinfow_ptr->ai_addrlen);
/* do conversions */
if (alloc_ptr != NULL) {
cur_ptr = alloc_ptr;
- addrinfow_ptr = req->res;
+ addrinfow_ptr = req->addrinfow;
while (addrinfow_ptr != NULL) {
/* copy addrinfo struct data */
addrinfo_ptr->ai_next = (struct addrinfo*)cur_ptr;
}
}
+ req->addrinfo = (struct addrinfo*)alloc_ptr;
} else {
req->retcode = UV_EAI_MEMORY;
}
}
/* return memory to system */
- if (req->res != NULL) {
- FreeAddrInfoW(req->res);
- req->res = NULL;
+ if (req->addrinfow != NULL) {
+ FreeAddrInfoW(req->addrinfow);
+ req->addrinfow = NULL;
}
complete:
uv__req_unregister(req->loop, req);
/* finally do callback with converted result */
- req->getaddrinfo_cb(req, req->retcode, (struct addrinfo*)alloc_ptr);
+ if (req->getaddrinfo_cb)
+ req->getaddrinfo_cb(req, req->retcode, req->addrinfo);
}
char* alloc_ptr = NULL;
int err;
- if (req == NULL || getaddrinfo_cb == NULL ||
- (node == NULL && service == NULL)) {
+ if (req == NULL || (node == NULL && service == NULL)) {
err = WSAEINVAL;
goto error;
}
uv_req_init(loop, (uv_req_t*)req);
req->getaddrinfo_cb = getaddrinfo_cb;
- req->res = NULL;
+ req->addrinfo = NULL;
req->type = UV_GETADDRINFO;
req->loop = loop;
req->retcode = 0;
/* copy hints to allocated memory and save pointer in req */
if (hints != NULL) {
- req->hints = (struct addrinfoW*)alloc_ptr;
- req->hints->ai_family = hints->ai_family;
- req->hints->ai_socktype = hints->ai_socktype;
- req->hints->ai_protocol = hints->ai_protocol;
- req->hints->ai_flags = hints->ai_flags;
- req->hints->ai_addrlen = 0;
- req->hints->ai_canonname = NULL;
- req->hints->ai_addr = NULL;
- req->hints->ai_next = NULL;
+ req->addrinfow = (struct addrinfoW*)alloc_ptr;
+ req->addrinfow->ai_family = hints->ai_family;
+ req->addrinfow->ai_socktype = hints->ai_socktype;
+ req->addrinfow->ai_protocol = hints->ai_protocol;
+ req->addrinfow->ai_flags = hints->ai_flags;
+ req->addrinfow->ai_addrlen = 0;
+ req->addrinfow->ai_canonname = NULL;
+ req->addrinfow->ai_addr = NULL;
+ req->addrinfow->ai_next = NULL;
} else {
- req->hints = NULL;
+ req->addrinfow = NULL;
}
- uv__work_submit(loop,
- &req->work_req,
- uv__getaddrinfo_work,
- uv__getaddrinfo_done);
-
uv__req_register(loop, req);
- return 0;
+ if (getaddrinfo_cb) {
+ uv__work_submit(loop,
+ &req->work_req,
+ uv__getaddrinfo_work,
+ uv__getaddrinfo_done);
+ return 0;
+ } else {
+ uv__getaddrinfo_work(&req->work_req);
+ uv__getaddrinfo_done(&req->work_req, 0);
+ return req->retcode;
+ }
error:
if (req != NULL && req->alloc != NULL) {
service = req->service;
}
- req->getnameinfo_cb(req, req->retcode, host, service);
+ if (req->getnameinfo_cb)
+ req->getnameinfo_cb(req, req->retcode, host, service);
}
uv_getnameinfo_cb getnameinfo_cb,
const struct sockaddr* addr,
int flags) {
- if (req == NULL || getnameinfo_cb == NULL || addr == NULL)
+ if (req == NULL || addr == NULL)
return UV_EINVAL;
if (addr->sa_family == AF_INET) {
req->loop = loop;
req->retcode = 0;
- uv__work_submit(loop,
- &req->work_req,
- uv__getnameinfo_work,
- uv__getnameinfo_done);
-
- return 0;
+ if (getnameinfo_cb) {
+ uv__work_submit(loop,
+ &req->work_req,
+ uv__getnameinfo_work,
+ uv__getnameinfo_done);
+ return 0;
+ } else {
+ uv__getnameinfo_work(&req->work_req);
+ uv__getnameinfo_done(&req->work_req, 0);
+ return req->retcode;
+ }
}
static void eof_timer_destroy(uv_pipe_t* pipe) {
- assert(pipe->flags && UV_HANDLE_CONNECTION);
+ assert(pipe->flags & UV_HANDLE_CONNECTION);
if (pipe->eof_timer) {
uv_close((uv_handle_t*) pipe->eof_timer, eof_timer_close_cb);
}
-int uv_pipe_getsockname(const uv_pipe_t* handle, char* buf, size_t* len) {
+static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size) {
NTSTATUS nt_status;
IO_STATUS_BLOCK io_status;
FILE_NAME_INFORMATION tmp_name_info;
name_info = NULL;
if (handle->handle == INVALID_HANDLE_VALUE) {
- *len = 0;
+ *size = 0;
return UV_EINVAL;
}
name_size = sizeof(*name_info) + tmp_name_info.FileNameLength;
name_info = malloc(name_size);
if (!name_info) {
- *len = 0;
+ *size = 0;
err = UV_ENOMEM;
goto cleanup;
}
}
if (nt_status != STATUS_SUCCESS) {
- *len = 0;
+ *size = 0;
err = uv_translate_sys_error(pRtlNtStatusToDosError(nt_status));
goto error;
}
}
if (name_len == 0) {
- *len = 0;
+ *size = 0;
err = 0;
goto error;
}
NULL,
NULL);
if (!addrlen) {
- *len = 0;
+ *size = 0;
err = uv_translate_sys_error(GetLastError());
goto error;
- } else if (pipe_prefix_len + addrlen + 1 > *len) {
- /* "\\\\.\\pipe" + name + '\0' */
- *len = pipe_prefix_len + addrlen + 1;
+ } else if (pipe_prefix_len + addrlen > *size) {
+ /* "\\\\.\\pipe" + name */
+ *size = pipe_prefix_len + addrlen;
err = UV_ENOBUFS;
goto error;
}
- memcpy(buf, pipe_prefix, pipe_prefix_len);
+ memcpy(buffer, pipe_prefix, pipe_prefix_len);
addrlen = WideCharToMultiByte(CP_UTF8,
0,
name_buf,
name_len,
- buf+pipe_prefix_len,
- *len-pipe_prefix_len,
+ buffer+pipe_prefix_len,
+ *size-pipe_prefix_len,
NULL,
NULL);
if (!addrlen) {
- *len = 0;
+ *size = 0;
err = uv_translate_sys_error(GetLastError());
goto error;
}
addrlen += pipe_prefix_len;
- buf[addrlen++] = '\0';
- *len = addrlen;
+ *size = addrlen;
err = 0;
goto cleanup;
}
+int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) {
+ if (handle->flags & UV_HANDLE_BOUND)
+ return uv__pipe_getname(handle, buffer, size);
+
+ if (handle->flags & UV_HANDLE_CONNECTION ||
+ handle->handle != INVALID_HANDLE_VALUE) {
+ *size = 0;
+ return 0;
+ }
+
+ return UV_EBADF;
+}
+
+
+int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) {
+ /* emulate unix behaviour */
+ if (handle->flags & UV_HANDLE_BOUND)
+ return UV_ENOTCONN;
+
+ if (handle->handle != INVALID_HANDLE_VALUE)
+ return uv__pipe_getname(handle, buffer, size);
+
+ return UV_EBADF;
+}
+
+
uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) {
if (!handle->ipc)
return UV_UNKNOWN_HANDLE;
int len;
SOCKET peer_socket, base_socket;
DWORD bytes;
+ DWORD yes = 1;
+
+ /* Set the socket to nonblocking mode */
+ if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR)
+ return uv_translate_sys_error(WSAGetLastError());
/* Try to obtain a base handle for the socket. This increases this chances */
/* that we find an AFD handle and are able to use the fast poll mechanism. */
len = sizeof buf;
r = uv_fs_event_getpath(&fs_event, buf, &len);
ASSERT(r == 0);
+ ASSERT(buf[len - 1] != 0);
ASSERT(memcmp(buf, "watch_dir", len) == 0);
r = uv_fs_event_stop(&fs_event);
ASSERT(r == 0);
ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb_fail, FIXTURE, 100));
len = sizeof buf;
ASSERT(0 == uv_fs_poll_getpath(&poll_handle, buf, &len));
+ ASSERT(buf[len - 1] != 0);
ASSERT(0 == memcmp(buf, FIXTURE, len));
uv_close((uv_handle_t*) &poll_handle, close_cb);
}
+TEST_IMPL(getaddrinfo_fail_sync) {
+ uv_getaddrinfo_t req;
+
+ ASSERT(0 > uv_getaddrinfo(uv_default_loop(),
+ &req,
+ NULL,
+ "xyzzy.xyzzy.xyzzy",
+ NULL,
+ NULL));
+ uv_freeaddrinfo(req.addrinfo);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+
TEST_IMPL(getaddrinfo_basic) {
int r;
getaddrinfo_handle = (uv_getaddrinfo_t*)malloc(sizeof(uv_getaddrinfo_t));
}
+TEST_IMPL(getaddrinfo_basic_sync) {
+ uv_getaddrinfo_t req;
+
+ ASSERT(0 == uv_getaddrinfo(uv_default_loop(),
+ &req,
+ NULL,
+ name,
+ NULL,
+ NULL));
+ uv_freeaddrinfo(req.addrinfo);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+
TEST_IMPL(getaddrinfo_concurrent) {
int i, r;
int* data;
ASSERT(service != NULL);
}
+
TEST_IMPL(getnameinfo_basic_ip4) {
int r;
return 0;
}
+
+TEST_IMPL(getnameinfo_basic_ip4_sync) {
+ ASSERT(0 == uv_ip4_addr(address_ip4, port, &addr4));
+
+ ASSERT(0 == uv_getnameinfo(uv_default_loop(),
+ &req,
+ NULL,
+ (const struct sockaddr*)&addr4,
+ 0));
+ ASSERT(req.host != NULL);
+ ASSERT(req.service != NULL);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+
TEST_IMPL(getnameinfo_basic_ip6) {
int r;
TEST_DECLARE (handle_fileno)
TEST_DECLARE (hrtime)
TEST_DECLARE (getaddrinfo_fail)
+TEST_DECLARE (getaddrinfo_fail_sync)
TEST_DECLARE (getaddrinfo_basic)
+TEST_DECLARE (getaddrinfo_basic_sync)
TEST_DECLARE (getaddrinfo_concurrent)
TEST_DECLARE (getnameinfo_basic_ip4)
+TEST_DECLARE (getnameinfo_basic_ip4_sync)
TEST_DECLARE (getnameinfo_basic_ip6)
TEST_DECLARE (getsockname_tcp)
TEST_DECLARE (getsockname_udp)
TEST_ENTRY (hrtime)
TEST_ENTRY_CUSTOM (getaddrinfo_fail, 0, 0, 10000)
+ TEST_ENTRY (getaddrinfo_fail_sync)
TEST_ENTRY (getaddrinfo_basic)
+ TEST_ENTRY (getaddrinfo_basic_sync)
TEST_ENTRY (getaddrinfo_concurrent)
TEST_ENTRY (getnameinfo_basic_ip4)
+ TEST_ENTRY (getnameinfo_basic_ip4_sync)
TEST_ENTRY (getnameinfo_basic_ip6)
TEST_ENTRY (getsockname_tcp)
# include <fcntl.h>
#endif
+static uv_pipe_t pipe_client;
+static uv_pipe_t pipe_server;
+static uv_connect_t connect_req;
-static int close_cb_called = 0;
+static int pipe_close_cb_called = 0;
+static int pipe_client_connect_cb_called = 0;
-static void close_cb(uv_handle_t* handle) {
- ASSERT(handle != NULL);
- close_cb_called++;
+static void pipe_close_cb(uv_handle_t* handle) {
+ ASSERT(handle == (uv_handle_t*) &pipe_client ||
+ handle == (uv_handle_t*) &pipe_server);
+ pipe_close_cb_called++;
+}
+
+
+static void pipe_client_connect_cb(uv_connect_t* req, int status) {
+ char buf[1024];
+ size_t len;
+ int r;
+
+ ASSERT(req == &connect_req);
+ ASSERT(status == 0);
+
+ len = sizeof buf;
+ r = uv_pipe_getpeername(&pipe_client, buf, &len);
+ ASSERT(r == 0);
+
+ ASSERT(buf[len - 1] != 0);
+ ASSERT(memcmp(buf, TEST_PIPENAME, len) == 0);
+
+ len = sizeof buf;
+ r = uv_pipe_getsockname(&pipe_client, buf, &len);
+ ASSERT(r == 0 && len == 0);
+
+ pipe_client_connect_cb_called++;
+
+
+ uv_close((uv_handle_t*) &pipe_client, pipe_close_cb);
+ uv_close((uv_handle_t*) &pipe_server, pipe_close_cb);
+}
+
+
+static void pipe_server_connection_cb(uv_stream_t* handle, int status) {
+ /* This function *may* be called, depending on whether accept or the
+ * connection callback is called first.
+ */
+ ASSERT(status == 0);
}
TEST_IMPL(pipe_getsockname) {
- uv_pipe_t server;
+ uv_loop_t* loop;
char buf[1024];
size_t len;
int r;
- r = uv_pipe_init(uv_default_loop(), &server, 0);
+ loop = uv_default_loop();
+ ASSERT(loop != NULL);
+
+ r = uv_pipe_init(loop, &pipe_server, 0);
ASSERT(r == 0);
- r = uv_pipe_bind(&server, TEST_PIPENAME);
+
+ len = sizeof buf;
+ r = uv_pipe_getsockname(&pipe_server, buf, &len);
+ ASSERT(r == UV_EBADF);
+
+ len = sizeof buf;
+ r = uv_pipe_getpeername(&pipe_server, buf, &len);
+ ASSERT(r == UV_EBADF);
+
+ r = uv_pipe_bind(&pipe_server, TEST_PIPENAME);
ASSERT(r == 0);
len = sizeof buf;
- r = uv_pipe_getsockname(&server, buf, &len);
+ r = uv_pipe_getsockname(&pipe_server, buf, &len);
ASSERT(r == 0);
+ ASSERT(buf[len - 1] != 0);
ASSERT(memcmp(buf, TEST_PIPENAME, len) == 0);
- uv_close((uv_handle_t*)&server, close_cb);
+ len = sizeof buf;
+ r = uv_pipe_getpeername(&pipe_server, buf, &len);
+ ASSERT(r == UV_ENOTCONN);
- uv_run(uv_default_loop(), UV_RUN_DEFAULT);
+ r = uv_listen((uv_stream_t*) &pipe_server, 0, pipe_server_connection_cb);
+ ASSERT(r == 0);
+
+ r = uv_pipe_init(loop, &pipe_client, 0);
+ ASSERT(r == 0);
+
+ len = sizeof buf;
+ r = uv_pipe_getsockname(&pipe_client, buf, &len);
+ ASSERT(r == UV_EBADF);
- ASSERT(close_cb_called == 1);
+ len = sizeof buf;
+ r = uv_pipe_getpeername(&pipe_client, buf, &len);
+ ASSERT(r == UV_EBADF);
+
+ uv_pipe_connect(&connect_req, &pipe_client, TEST_PIPENAME, pipe_client_connect_cb);
+
+ len = sizeof buf;
+ r = uv_pipe_getsockname(&pipe_client, buf, &len);
+ ASSERT(r == 0 && len == 0);
+
+ len = sizeof buf;
+ r = uv_pipe_getpeername(&pipe_client, buf, &len);
+ ASSERT(r == 0);
+
+ ASSERT(buf[len - 1] != 0);
+ ASSERT(memcmp(buf, TEST_PIPENAME, len) == 0);
+
+ r = uv_run(loop, UV_RUN_DEFAULT);
+ ASSERT(r == 0);
+ ASSERT(pipe_client_connect_cb_called == 1);
+ ASSERT(pipe_close_cb_called == 2);
MAKE_VALGRIND_HAPPY();
return 0;
TEST_IMPL(pipe_getsockname_abstract) {
#if defined(__linux__)
- uv_pipe_t server;
char buf[1024];
size_t len;
int r;
r = bind(sock, (struct sockaddr*)&sun, sun_len);
ASSERT(r == 0);
- r = uv_pipe_init(uv_default_loop(), &server, 0);
+ r = uv_pipe_init(uv_default_loop(), &pipe_server, 0);
ASSERT(r == 0);
- r = uv_pipe_open(&server, sock);
+ r = uv_pipe_open(&pipe_server, sock);
ASSERT(r == 0);
len = sizeof buf;
- r = uv_pipe_getsockname(&server, buf, &len);
+ r = uv_pipe_getsockname(&pipe_server, buf, &len);
ASSERT(r == 0);
ASSERT(memcmp(buf, abstract_pipe, sizeof abstract_pipe) == 0);
- uv_close((uv_handle_t*)&server, close_cb);
+ uv_close((uv_handle_t*)&pipe_server, pipe_close_cb);
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
close(sock);
- ASSERT(close_cb_called == 1);
+ ASSERT(pipe_close_cb_called == 1);
MAKE_VALGRIND_HAPPY();
return 0;
#else
TEST_IMPL(pipe_getsockname_blocking) {
#ifdef _WIN32
- uv_pipe_t reader;
HANDLE readh, writeh;
int readfd;
char buf1[1024], buf2[1024];
r = CreatePipe(&readh, &writeh, NULL, 65536);
ASSERT(r != 0);
- r = uv_pipe_init(uv_default_loop(), &reader, 0);
+ r = uv_pipe_init(uv_default_loop(), &pipe_client, 0);
ASSERT(r == 0);
readfd = _open_osfhandle((intptr_t)readh, _O_RDONLY);
ASSERT(r != -1);
- r = uv_pipe_open(&reader, readfd);
+ r = uv_pipe_open(&pipe_client, readfd);
ASSERT(r == 0);
- r = uv_read_start((uv_stream_t*)&reader, NULL, NULL);
+ r = uv_read_start((uv_stream_t*)&pipe_client, NULL, NULL);
ASSERT(r == 0);
Sleep(100);
- r = uv_read_stop((uv_stream_t*)&reader);
+ r = uv_read_stop((uv_stream_t*)&pipe_client);
ASSERT(r == 0);
len1 = sizeof buf1;
- r = uv_pipe_getsockname(&reader, buf1, &len1);
+ r = uv_pipe_getsockname(&pipe_client, buf1, &len1);
ASSERT(r == 0);
+ ASSERT(buf1[len1 - 1] != 0);
- r = uv_read_start((uv_stream_t*)&reader, NULL, NULL);
+ r = uv_read_start((uv_stream_t*)&pipe_client, NULL, NULL);
ASSERT(r == 0);
Sleep(100);
len2 = sizeof buf2;
- r = uv_pipe_getsockname(&reader, buf2, &len2);
+ r = uv_pipe_getsockname(&pipe_client, buf2, &len2);
ASSERT(r == 0);
+ ASSERT(buf2[len2 - 1] != 0);
- r = uv_read_stop((uv_stream_t*)&reader);
+ r = uv_read_stop((uv_stream_t*)&pipe_client);
ASSERT(r == 0);
ASSERT(len1 == len2);
ASSERT(memcmp(buf1, buf2, len1) == 0);
- close_cb_called = 0;
- uv_close((uv_handle_t*)&reader, close_cb);
+ pipe_close_cb_called = 0;
+ uv_close((uv_handle_t*)&pipe_client, pipe_close_cb);
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
- ASSERT(close_cb_called == 1);
+ ASSERT(pipe_close_cb_called == 1);
_close(readfd);
CloseHandle(writeh);
#include <errno.h>
#ifndef _WIN32
-# include <fcntl.h>
# include <sys/socket.h>
# include <unistd.h>
#endif
}
-static void set_nonblocking(uv_os_sock_t sock) {
- int r;
-#ifdef _WIN32
- unsigned long on = 1;
- r = ioctlsocket(sock, FIONBIO, &on);
- ASSERT(r == 0);
-#else
- int flags = fcntl(sock, F_GETFL, 0);
- ASSERT(flags >= 0);
- r = fcntl(sock, F_SETFL, flags | O_NONBLOCK);
- ASSERT(r >= 0);
-#endif
-}
-
-
-static uv_os_sock_t create_nonblocking_bound_socket(
- struct sockaddr_in bind_addr) {
+static uv_os_sock_t create_bound_socket (struct sockaddr_in bind_addr) {
uv_os_sock_t sock;
int r;
ASSERT(sock >= 0);
#endif
- set_nonblocking(sock);
-
#ifndef _WIN32
{
/* Allow reuse of the port. */
ASSERT(sock >= 0);
#endif
- set_nonblocking(sock);
-
connection_context = create_connection_context(sock, 1);
connection_context->events = UV_READABLE | UV_WRITABLE;
r = uv_poll_start(&connection_context->poll_handle,
int r;
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
- sock = create_nonblocking_bound_socket(addr);
+ sock = create_bound_socket(addr);
context = create_server_context(sock);
r = listen(sock, 100);
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &server_addr));
ASSERT(0 == uv_ip4_addr("0.0.0.0", 0, &addr));
- sock = create_nonblocking_bound_socket(addr);
+ sock = create_bound_socket(addr);
context = create_connection_context(sock, 0);
context->events = UV_READABLE | UV_WRITABLE;
}
}
if (prev) { /* verify sort order -- requires Vista */
-#if _WIN32_WINNT >= 0x0600
+#if _WIN32_WINNT >= 0x0600 && \
+ (!defined(__MINGW32__) || defined(__MINGW64_VERSION_MAJOR))
ASSERT(CompareStringOrdinal(prev, -1, str, -1, TRUE) == 1);
#endif
}
'cflags': [ '-Wstrict-aliasing' ],
}],
[ 'OS=="linux"', {
+ 'defines': [ '_GNU_SOURCE' ],
'sources': [
'src/unix/linux-core.c',
'src/unix/linux-inotify.c',