CPPFLAGS += -D_LARGEFILE_SOURCE
CPPFLAGS += -D_FILE_OFFSET_BITS=64
+OBJS += src/unix/async.o
+OBJS += src/unix/cares.o
+OBJS += src/unix/check.o
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
OBJS += src/unix/error.o
-OBJS += src/unix/thread.o
+OBJS += src/unix/fs.o
+OBJS += src/unix/idle.o
+OBJS += src/unix/loop.o
+OBJS += src/unix/pipe.o
+OBJS += src/unix/prepare.o
OBJS += src/unix/process.o
+OBJS += src/unix/stream.o
OBJS += src/unix/tcp.o
-OBJS += src/unix/pipe.o
+OBJS += src/unix/thread.o
+OBJS += src/unix/timer.o
OBJS += src/unix/tty.o
-OBJS += src/unix/stream.o
+OBJS += src/unix/udp.o
ifeq (SunOS,$(uname_S))
EV_CONFIG=config_sunos.h
ifeq (Darwin,$(uname_S))
EV_CONFIG=config_darwin.h
EIO_CONFIG=config_darwin.h
-CPPFLAGS += -Isrc/ares/config_darwin
+CPPFLAGS += -D_DARWIN_USE_64_BIT_INODE=1 -Isrc/ares/config_darwin
LINKFLAGS+=-framework CoreServices
OBJS += src/unix/darwin.o
OBJS += src/unix/kqueue.o
CSTDFLAG += -D_GNU_SOURCE
CPPFLAGS += -Isrc/ares/config_linux
LINKFLAGS+=-ldl -lrt
-OBJS += src/unix/linux/core.o src/unix/linux/inotify.o
+OBJS += src/unix/linux/core.o src/unix/linux/inotify.o src/unix/linux/syscalls.o
endif
ifeq (FreeBSD,$(uname_S))
#ifndef UV_TREE_H_
#define UV_TREE_H_
-#if __GNUC__
-# define __unused __attribute__((unused))
-#else
-# define __unused
+#ifndef UV__UNUSED
+# if __GNUC__
+# define UV__UNUSED __attribute__((unused))
+# else
+# define UV__UNUSED
+# endif
#endif
/*
#define RB_PROTOTYPE(name, type, field, cmp) \
RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \
- RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static)
+ RB_PROTOTYPE_INTERNAL(name, type, field, cmp, UV__UNUSED static)
#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \
attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \
attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
#define RB_GENERATE(name, type, field, cmp) \
RB_GENERATE_INTERNAL(name, type, field, cmp,)
#define RB_GENERATE_STATIC(name, type, field, cmp) \
- RB_GENERATE_INTERNAL(name, type, field, cmp, __unused static)
+ RB_GENERATE_INTERNAL(name, type, field, cmp, UV__UNUSED static)
#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \
attr void \
name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
typedef void* uv_lib_t;
#define UV_DYNAMIC /* empty */
+#define UV_HANDLE_TYPE_PRIVATE /* empty */
+#define UV_REQ_TYPE_PRIVATE /* empty */
+
#if __linux__
# define UV_LOOP_PRIVATE_PLATFORM_FIELDS \
/* RB_HEAD(uv__inotify_watchers, uv_fs_event_s) */ \
* sure that we're always calling ares_process. See the warning above the \
* definition of ares_timeout(). \
*/ \
- ev_timer timer; \
+ uv_timer_t timer; \
/* Poll result queue */ \
eio_channel uv_eio_channel; \
struct ev_loop* ev; \
uv_async_t uv_eio_want_poll_notifier; \
uv_async_t uv_eio_done_poll_notifier; \
uv_idle_t uv_eio_poller; \
+ uv_handle_t* endgame_handles; \
UV_LOOP_PRIVATE_PLATFORM_FIELDS
#define UV_REQ_BUFSML_SIZE (4)
#define UV_HANDLE_PRIVATE_FIELDS \
int fd; \
int flags; \
- ev_idle next_watcher;
+ uv_handle_t* endgame_next; /* that's what uv-win calls it */ \
#define UV_STREAM_PRIVATE_FIELDS \
ev_timer timer_watcher; \
uv_timer_cb timer_cb;
-#define UV_ARES_TASK_PRIVATE_FIELDS \
- int sock; \
- ev_io read_watcher; \
- ev_io write_watcher;
-
#define UV_GETADDRINFO_PRIVATE_FIELDS \
uv_getaddrinfo_cb cb; \
struct addrinfo* hints; \
ev_io read_watcher; \
uv_fs_event_cb cb;
-#elif (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060) \
+#elif defined(__APPLE__) \
|| defined(__FreeBSD__) \
|| defined(__OpenBSD__) \
|| defined(__NetBSD__)
/* Counter to keep track of active udp streams */ \
unsigned int active_udp_streams;
+#define UV_HANDLE_TYPE_PRIVATE \
+ UV_ARES_EVENT,
+
#define UV_REQ_TYPE_PRIVATE \
/* TODO: remove the req suffix */ \
+ UV_ACCEPT, \
UV_ARES_EVENT_REQ, \
UV_ARES_CLEANUP_REQ, \
+ UV_FS_EVENT_REQ, \
UV_GETADDRINFO_REQ, \
UV_PROCESS_EXIT, \
UV_PROCESS_CLOSE, \
+ UV_READ, \
UV_UDP_RECV, \
- UV_FS_EVENT_REQ
+ UV_WAKEUP,
#define UV_REQ_PRIVATE_FIELDS \
union { \
uv_handle_t* endgame_next; \
unsigned int flags;
-#define UV_ARES_TASK_PRIVATE_FIELDS \
- struct uv_req_s ares_req; \
- SOCKET sock; \
- HANDLE h_wait; \
- WSAEVENT h_event; \
- HANDLE h_close_event;
-
#define UV_GETADDRINFO_PRIVATE_FIELDS \
struct uv_req_s getadddrinfo_req; \
uv_getaddrinfo_cb getaddrinfo_cb; \
} uv_err_code;
#undef UV_ERRNO_GEN
+#define UV_HANDLE_TYPE_MAP(XX) \
+ XX(ARES_TASK, ares_task) \
+ XX(ASYNC, async) \
+ XX(CHECK, check) \
+ XX(FS_EVENT, fs_event) \
+ XX(IDLE, idle) \
+ XX(NAMED_PIPE, pipe) \
+ XX(PREPARE, prepare) \
+ XX(PROCESS, process) \
+ XX(TCP, tcp) \
+ XX(TIMER, timer) \
+ XX(TTY, tty) \
+ XX(UDP, udp) \
+
+#define UV_REQ_TYPE_MAP(XX) \
+ XX(CONNECT, connect) \
+ XX(WRITE, write) \
+ XX(SHUTDOWN, shutdown) \
+ XX(UDP_SEND, udp_send) \
+ XX(FS, fs) \
+ XX(WORK, work) \
+ XX(GETADDRINFO, getaddrinfo) \
+
typedef enum {
UV_UNKNOWN_HANDLE = 0,
- UV_TCP,
- UV_UDP,
- UV_NAMED_PIPE,
- UV_TTY,
+#define XX(uc, lc) UV_##uc,
+ UV_HANDLE_TYPE_MAP(XX)
+#undef XX
UV_FILE,
- UV_TIMER,
- UV_PREPARE,
- UV_CHECK,
- UV_IDLE,
- UV_ASYNC,
- UV_ARES_TASK,
- UV_ARES_EVENT,
- UV_PROCESS,
- UV_FS_EVENT
+ UV_HANDLE_TYPE_PRIVATE
+ UV_HANDLE_TYPE_MAX
} uv_handle_type;
typedef enum {
UV_UNKNOWN_REQ = 0,
- UV_CONNECT,
- UV_ACCEPT,
- UV_READ,
- UV_WRITE,
- UV_SHUTDOWN,
- UV_WAKEUP,
- UV_UDP_SEND,
- UV_FS,
- UV_WORK,
- UV_GETADDRINFO,
+#define XX(uc, lc) UV_##uc,
+ UV_REQ_TYPE_MAP(XX)
+#undef XX
UV_REQ_TYPE_PRIVATE
+ UV_REQ_TYPE_MAX
} uv_req_type;
};
/*
+ * Returns size of various handle types, useful for FFI
+ * bindings to allocate correct memory without copying struct
+ * definitions
+ */
+UV_EXTERN size_t uv_handle_size(uv_handle_type type);
+
+/*
+ * Returns size of request types, useful for dynamic lookup with FFI
+ */
+UV_EXTERN size_t uv_req_size(uv_req_type type);
+
+/*
* Returns 1 if the prepare/check/idle/timer handle has been started, 0
* otherwise. For other handle types this always returns 1.
*/
/*
+ * Used to determine whether a stream is closing or closed.
+ *
+ * N.B. is only valid between the initialization of the handle
+ * and the arrival of the close callback, and cannot be used
+ * to validate the handle.
+ */
+UV_EXTERN int uv_is_closing(uv_handle_t* handle);
+
+
+/*
* uv_tcp_t is a subclass of uv_stream_t
*
* Represents a TCP stream or TCP server.
/* Don't export the private CPP symbols. */
+#undef UV_HANDLE_TYPE_PRIVATE
#undef UV_REQ_TYPE_PRIVATE
#undef UV_REQ_PRIVATE_FIELDS
#undef UV_STREAM_PRIVATE_FIELDS
--- /dev/null
+/* 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"
+
+
+static void uv__async(EV_P_ ev_async* w, int revents) {
+ uv_async_t* async = container_of(w, uv_async_t, async_watcher);
+
+ if (async->async_cb) {
+ async->async_cb(async, 0);
+ }
+}
+
+
+int uv_async_init(uv_loop_t* loop, uv_async_t* async, uv_async_cb async_cb) {
+ uv__handle_init(loop, (uv_handle_t*)async, UV_ASYNC);
+ loop->counters.async_init++;
+
+ ev_async_init(&async->async_watcher, uv__async);
+ async->async_cb = async_cb;
+
+ /* Note: This does not have symmetry with the other libev wrappers. */
+ ev_async_start(loop->ev, &async->async_watcher);
+ ev_unref(loop->ev);
+
+ return 0;
+}
+
+
+int uv_async_send(uv_async_t* async) {
+ ev_async_send(async->loop->ev, &async->async_watcher);
+ return 0;
+}
+
+
+void uv__async_close(uv_async_t* handle) {
+ ev_async_stop(handle->loop->ev, &handle->async_watcher);
+ ev_ref(handle->loop->ev);
+}
* This is called once per second by loop->timer. It is used to
* constantly callback into c-ares for possibly processing timeouts.
*/
-static void uv__ares_timeout(struct ev_loop* ev, struct ev_timer* watcher,
- int revents) {
- uv_loop_t* loop = ev_userdata(ev);
+static void uv__ares_timeout(uv_timer_t* handle, int status) {
+ assert(!uv_ares_handles_empty(handle->loop));
+ ares_process_fd(handle->loop->channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
+}
+
+
+static void uv__ares_timer_start(uv_loop_t* loop) {
+ if (uv_is_active((uv_handle_t*)&loop->timer)) return;
+ uv_timer_start(&loop->timer, uv__ares_timeout, 1000, 1000);
+ uv_ref(loop);
+}
- assert(ev == loop->ev);
- assert((uv_loop_t*)watcher->data == loop);
- assert(watcher == &loop->timer);
- assert(revents == EV_TIMER);
- assert(!uv_ares_handles_empty(loop));
- ares_process_fd(loop->channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
+static void uv__ares_timer_stop(uv_loop_t* loop) {
+ if (!uv_is_active((uv_handle_t*)&loop->timer)) return;
+ uv_timer_stop(&loop->timer);
+ uv_unref(loop);
}
assert(ev == loop->ev);
/* Reset the idle timer */
- ev_timer_again(ev, &loop->timer);
+ uv_timer_again(&loop->timer);
/* Process DNS responses */
ares_process_fd(loop->channel,
/* New socket */
/* If this is the first socket then start the timer. */
- if (!ev_is_active(&loop->timer)) {
+ if (!uv_is_active((uv_handle_t*)&loop->timer)) {
assert(uv_ares_handles_empty(loop));
- ev_timer_again(loop->ev, &loop->timer);
+ uv__ares_timer_start(loop);
}
h = uv__ares_task_create(loop, sock);
free(h);
if (uv_ares_handles_empty(loop)) {
- ev_timer_stop(loop->ev, &loop->timer);
+ uv__ares_timer_stop(loop);
}
}
}
* Initialize the timeout timer. The timer won't be started until the
* first socket is opened.
*/
- ev_timer_init(&loop->timer, uv__ares_timeout, 1., 1.);
+ uv_timer_init(loop, &loop->timer);
+ uv_unref(loop);
loop->timer.data = loop;
return rc;
void uv_ares_destroy(uv_loop_t* loop, ares_channel channel) {
/* only allow destroy if did init */
if (loop->channel) {
- ev_timer_stop(loop->ev, &loop->timer);
+ uv__ares_timer_stop(loop);
ares_destroy(channel);
loop->channel = NULL;
}
--- /dev/null
+/* 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"
+
+
+static void uv__check(EV_P_ ev_check* w, int revents) {
+ uv_check_t* check = container_of(w, uv_check_t, check_watcher);
+
+ if (check->check_cb) {
+ check->check_cb(check, 0);
+ }
+}
+
+
+int uv_check_init(uv_loop_t* loop, uv_check_t* check) {
+ uv__handle_init(loop, (uv_handle_t*)check, UV_CHECK);
+ loop->counters.check_init++;
+
+ ev_check_init(&check->check_watcher, uv__check);
+ check->check_cb = NULL;
+
+ return 0;
+}
+
+
+int uv_check_start(uv_check_t* check, uv_check_cb cb) {
+ int was_active = ev_is_active(&check->check_watcher);
+
+ check->check_cb = cb;
+
+ ev_check_start(check->loop->ev, &check->check_watcher);
+
+ if (!was_active) {
+ ev_unref(check->loop->ev);
+ }
+
+ return 0;
+}
+
+
+int uv_check_stop(uv_check_t* check) {
+ int was_active = ev_is_active(&check->check_watcher);
+
+ ev_check_stop(check->loop->ev, &check->check_watcher);
+
+ if (was_active) {
+ ev_ref(check->loop->ev);
+ }
+
+ return 0;
+}
+
+
+int uv__check_active(const uv_check_t* handle) {
+ return ev_is_active(&handle->check_watcher);
+}
+
+
+void uv__check_close(uv_check_t* handle) {
+ uv_check_stop(handle);
+}
static uv_loop_t default_loop_struct;
static uv_loop_t* default_loop_ptr;
-void uv__next(EV_P_ ev_idle* watcher, int revents);
static void uv__finish_close(uv_handle_t* handle);
void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
- uv_async_t* async;
- uv_stream_t* stream;
- uv_process_t* process;
-
handle->close_cb = close_cb;
switch (handle->type) {
- case UV_NAMED_PIPE:
- uv_pipe_cleanup((uv_pipe_t*)handle);
- /* Fall through. */
-
- case UV_TTY:
- case UV_TCP:
- stream = (uv_stream_t*)handle;
-
- uv_read_stop(stream);
- ev_io_stop(stream->loop->ev, &stream->write_watcher);
-
- close(stream->fd);
- stream->fd = -1;
-
- if (stream->accepted_fd >= 0) {
- close(stream->accepted_fd);
- stream->accepted_fd = -1;
- }
+ case UV_NAMED_PIPE:
+ uv__pipe_close((uv_pipe_t*)handle);
+ break;
- assert(!ev_is_active(&stream->read_watcher));
- assert(!ev_is_active(&stream->write_watcher));
- break;
+ case UV_TTY:
+ case UV_TCP:
+ uv__stream_close((uv_stream_t*)handle);
+ break;
- case UV_UDP:
- uv__udp_start_close((uv_udp_t*)handle);
- break;
+ case UV_UDP:
+ uv__udp_close((uv_udp_t*)handle);
+ break;
- case UV_PREPARE:
- uv_prepare_stop((uv_prepare_t*) handle);
- break;
+ case UV_PREPARE:
+ uv__prepare_close((uv_prepare_t*)handle);
+ break;
- case UV_CHECK:
- uv_check_stop((uv_check_t*) handle);
- break;
+ case UV_CHECK:
+ uv__check_close((uv_check_t*)handle);
+ break;
- case UV_IDLE:
- uv_idle_stop((uv_idle_t*) handle);
- break;
+ case UV_IDLE:
+ uv__idle_close((uv_idle_t*)handle);
+ break;
- case UV_ASYNC:
- async = (uv_async_t*)handle;
- ev_async_stop(async->loop->ev, &async->async_watcher);
- ev_ref(async->loop->ev);
- break;
+ case UV_ASYNC:
+ uv__async_close((uv_async_t*)handle);
+ break;
- case UV_TIMER:
- uv_timer_stop((uv_timer_t*)handle);
- break;
+ case UV_TIMER:
+ uv__timer_close((uv_timer_t*)handle);
+ break;
- case UV_PROCESS:
- process = (uv_process_t*)handle;
- ev_child_stop(process->loop->ev, &process->child_watcher);
- break;
+ case UV_PROCESS:
+ uv__process_close((uv_process_t*)handle);
+ break;
- case UV_FS_EVENT:
- uv__fs_event_destroy((uv_fs_event_t*)handle);
- break;
+ case UV_FS_EVENT:
+ uv__fs_event_close((uv_fs_event_t*)handle);
+ break;
- default:
- assert(0);
+ default:
+ assert(0);
}
handle->flags |= UV_CLOSING;
+ handle->endgame_next = handle->loop->endgame_handles;
+ handle->loop->endgame_handles = handle;
+ uv_unref(handle->loop);
+}
+
- /* This is used to call the on_close callback in the next loop. */
- ev_idle_start(handle->loop->ev, &handle->next_watcher);
- ev_feed_event(handle->loop->ev, &handle->next_watcher, EV_IDLE);
- assert(ev_is_pending(&handle->next_watcher));
+int uv_is_closing(uv_handle_t* handle) {
+ return handle->flags & (UV_CLOSING | UV_CLOSED);
}
-static int uv__loop_init(uv_loop_t* loop,
- struct ev_loop *(ev_loop_new)(unsigned int flags)) {
- memset(loop, 0, sizeof(*loop));
- RB_INIT(&loop->uv_ares_handles_);
-#if HAVE_KQUEUE
- loop->ev = ev_loop_new(EVBACKEND_KQUEUE);
-#else
- loop->ev = ev_loop_new(EVFLAG_AUTO);
-#endif
- ev_set_userdata(loop->ev, loop);
- eio_channel_init(&loop->uv_eio_channel, loop);
- uv__loop_platform_init(loop);
- return 0;
+uv_loop_t* uv_default_loop(void) {
+ if (default_loop_ptr)
+ return default_loop_ptr;
+
+ if (uv__loop_init(&default_loop_struct, /* default_loop? */ 1))
+ return NULL;
+
+ return (default_loop_ptr = &default_loop_struct);
}
if ((loop = malloc(sizeof(*loop))) == NULL)
return NULL;
- if (uv__loop_init(loop, ev_loop_new)) {
+ if (uv__loop_init(loop, /* default_loop? */ 0)) {
free(loop);
return NULL;
}
void uv_loop_delete(uv_loop_t* loop) {
- uv_ares_destroy(loop, loop->channel);
- ev_loop_destroy(loop->ev);
- uv__loop_platform_delete(loop);
+ uv__loop_delete(loop);
#ifndef NDEBUG
memset(loop, -1, sizeof *loop);
#endif
}
-uv_loop_t* uv_default_loop(void) {
- if (default_loop_ptr)
- return default_loop_ptr;
-
- if (uv__loop_init(&default_loop_struct, ev_default_loop))
- return NULL;
+void uv__run(uv_loop_t* loop) {
+ ev_run(loop->ev, EVRUN_ONCE);
- default_loop_ptr = &default_loop_struct;
- return default_loop_ptr;
+ while (loop->endgame_handles)
+ uv__finish_close(loop->endgame_handles);
}
int uv_run(uv_loop_t* loop) {
- ev_run(loop->ev, 0);
+ do
+ uv__run(loop);
+ while (uv_loop_refcount(loop) > 0);
+
return 0;
}
int uv_run_once(uv_loop_t* loop) {
- ev_run(loop->ev, EVRUN_ONCE);
+ uv__run(loop);
return 0;
}
handle->loop = loop;
handle->type = type;
handle->flags = 0;
-
- ev_init(&handle->next_watcher, uv__next);
-
- /* Ref the loop until this handle is closed. See uv__finish_close. */
- ev_ref(loop->ev);
+ handle->endgame_next = NULL;
+ uv_ref(loop); /* unref'd in uv_close() */
}
break;
}
- ev_idle_stop(loop->ev, &handle->next_watcher);
+
+ loop->endgame_handles = handle->endgame_next;
if (handle->close_cb) {
handle->close_cb(handle);
}
-
- ev_unref(loop->ev);
-}
-
-
-void uv__next(EV_P_ ev_idle* w, int revents) {
- uv_handle_t* handle = container_of(w, uv_handle_t, next_watcher);
-
- assert(revents == EV_IDLE);
-
- /* For now this function is only to handle the closing event, but we might
- * put more stuff here later.
- */
- assert(handle->flags & UV_CLOSING);
- uv__finish_close(handle);
}
}
-static void uv__prepare(EV_P_ ev_prepare* w, int revents) {
- uv_prepare_t* prepare = container_of(w, uv_prepare_t, prepare_watcher);
-
- if (prepare->prepare_cb) {
- prepare->prepare_cb(prepare, 0);
- }
-}
-
-
-int uv_prepare_init(uv_loop_t* loop, uv_prepare_t* prepare) {
- uv__handle_init(loop, (uv_handle_t*)prepare, UV_PREPARE);
- loop->counters.prepare_init++;
-
- ev_prepare_init(&prepare->prepare_watcher, uv__prepare);
- prepare->prepare_cb = NULL;
-
- return 0;
-}
-
-
-int uv_prepare_start(uv_prepare_t* prepare, uv_prepare_cb cb) {
- int was_active = ev_is_active(&prepare->prepare_watcher);
-
- prepare->prepare_cb = cb;
-
- ev_prepare_start(prepare->loop->ev, &prepare->prepare_watcher);
-
- if (!was_active) {
- ev_unref(prepare->loop->ev);
- }
-
- return 0;
-}
-
-
-int uv_prepare_stop(uv_prepare_t* prepare) {
- int was_active = ev_is_active(&prepare->prepare_watcher);
-
- ev_prepare_stop(prepare->loop->ev, &prepare->prepare_watcher);
-
- if (was_active) {
- ev_ref(prepare->loop->ev);
- }
- return 0;
-}
-
-
-
-static void uv__check(EV_P_ ev_check* w, int revents) {
- uv_check_t* check = container_of(w, uv_check_t, check_watcher);
-
- if (check->check_cb) {
- check->check_cb(check, 0);
- }
-}
-
-
-int uv_check_init(uv_loop_t* loop, uv_check_t* check) {
- uv__handle_init(loop, (uv_handle_t*)check, UV_CHECK);
- loop->counters.check_init++;
-
- ev_check_init(&check->check_watcher, uv__check);
- check->check_cb = NULL;
-
- return 0;
-}
-
-
-int uv_check_start(uv_check_t* check, uv_check_cb cb) {
- int was_active = ev_is_active(&check->check_watcher);
-
- check->check_cb = cb;
-
- ev_check_start(check->loop->ev, &check->check_watcher);
-
- if (!was_active) {
- ev_unref(check->loop->ev);
- }
-
- return 0;
-}
-
-
-int uv_check_stop(uv_check_t* check) {
- int was_active = ev_is_active(&check->check_watcher);
-
- ev_check_stop(check->loop->ev, &check->check_watcher);
-
- if (was_active) {
- ev_ref(check->loop->ev);
- }
-
- return 0;
-}
-
-
-static void uv__idle(EV_P_ ev_idle* w, int revents) {
- uv_idle_t* idle = container_of(w, uv_idle_t, idle_watcher);
-
- if (idle->idle_cb) {
- idle->idle_cb(idle, 0);
- }
-}
-
-
-
-int uv_idle_init(uv_loop_t* loop, uv_idle_t* idle) {
- uv__handle_init(loop, (uv_handle_t*)idle, UV_IDLE);
- loop->counters.idle_init++;
-
- ev_idle_init(&idle->idle_watcher, uv__idle);
- idle->idle_cb = NULL;
-
- return 0;
-}
-
-
-int uv_idle_start(uv_idle_t* idle, uv_idle_cb cb) {
- int was_active = ev_is_active(&idle->idle_watcher);
-
- idle->idle_cb = cb;
- ev_idle_start(idle->loop->ev, &idle->idle_watcher);
-
- if (!was_active) {
- ev_unref(idle->loop->ev);
- }
-
- return 0;
-}
-
-
-int uv_idle_stop(uv_idle_t* idle) {
- int was_active = ev_is_active(&idle->idle_watcher);
-
- ev_idle_stop(idle->loop->ev, &idle->idle_watcher);
-
- if (was_active) {
- ev_ref(idle->loop->ev);
- }
-
- return 0;
-}
-
-
int uv_is_active(uv_handle_t* handle) {
switch (handle->type) {
- case UV_TIMER:
- return ev_is_active(&((uv_timer_t*)handle)->timer_watcher);
-
- case UV_PREPARE:
- return ev_is_active(&((uv_prepare_t*)handle)->prepare_watcher);
-
- case UV_CHECK:
- return ev_is_active(&((uv_check_t*)handle)->check_watcher);
-
- case UV_IDLE:
- return ev_is_active(&((uv_idle_t*)handle)->idle_watcher);
-
- default:
- return 1;
+ case UV_CHECK:
+ return uv__check_active((uv_check_t*)handle);
+ case UV_IDLE:
+ return uv__idle_active((uv_idle_t*)handle);
+ case UV_PREPARE:
+ return uv__prepare_active((uv_prepare_t*)handle);
+ case UV_TIMER:
+ return uv__timer_active((uv_timer_t*)handle);
+ default:
+ return 1;
}
}
-static void uv__async(EV_P_ ev_async* w, int revents) {
- uv_async_t* async = container_of(w, uv_async_t, async_watcher);
-
- if (async->async_cb) {
- async->async_cb(async, 0);
- }
-}
-
-
-int uv_async_init(uv_loop_t* loop, uv_async_t* async, uv_async_cb async_cb) {
- uv__handle_init(loop, (uv_handle_t*)async, UV_ASYNC);
- loop->counters.async_init++;
-
- ev_async_init(&async->async_watcher, uv__async);
- async->async_cb = async_cb;
-
- /* Note: This does not have symmetry with the other libev wrappers. */
- ev_async_start(loop->ev, &async->async_watcher);
- ev_unref(loop->ev);
-
- return 0;
-}
-
-
-int uv_async_send(uv_async_t* async) {
- ev_async_send(async->loop->ev, &async->async_watcher);
- return 0;
-}
-
-
-static int uv__timer_active(const uv_timer_t* timer) {
- return timer->flags & UV_TIMER_ACTIVE;
-}
-
-
-static int uv__timer_repeating(const uv_timer_t* timer) {
- return timer->flags & UV_TIMER_REPEAT;
-}
-
-
-static void uv__timer_cb(EV_P_ ev_timer* w, int revents) {
- uv_timer_t* timer = container_of(w, uv_timer_t, timer_watcher);
-
- assert(uv__timer_active(timer));
-
- if (!uv__timer_repeating(timer)) {
- timer->flags &= ~UV_TIMER_ACTIVE;
- ev_ref(EV_A);
- }
-
- if (timer->timer_cb) {
- timer->timer_cb(timer, 0);
- }
-}
-
-
-int uv_timer_init(uv_loop_t* loop, uv_timer_t* timer) {
- uv__handle_init(loop, (uv_handle_t*)timer, UV_TIMER);
- loop->counters.timer_init++;
-
- ev_init(&timer->timer_watcher, uv__timer_cb);
-
- return 0;
-}
-
-
-int uv_timer_start(uv_timer_t* timer, uv_timer_cb cb, int64_t timeout,
- int64_t repeat) {
- if (uv__timer_active(timer)) {
- return -1;
- }
-
- timer->timer_cb = cb;
- timer->flags |= UV_TIMER_ACTIVE;
-
- if (repeat)
- timer->flags |= UV_TIMER_REPEAT;
- else
- timer->flags &= ~UV_TIMER_REPEAT;
-
- ev_timer_set(&timer->timer_watcher, timeout / 1000.0, repeat / 1000.0);
- ev_timer_start(timer->loop->ev, &timer->timer_watcher);
- ev_unref(timer->loop->ev);
-
- return 0;
-}
-
-
-int uv_timer_stop(uv_timer_t* timer) {
- if (uv__timer_active(timer)) {
- ev_ref(timer->loop->ev);
- }
-
- timer->flags &= ~(UV_TIMER_ACTIVE | UV_TIMER_REPEAT);
- ev_timer_stop(timer->loop->ev, &timer->timer_watcher);
-
- return 0;
-}
-
-
-int uv_timer_again(uv_timer_t* timer) {
- if (!uv__timer_active(timer)) {
- uv__set_sys_error(timer->loop, EINVAL);
- return -1;
- }
-
- assert(uv__timer_repeating(timer));
- ev_timer_again(timer->loop->ev, &timer->timer_watcher);
- return 0;
-}
-
-
-void uv_timer_set_repeat(uv_timer_t* timer, int64_t repeat) {
- assert(timer->type == UV_TIMER);
- timer->timer_watcher.repeat = repeat / 1000.0;
-
- if (repeat)
- timer->flags |= UV_TIMER_REPEAT;
- else
- timer->flags &= ~UV_TIMER_REPEAT;
-}
-
-
-int64_t uv_timer_get_repeat(uv_timer_t* timer) {
- assert(timer->type == UV_TIMER);
- return (int64_t)(1000 * timer->timer_watcher.repeat);
-}
-
-
static int uv_getaddrinfo_done(eio_req* req) {
uv_getaddrinfo_t* handle = req->data;
struct addrinfo *res = handle->res;
assert(sockfd >= 0);
while (1) {
-#if HAVE_SYS_ACCEPT4
- peerfd = sys_accept4(sockfd, saddr, &slen, SOCK_NONBLOCK | SOCK_CLOEXEC);
-
+#if __linux__
+ peerfd = uv__accept4(sockfd, saddr, &slen, UV__SOCK_NONBLOCK|UV__SOCK_CLOEXEC);
if (peerfd != -1)
break;
}
-void uv__fs_event_destroy(uv_fs_event_t* handle) {
+void uv__fs_event_close(uv_fs_event_t* handle) {
assert(0 && "implement me");
}
int uv_exepath(char* buffer, size_t* size) {
uint32_t usize;
int result;
+ char* path;
char* fullpath;
if (!buffer || !size) {
result = _NSGetExecutablePath(buffer, &usize);
if (result) return result;
- fullpath = realpath(buffer, NULL);
+ path = (char*)malloc(2 * PATH_MAX);
+ fullpath = realpath(buffer, path);
if (fullpath == NULL) {
+ free(path);
return -1;
}
#include <string.h>
#include <errno.h>
+/* These are the same on OS X and the BSDs. */
+#ifndef NOTE_DELETE
+# define NOTE_DELETE 0x01
+#endif
+#ifndef NOTE_WRITE
+# define NOTE_WRITE 0x02
+#endif
+#ifndef NOTE_EXTEND
+# define NOTE_EXTEND 0x04
+#endif
+#ifndef NOTE_ATTRIB
+# define NOTE_ATTRIB 0x08
+#endif
+#ifndef NOTE_LINK
+# define NOTE_LINK 0x10
+#endif
+#ifndef NOTE_RENAME
+# define NOTE_RENAME 0x20
+#endif
+#ifndef NOTE_REVOKE
+# define NOTE_REVOKE 0x40
+#endif
+
+
extern void
uv__kqueue_hack (EV_P_ int fflags, ev_io *w);
#if HAVE_FUTIMES
-static int _futime(const uv_file file, double atime, double mtime) {
+static int _futime(const uv_file fd, double atime, double mtime) {
+#if __linux__
+ /* utimesat() has nanosecond resolution but we stick to microseconds
+ * for the sake of consistency with other platforms.
+ */
+ struct timespec ts[2];
+ ts[0].tv_sec = atime;
+ ts[0].tv_nsec = (unsigned long)(atime * 1000000) % 1000000 * 1000;
+ ts[1].tv_sec = mtime;
+ ts[1].tv_nsec = (unsigned long)(mtime * 1000000) % 1000000 * 1000;
+ return uv__utimesat(fd, NULL, ts, 0);
+#else
struct timeval tv[2];
-
- /* FIXME possible loss of precision in floating-point arithmetic? */
tv[0].tv_sec = atime;
tv[0].tv_usec = (unsigned long)(atime * 1000000) % 1000000;
-
tv[1].tv_sec = mtime;
tv[1].tv_usec = (unsigned long)(mtime * 1000000) % 1000000;
-
-#ifdef __sun
- return futimesat(file, NULL, tv);
-#else
- return futimes(file, tv);
-#endif
+ return futimes(fd, tv);
+#endif /* __linux__ */
}
-#endif
+#endif /* HAVE_FUTIMES */
int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime,
--- /dev/null
+/* 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"
+
+
+static void uv__idle(EV_P_ ev_idle* w, int revents) {
+ uv_idle_t* idle = container_of(w, uv_idle_t, idle_watcher);
+
+ if (idle->idle_cb) {
+ idle->idle_cb(idle, 0);
+ }
+}
+
+
+int uv_idle_init(uv_loop_t* loop, uv_idle_t* idle) {
+ uv__handle_init(loop, (uv_handle_t*)idle, UV_IDLE);
+ loop->counters.idle_init++;
+
+ ev_idle_init(&idle->idle_watcher, uv__idle);
+ idle->idle_cb = NULL;
+
+ return 0;
+}
+
+
+int uv_idle_start(uv_idle_t* idle, uv_idle_cb cb) {
+ int was_active = ev_is_active(&idle->idle_watcher);
+
+ idle->idle_cb = cb;
+ ev_idle_start(idle->loop->ev, &idle->idle_watcher);
+
+ if (!was_active) {
+ ev_unref(idle->loop->ev);
+ }
+
+ return 0;
+}
+
+
+int uv_idle_stop(uv_idle_t* idle) {
+ int was_active = ev_is_active(&idle->idle_watcher);
+
+ ev_idle_stop(idle->loop->ev, &idle->idle_watcher);
+
+ if (was_active) {
+ ev_ref(idle->loop->ev);
+ }
+
+ return 0;
+}
+
+
+int uv__idle_active(const uv_idle_t* handle) {
+ return ev_is_active(&handle->idle_watcher);
+}
+
+
+void uv__idle_close(uv_idle_t* handle) {
+ uv_idle_stop(handle);
+}
#undef HAVE_KQUEUE
#undef HAVE_PORTS_FS
-#if defined(__linux__)
-
-# undef HAVE_SYS_UTIMESAT
-# undef HAVE_SYS_PIPE2
-# undef HAVE_SYS_ACCEPT4
-
-# undef _GNU_SOURCE
-# define _GNU_SOURCE
-
-# include <linux/version.h>
-# include <sys/syscall.h>
-# include <features.h>
-# include <unistd.h>
-
-# if __NR_utimensat
-# define HAVE_SYS_UTIMESAT 1
-# endif
-# if __NR_pipe2
-# define HAVE_SYS_PIPE2 1
-# endif
-# if __NR_accept4
-# define HAVE_SYS_ACCEPT4 1
-# endif
-
-# ifndef O_CLOEXEC
-# define O_CLOEXEC 02000000
-# endif
-
-# ifndef SOCK_CLOEXEC
-# define SOCK_CLOEXEC O_CLOEXEC
-# endif
-
-# ifndef SOCK_NONBLOCK
-# define SOCK_NONBLOCK O_NONBLOCK
-# endif
-
-# if HAVE_SYS_UTIMESAT
-inline static int sys_utimesat(int dirfd,
- const char* path,
- const struct timespec times[2],
- int flags)
-{
- return syscall(__NR_utimensat, dirfd, path, times, flags);
-}
-inline static int sys_futimes(int fd, const struct timeval times[2])
-{
- struct timespec ts[2];
- ts[0].tv_sec = times[0].tv_sec, ts[0].tv_nsec = times[0].tv_usec * 1000;
- ts[1].tv_sec = times[1].tv_sec, ts[1].tv_nsec = times[1].tv_usec * 1000;
- return sys_utimesat(fd, NULL, ts, 0);
-}
-# undef HAVE_FUTIMES
-# define HAVE_FUTIMES 1
-# define futimes(fd, times) sys_futimes(fd, times)
-# endif /* HAVE_SYS_FUTIMESAT */
-
-# if HAVE_SYS_PIPE2
-inline static int sys_pipe2(int pipefd[2], int flags)
-{
- return syscall(__NR_pipe2, pipefd, flags);
-}
-# endif /* HAVE_SYS_PIPE2 */
-
-# if HAVE_SYS_ACCEPT4
-inline static int sys_accept4(int fd,
- struct sockaddr* addr,
- socklen_t* addrlen,
- int flags)
-{
- return syscall(__NR_accept4, fd, addr, addrlen, flags);
-}
-# endif /* HAVE_SYS_ACCEPT4 */
-
+#if __linux__
+# include "linux/syscalls.h"
+# define HAVE_FUTIMES 1 /* emulated with utimesat() */
#endif /* __linux__ */
#if defined(__sun)
# ifdef PORT_SOURCE_FILE
# define HAVE_PORTS_FS 1
# endif
+# define HAVE_FUTIMES 1
+# define futimes(fd, tv) futimesat(fd, (void*)0, tv)
#endif /* __sun */
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__sun)
#endif
/* FIXME exact copy of the #ifdef guard in uv-unix.h */
-#if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060) \
+#if defined(__APPLE__) \
|| defined(__FreeBSD__) \
|| defined(__OpenBSD__) \
|| defined(__NetBSD__)
int uv__socket(int domain, int type, int protocol);
int uv__dup(int fd);
+/* loop */
+int uv__loop_init(uv_loop_t* loop, int default_loop);
+void uv__loop_delete(uv_loop_t* loop);
+
/* error */
uv_err_code uv_translate_sys_error(int sys_errno);
void uv_fatal_error(const int errorno, const char* syscall);
/* pipe */
int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);
void uv__pipe_accept(EV_P_ ev_io* watcher, int revents);
-int uv_pipe_cleanup(uv_pipe_t* handle);
-/* udp */
-void uv__udp_start_close(uv_udp_t* handle);
+/* various */
+int uv__check_active(const uv_check_t* handle);
+int uv__idle_active(const uv_idle_t* handle);
+int uv__prepare_active(const uv_prepare_t* handle);
+int uv__timer_active(const uv_timer_t* handle);
+
+void uv__async_close(uv_async_t* handle);
+void uv__check_close(uv_check_t* handle);
+void uv__fs_event_close(uv_fs_event_t* handle);
+void uv__idle_close(uv_idle_t* handle);
+void uv__pipe_close(uv_pipe_t* handle);
+void uv__prepare_close(uv_prepare_t* handle);
+void uv__process_close(uv_process_t* handle);
+void uv__stream_close(uv_stream_t* handle);
+void uv__timer_close(uv_timer_t* handle);
+void uv__udp_close(uv_udp_t* handle);
void uv__udp_finish_close(uv_udp_t* handle);
-/* fs */
-void uv__fs_event_destroy(uv_fs_event_t* handle);
-
#define UV__F_IPC (1 << 0)
#define UV__F_NONBLOCK (1 << 1)
int uv__make_socketpair(int fds[2], int flags);
int uv__make_pipe(int fds[2], int flags);
-#if __linux__
-void uv__inotify_loop_init(uv_loop_t* loop);
-void uv__inotify_loop_delete(uv_loop_t* loop);
-# define uv__loop_platform_init(loop) uv__inotify_loop_init(loop)
-# define uv__loop_platform_delete(loop) uv__inotify_loop_delete(loop)
-#else
-# define uv__loop_platform_init(loop)
-# define uv__loop_platform_delete(loop)
-#endif
-
#endif /* UV_UNIX_INTERNAL_H_ */
#include <string.h>
#include <errno.h>
-#if HAVE_KQUEUE
-
#include <sys/sysctl.h>
#include <sys/types.h>
#include <sys/event.h>
}
-void uv__fs_event_destroy(uv_fs_event_t* handle) {
+void uv__fs_event_close(uv_fs_event_t* handle) {
uv__fs_event_stop(handle);
free(handle->filename);
close(handle->fd);
handle->fd = -1;
}
-
-#else /* !HAVE_KQUEUE */
-
-int uv_fs_event_init(uv_loop_t* loop,
- uv_fs_event_t* handle,
- const char* filename,
- uv_fs_event_cb cb,
- int flags) {
- loop->counters.fs_event_init++;
- uv__set_sys_error(loop, ENOSYS);
- return -1;
-}
-
-
-void uv__fs_event_destroy(uv_fs_event_t* handle) {
- UNREACHABLE();
-}
-
-
-/* Called by libev, don't touch. */
-void uv__kqueue_hack(EV_P_ int fflags, ev_io *w) {
- UNREACHABLE();
-}
-
-#endif /* HAVE_KQUEUE */
#include "uv.h"
#include "tree.h"
#include "../internal.h"
+#include "syscalls.h"
#include <stdint.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
-#include <fcntl.h>
-
-#undef HAVE_INOTIFY_INIT
-#undef HAVE_INOTIFY_INIT1
-#undef HAVE_INOTIFY_ADD_WATCH
-#undef HAVE_INOTIFY_RM_WATCH
-
-#if __NR_inotify_init
-# define HAVE_INOTIFY_INIT 1
-#endif
-#if __NR_inotify_init1
-# define HAVE_INOTIFY_INIT1 1
-#endif
-#if __NR_inotify_add_watch
-# define HAVE_INOTIFY_ADD_WATCH 1
-#endif
-#if __NR_inotify_rm_watch
-# define HAVE_INOTIFY_RM_WATCH 1
-#endif
-
-#if HAVE_INOTIFY_INIT || HAVE_INOTIFY_INIT1
-# undef IN_ACCESS
-# undef IN_MODIFY
-# undef IN_ATTRIB
-# undef IN_CLOSE_WRITE
-# undef IN_CLOSE_NOWRITE
-# undef IN_OPEN
-# undef IN_MOVED_FROM
-# undef IN_MOVED_TO
-# undef IN_CREATE
-# undef IN_DELETE
-# undef IN_DELETE_SELF
-# undef IN_MOVE_SELF
-# define IN_ACCESS 0x001
-# define IN_MODIFY 0x002
-# define IN_ATTRIB 0x004
-# define IN_CLOSE_WRITE 0x008
-# define IN_CLOSE_NOWRITE 0x010
-# define IN_OPEN 0x020
-# define IN_MOVED_FROM 0x040
-# define IN_MOVED_TO 0x080
-# define IN_CREATE 0x100
-# define IN_DELETE 0x200
-# define IN_DELETE_SELF 0x400
-# define IN_MOVE_SELF 0x800
-struct inotify_event {
- int32_t wd;
- uint32_t mask;
- uint32_t cookie;
- uint32_t len;
- /* char name[0]; */
-};
-#endif /* HAVE_INOTIFY_INIT || HAVE_INOTIFY_INIT1 */
-
-#undef IN_CLOEXEC
-#undef IN_NONBLOCK
-
-#if HAVE_INOTIFY_INIT1
-# define IN_CLOEXEC O_CLOEXEC
-# define IN_NONBLOCK O_NONBLOCK
-#endif /* HAVE_INOTIFY_INIT1 */
-
-#if HAVE_INOTIFY_INIT
-inline static int inotify_init(void) {
- return syscall(__NR_inotify_init);
-}
-#endif /* HAVE_INOTIFY_INIT */
-
-#if HAVE_INOTIFY_INIT1
-inline static int inotify_init1(int flags) {
- return syscall(__NR_inotify_init1, flags);
-}
-#endif /* HAVE_INOTIFY_INIT1 */
-
-#if HAVE_INOTIFY_ADD_WATCH
-inline static int inotify_add_watch(int fd, const char* path, uint32_t mask) {
- return syscall(__NR_inotify_add_watch, fd, path, mask);
-}
-#endif /* HAVE_INOTIFY_ADD_WATCH */
-
-#if HAVE_INOTIFY_RM_WATCH
-inline static int inotify_rm_watch(int fd, uint32_t wd) {
- return syscall(__NR_inotify_rm_watch, fd, wd);
-}
-#endif /* HAVE_INOTIFY_RM_WATCH */
/* Don't look aghast, this is exactly how glibc's basename() works. */
RB_GENERATE_STATIC(uv__inotify_watchers, uv_fs_event_s, node, compare_watchers)
-void uv__inotify_loop_init(uv_loop_t* loop) {
- RB_INIT(&loop->inotify_watchers);
- loop->inotify_fd = -1;
-}
-
-
-void uv__inotify_loop_delete(uv_loop_t* loop) {
- if (loop->inotify_fd == -1) return;
- ev_io_stop(loop->ev, &loop->inotify_read_watcher);
- close(loop->inotify_fd);
- loop->inotify_fd = -1;
-}
-
-
-#if HAVE_INOTIFY_INIT || HAVE_INOTIFY_INIT1
-
static void uv__inotify_read(EV_P_ ev_io* w, int revents);
static int new_inotify_fd(void) {
int fd;
-#if HAVE_INOTIFY_INIT1
- fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
+ fd = uv__inotify_init1(UV__IN_NONBLOCK | UV__IN_CLOEXEC);
if (fd != -1)
return fd;
if (errno != ENOSYS)
return -1;
-#endif
- if ((fd = inotify_init()) == -1)
+ if ((fd = uv__inotify_init()) == -1)
return -1;
if (uv__cloexec(fd, 1) || uv__nonblock(fd, 1)) {
static void uv__inotify_read(EV_P_ ev_io* w, int revents) {
- const struct inotify_event* e;
+ const struct uv__inotify_event* e;
uv_fs_event_t* handle;
uv_loop_t* uv_loop;
const char* filename;
/* Now we have one or more inotify_event structs. */
for (p = buf; p < buf + size; p += sizeof(*e) + e->len) {
- e = (const struct inotify_event*)p;
+ e = (const struct uv__inotify_event*)p;
events = 0;
- if (e->mask & (IN_ATTRIB|IN_MODIFY))
+ if (e->mask & (UV__IN_ATTRIB|UV__IN_MODIFY))
events |= UV_CHANGE;
- if (e->mask & ~(IN_ATTRIB|IN_MODIFY))
+ if (e->mask & ~(UV__IN_ATTRIB|UV__IN_MODIFY))
events |= UV_RENAME;
handle = find_watcher(uv_loop, e->wd);
if (init_inotify(loop)) return -1;
- events = IN_ATTRIB
- | IN_CREATE
- | IN_MODIFY
- | IN_DELETE
- | IN_DELETE_SELF
- | IN_MOVED_FROM
- | IN_MOVED_TO;
+ events = UV__IN_ATTRIB
+ | UV__IN_CREATE
+ | UV__IN_MODIFY
+ | UV__IN_DELETE
+ | UV__IN_DELETE_SELF
+ | UV__IN_MOVED_FROM
+ | UV__IN_MOVED_TO;
- wd = inotify_add_watch(loop->inotify_fd, filename, events);
+ wd = uv__inotify_add_watch(loop->inotify_fd, filename, events);
if (wd == -1) return uv__set_sys_error(loop, errno);
uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT);
}
-void uv__fs_event_destroy(uv_fs_event_t* handle) {
- inotify_rm_watch(handle->loop->inotify_fd, handle->fd);
+void uv__fs_event_close(uv_fs_event_t* handle) {
+ uv__inotify_rm_watch(handle->loop->inotify_fd, handle->fd);
remove_watcher(handle);
handle->fd = -1;
free(handle->filename);
handle->filename = NULL;
}
-
-#else /* !HAVE_INOTIFY_INIT || HAVE_INOTIFY_INIT1 */
-
-int uv_fs_event_init(uv_loop_t* loop,
- uv_fs_event_t* handle,
- const char* filename,
- uv_fs_event_cb cb,
- int flags) {
- loop->counters.fs_event_init++;
- uv__set_sys_error(loop, ENOSYS);
- return -1;
-}
-
-
-void uv__fs_event_destroy(uv_fs_event_t* handle) {
- UNREACHABLE();
-}
-
-#endif /* HAVE_INOTIFY_INIT || HAVE_INOTIFY_INIT1 */
--- /dev/null
+/* 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 "syscalls.h"
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <errno.h>
+
+#if __i386__
+# ifndef __NR_socketcall
+# define __NR_socketcall 102
+# endif
+#endif
+
+#if __arm__
+# if __thumb__ || __ARM_EABI__
+# define UV_SYSCALL_BASE 0
+# else
+# define UV_SYSCALL_BASE 0x900000
+# endif
+#endif /* __arm__ */
+
+#ifndef __NR_accept4
+# if __x86_64__
+# define __NR_accept4 288
+# elif __i386__
+ /* Nothing. Handled through socketcall(). */
+# elif __arm__
+# define __NR_accept4 (UV_SYSCALL_BASE + 366)
+# endif
+#endif /* __NR_accept4 */
+
+#ifndef __NR_inotify_init
+# if __x86_64__
+# define __NR_inotify_init 253
+# elif __i386__
+# define __NR_inotify_init 291
+# elif __arm__
+# define __NR_inotify_init (UV_SYSCALL_BASE + 316)
+# endif
+#endif /* __NR_inotify_init */
+
+#ifndef __NR_inotify_init1
+# if __x86_64__
+# define __NR_inotify_init1 294
+# elif __i386__
+# define __NR_inotify_init1 332
+# elif __arm__
+# define __NR_inotify_init1 (UV_SYSCALL_BASE + 360)
+# endif
+#endif /* __NR_inotify_init1 */
+
+#ifndef __NR_inotify_add_watch
+# if __x86_64__
+# define __NR_inotify_add_watch 254
+# elif __i386__
+# define __NR_inotify_add_watch 292
+# elif __arm__
+# define __NR_inotify_add_watch (UV_SYSCALL_BASE + 317)
+# endif
+#endif /* __NR_inotify_add_watch */
+
+#ifndef __NR_inotify_rm_watch
+# if __x86_64__
+# define __NR_inotify_rm_watch 255
+# elif __i386__
+# define __NR_inotify_rm_watch 293
+# elif __arm__
+# define __NR_inotify_rm_watch (UV_SYSCALL_BASE + 318)
+# endif
+#endif /* __NR_inotify_rm_watch */
+
+#ifndef __NR_pipe2
+# if __x86_64__
+# define __NR_pipe2 293
+# elif __i386__
+# define __NR_pipe2 331
+# elif __arm__
+# define __NR_pipe2 (UV_SYSCALL_BASE + 359)
+# endif
+#endif /* __NR_pipe2 */
+
+#ifndef __NR_recvmmsg
+# if __x86_64__
+# define __NR_recvmmsg 299
+# elif __i386__
+# define __NR_recvmmsg 337
+# elif __arm__
+# define __NR_recvmmsg (UV_SYSCALL_BASE + 365)
+# endif
+#endif /* __NR_recvmsg */
+
+#ifndef __NR_sendmmsg
+# if __x86_64__
+# define __NR_sendmmsg 307
+# elif __i386__
+# define __NR_sendmmsg 345
+# elif __arm__
+# define __NR_recvmmsg (UV_SYSCALL_BASE + 374)
+# endif
+#endif /* __NR_sendmmsg */
+
+#ifndef __NR_utimensat
+# if __x86_64__
+# define __NR_utimensat 280
+# elif __i386__
+# define __NR_utimensat 320
+# elif __arm__
+# define __NR_utimensat (UV_SYSCALL_BASE + 348)
+# endif
+#endif /* __NR_utimensat */
+
+
+int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) {
+#if __i386__
+ unsigned long args[] = {
+ (unsigned long) fd,
+ (unsigned long) addr,
+ (unsigned long) addrlen,
+ (unsigned long) flags
+ };
+ return syscall(__NR_socketcall, 18 /* SYS_ACCEPT4 */, args);
+#elif __NR_accept4
+ return syscall(__NR_accept4, fd, addr, addrlen, flags);
+#else
+ return errno = ENOSYS, -1;
+#endif
+}
+
+
+int uv__inotify_init(void) {
+#if __NR_inotify_init
+ return syscall(__NR_inotify_init);
+#else
+ return errno = ENOSYS, -1;
+#endif
+}
+
+
+int uv__inotify_init1(int flags) {
+#if __NR_inotify_init1
+ return syscall(__NR_inotify_init1, flags);
+#else
+ return errno = ENOSYS, -1;
+#endif
+}
+
+
+int uv__inotify_add_watch(int fd, const char* path, __u32 mask) {
+#if __NR_inotify_add_watch
+ return syscall(__NR_inotify_add_watch, fd, path, mask);
+#else
+ return errno = ENOSYS, -1;
+#endif
+}
+
+
+int uv__inotify_rm_watch(int fd, __s32 wd) {
+#if __NR_inotify_rm_watch
+ return syscall(__NR_inotify_rm_watch, fd, wd);
+#else
+ return errno = ENOSYS, -1;
+#endif
+}
+
+
+int uv__pipe2(int pipefd[2], int flags) {
+#if __NR_pipe2
+ return syscall(__NR_pipe2, pipefd, flags);
+#else
+ return errno = ENOSYS, -1;
+#endif
+}
+
+
+int uv__sendmmsg(int fd,
+ struct uv__mmsghdr* mmsg,
+ unsigned int vlen,
+ unsigned int flags) {
+#if __NR_sendmmsg
+ return syscall(__NR_sendmmsg, fd, mmsg, vlen, flags);
+#else
+ return errno = ENOSYS, -1;
+#endif
+}
+
+
+int uv__recvmmsg(int fd,
+ struct uv__mmsghdr* mmsg,
+ unsigned int vlen,
+ unsigned int flags,
+ struct timespec* timeout) {
+#if __NR_recvmmsg
+ return syscall(__NR_recvmmsg, fd, mmsg, vlen, flags, timeout);
+#else
+ return errno = ENOSYS, -1;
+#endif
+}
+
+
+int uv__utimesat(int dirfd,
+ const char* path,
+ const struct timespec times[2],
+ int flags)
+{
+#if __NR_utimensat
+ return syscall(__NR_utimensat, dirfd, path, times, flags);
+#else
+ return errno = ENOSYS, -1;
+#endif
+}
--- /dev/null
+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef UV_LINUX_SYSCALL_H_
+#define UV_LINUX_SYSCALL_H_
+
+#undef _GNU_SOURCE
+#define _GNU_SOURCE
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <linux/types.h>
+
+#define UV__O_NONBLOCK 0x800
+#define UV__O_CLOEXEC 0x80000
+
+#define UV__SOCK_CLOEXEC UV__O_CLOEXEC
+#define UV__SOCK_NONBLOCK UV__O_NONBLOCK
+
+#define UV__IN_CLOEXEC UV__O_CLOEXEC
+#define UV__IN_NONBLOCK UV__O_NONBLOCK
+
+#define UV__IN_ACCESS 0x001
+#define UV__IN_MODIFY 0x002
+#define UV__IN_ATTRIB 0x004
+#define UV__IN_CLOSE_WRITE 0x008
+#define UV__IN_CLOSE_NOWRITE 0x010
+#define UV__IN_OPEN 0x020
+#define UV__IN_MOVED_FROM 0x040
+#define UV__IN_MOVED_TO 0x080
+#define UV__IN_CREATE 0x100
+#define UV__IN_DELETE 0x200
+#define UV__IN_DELETE_SELF 0x400
+#define UV__IN_MOVE_SELF 0x800
+
+struct uv__inotify_event {
+ __s32 wd;
+ __u32 mask;
+ __u32 cookie;
+ __u32 len;
+ /* char name[0]; */
+};
+
+struct uv__mmsghdr {
+ struct msghdr msg_hdr;
+ unsigned int msg_len;
+};
+
+int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags);
+int uv__inotify_init(void);
+int uv__inotify_init1(int flags);
+int uv__inotify_add_watch(int fd, const char* path, __u32 mask);
+int uv__inotify_rm_watch(int fd, __s32 wd);
+int uv__pipe2(int pipefd[2], int flags);
+int uv__recvmmsg(int fd,
+ struct uv__mmsghdr* mmsg,
+ unsigned int vlen,
+ unsigned int flags,
+ struct timespec* timeout);
+int uv__sendmmsg(int fd,
+ struct uv__mmsghdr* mmsg,
+ unsigned int vlen,
+ unsigned int flags);
+int uv__utimesat(int dirfd,
+ const char* path,
+ const struct timespec times[2],
+ int flags);
+
+#endif /* UV_LINUX_SYSCALL_H_ */
--- /dev/null
+/* 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 "tree.h"
+#include "internal.h"
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+int uv__loop_init(uv_loop_t* loop, int default_loop) {
+#if HAVE_KQUEUE
+ int flags = EVBACKEND_KQUEUE;
+#else
+ int flags = EVFLAG_AUTO;
+#endif
+ RB_INIT(&loop->uv_ares_handles_);
+ loop->endgame_handles = NULL;
+ loop->ev = (default_loop ? ev_default_loop : ev_loop_new)(flags);
+ ev_set_userdata(loop->ev, loop);
+ eio_channel_init(&loop->uv_eio_channel, loop);
+#if __linux__
+ RB_INIT(&loop->inotify_watchers);
+ loop->inotify_fd = -1;
+#endif
+ return 0;
+}
+
+
+void uv__loop_delete(uv_loop_t* loop) {
+ uv_ares_destroy(loop, loop->channel);
+ ev_loop_destroy(loop->ev);
+#if __linux__
+ if (loop->inotify_fd == -1) return;
+ ev_io_stop(loop->ev, &loop->inotify_read_watcher);
+ close(loop->inotify_fd);
+ loop->inotify_fd = -1;
+#endif
+}
}
-int uv_pipe_cleanup(uv_pipe_t* handle) {
- int saved_errno;
- int status;
-
- saved_errno = errno;
- status = -1;
-
+void uv__pipe_close(uv_pipe_t* handle) {
if (handle->pipe_fname) {
/*
* Unlink the file system entity before closing the file descriptor.
* Doing it the other way around introduces a race where our process
* unlinks a socket with the same name that's just been created by
* another thread or process.
- *
- * This is less of an issue now that we attach a file lock
- * to the socket but it's still a best practice.
*/
unlink(handle->pipe_fname);
free((void*)handle->pipe_fname);
}
- errno = saved_errno;
- return status;
+ uv__stream_close((uv_stream_t*)handle);
}
--- /dev/null
+/* 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"
+
+
+static void uv__prepare(EV_P_ ev_prepare* w, int revents) {
+ uv_prepare_t* prepare = container_of(w, uv_prepare_t, prepare_watcher);
+
+ if (prepare->prepare_cb) {
+ prepare->prepare_cb(prepare, 0);
+ }
+}
+
+
+int uv_prepare_init(uv_loop_t* loop, uv_prepare_t* prepare) {
+ uv__handle_init(loop, (uv_handle_t*)prepare, UV_PREPARE);
+ loop->counters.prepare_init++;
+
+ ev_prepare_init(&prepare->prepare_watcher, uv__prepare);
+ prepare->prepare_cb = NULL;
+
+ return 0;
+}
+
+
+int uv_prepare_start(uv_prepare_t* prepare, uv_prepare_cb cb) {
+ int was_active = ev_is_active(&prepare->prepare_watcher);
+
+ prepare->prepare_cb = cb;
+
+ ev_prepare_start(prepare->loop->ev, &prepare->prepare_watcher);
+
+ if (!was_active) {
+ ev_unref(prepare->loop->ev);
+ }
+
+ return 0;
+}
+
+
+int uv_prepare_stop(uv_prepare_t* prepare) {
+ int was_active = ev_is_active(&prepare->prepare_watcher);
+
+ ev_prepare_stop(prepare->loop->ev, &prepare->prepare_watcher);
+
+ if (was_active) {
+ ev_ref(prepare->loop->ev);
+ }
+ return 0;
+}
+
+
+int uv__prepare_active(const uv_prepare_t* handle) {
+ return ev_is_active(&handle->prepare_watcher);
+}
+
+
+void uv__prepare_close(uv_prepare_t* handle) {
+ uv_prepare_stop(handle);
+}
int uv__make_pipe(int fds[2], int flags) {
-#if HAVE_SYS_PIPE2
+#if __linux__
int fl;
fl = O_CLOEXEC;
if (flags & UV__F_NONBLOCK)
fl |= O_NONBLOCK;
- if (sys_pipe2(fds, fl) == 0)
+ if (uv__pipe2(fds, fl) == 0)
return 0;
if (errno != ENOSYS)
return -1;
-
- /* errno == ENOSYS so maybe the kernel headers lied about
- * the availability of pipe2(). This can happen if people
- * build libuv against newer kernel headers than the kernel
- * they actually run the software on.
- */
#endif
if (pipe(fds))
return uv_ok_;
}
}
+
+
+void uv__process_close(uv_process_t* handle) {
+ ev_child_stop(handle->loop->ev, &handle->child_watcher);
+}
int uv_is_writable(uv_stream_t* stream) {
return stream->flags & UV_WRITABLE;
}
+
+
+void uv__stream_close(uv_stream_t* handle) {
+ uv_read_stop(handle);
+ ev_io_stop(handle->loop->ev, &handle->write_watcher);
+
+ close(handle->fd);
+ handle->fd = -1;
+
+ if (handle->accepted_fd >= 0) {
+ close(handle->accepted_fd);
+ handle->accepted_fd = -1;
+ }
+
+ assert(!ev_is_active(&handle->read_watcher));
+ assert(!ev_is_active(&handle->write_watcher));
+}
#include <sys/time.h>
#include <unistd.h>
#include <kstat.h>
+#include <fcntl.h>
#if HAVE_PORTS_FS
# include <sys/port.h>
}
-void uv__fs_event_destroy(uv_fs_event_t* handle) {
+void uv__fs_event_close(uv_fs_event_t* handle) {
ev_ref(handle->loop->ev);
ev_io_stop(handle->loop->ev, &handle->event_watcher);
close(handle->fd);
}
-void uv__fs_event_destroy(uv_fs_event_t* handle) {
+void uv__fs_event_close(uv_fs_event_t* handle) {
UNREACHABLE();
}
uv_err_t uv_resident_set_memory(size_t* rss) {
- pid_t pid = getpid();
psinfo_t psinfo;
- char pidpath[1024];
- FILE *f;
+ uv_err_t err;
+ int fd;
- sprintf(pidpath, "/proc/%d/psinfo", (int)pid);
-
- f = fopen(pidpath, "r");
- if (!f) return uv__new_sys_error(errno);
-
- if (fread(&psinfo, sizeof(psinfo_t), 1, f) != 1) {
- fclose (f);
+ fd = open("/proc/self/psinfo", O_RDONLY);
+ if (fd == -1)
return uv__new_sys_error(errno);
- }
- /* XXX correct? */
+ err = uv_ok_;
- *rss = (size_t) psinfo.pr_rssize * 1024;
+ if (read(fd, &psinfo, sizeof(psinfo)) == sizeof(psinfo))
+ *rss = (size_t)psinfo.pr_rssize * 1024;
+ else
+ err = uv__new_sys_error(EINVAL);
- fclose (f);
+ close(fd);
- return uv_ok_;
+ return err;
}
--- /dev/null
+/* 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 <assert.h>
+
+
+static int uv__timer_repeating(const uv_timer_t* timer) {
+ return timer->flags & UV_TIMER_REPEAT;
+}
+
+
+static void uv__timer_cb(EV_P_ ev_timer* w, int revents) {
+ uv_timer_t* timer = container_of(w, uv_timer_t, timer_watcher);
+
+ assert(uv__timer_active(timer));
+
+ if (!uv__timer_repeating(timer)) {
+ timer->flags &= ~UV_TIMER_ACTIVE;
+ ev_ref(EV_A);
+ }
+
+ if (timer->timer_cb) {
+ timer->timer_cb(timer, 0);
+ }
+}
+
+
+int uv_timer_init(uv_loop_t* loop, uv_timer_t* timer) {
+ uv__handle_init(loop, (uv_handle_t*)timer, UV_TIMER);
+ loop->counters.timer_init++;
+
+ ev_init(&timer->timer_watcher, uv__timer_cb);
+
+ return 0;
+}
+
+
+int uv_timer_start(uv_timer_t* timer, uv_timer_cb cb, int64_t timeout,
+ int64_t repeat) {
+ if (uv__timer_active(timer)) {
+ return -1;
+ }
+
+ timer->timer_cb = cb;
+ timer->flags |= UV_TIMER_ACTIVE;
+
+ if (repeat)
+ timer->flags |= UV_TIMER_REPEAT;
+ else
+ timer->flags &= ~UV_TIMER_REPEAT;
+
+ ev_timer_set(&timer->timer_watcher, timeout / 1000.0, repeat / 1000.0);
+ ev_timer_start(timer->loop->ev, &timer->timer_watcher);
+ ev_unref(timer->loop->ev);
+
+ return 0;
+}
+
+
+int uv_timer_stop(uv_timer_t* timer) {
+ if (uv__timer_active(timer)) {
+ ev_ref(timer->loop->ev);
+ }
+
+ timer->flags &= ~(UV_TIMER_ACTIVE | UV_TIMER_REPEAT);
+ ev_timer_stop(timer->loop->ev, &timer->timer_watcher);
+
+ return 0;
+}
+
+
+int uv_timer_again(uv_timer_t* timer) {
+ if (!uv__timer_active(timer)) {
+ uv__set_artificial_error(timer->loop, UV_EINVAL);
+ return -1;
+ }
+
+ assert(uv__timer_repeating(timer));
+ ev_timer_again(timer->loop->ev, &timer->timer_watcher);
+ return 0;
+}
+
+
+void uv_timer_set_repeat(uv_timer_t* timer, int64_t repeat) {
+ assert(timer->type == UV_TIMER);
+ timer->timer_watcher.repeat = repeat / 1000.0;
+
+ if (repeat)
+ timer->flags |= UV_TIMER_REPEAT;
+ else
+ timer->flags &= ~UV_TIMER_REPEAT;
+}
+
+
+int64_t uv_timer_get_repeat(uv_timer_t* timer) {
+ assert(timer->type == UV_TIMER);
+ return (int64_t)(1000 * timer->timer_watcher.repeat);
+}
+
+
+int uv__timer_active(const uv_timer_t* timer) {
+ return timer->flags & UV_TIMER_ACTIVE;
+}
+
+
+void uv__timer_close(uv_timer_t* handle) {
+ uv_timer_stop(handle);
+}
}
-void uv__udp_start_close(uv_udp_t* handle) {
+void uv__udp_close(uv_udp_t* handle) {
uv__udp_stop_write_watcher(handle);
uv__udp_stop_read_watcher(handle);
close(handle->fd);
#include "ares/inet_net_pton.h"
#include "ares/inet_ntop.h"
+#define XX(uc, lc) case UV_##uc: return sizeof(uv_##lc##_t);
+
+size_t uv_handle_size(uv_handle_type type) {
+ switch (type) {
+ UV_HANDLE_TYPE_MAP(XX)
+ default:
+ return -1;
+ }
+}
+
+size_t uv_req_size(uv_req_type type) {
+ switch(type) {
+ UV_REQ_TYPE_MAP(XX)
+ default:
+ return -1;
+ }
+}
+
+#undef XX
size_t uv_strlcpy(char* dst, const char* src, size_t size) {
size_t n;
struct uv_ares_task_s {
UV_HANDLE_FIELDS
- UV_ARES_TASK_PRIVATE_FIELDS
+#if _WIN32
+ struct uv_req_s ares_req;
+ SOCKET sock;
+ HANDLE h_wait;
+ WSAEVENT h_event;
+ HANDLE h_close_event;
+#else
+ int sock;
+ ev_io read_watcher;
+ ev_io write_watcher;
+#endif
RB_ENTRY(uv_ares_task_s) node;
};
}
+int uv_is_closing(uv_handle_t* handle) {
+ return handle->flags & (UV_HANDLE_CLOSING | UV_HANDLE_CLOSED);
+}
+
+
void uv_want_endgame(uv_loop_t* loop, uv_handle_t* handle) {
if (!(handle->flags & UV_HANDLE_ENDGAME_QUEUED)) {
handle->flags |= UV_HANDLE_ENDGAME_QUEUED;
int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid,
LPWSAPROTOCOL_INFOW protocol_info);
+void uv_tcp_close(uv_tcp_t* tcp);
+
/*
* UDP
int addrsize) {
DWORD err;
int r;
- SOCKET sock;
if (handle->socket == INVALID_SOCKET) {
- sock = socket(domain, SOCK_STREAM, 0);
+ SOCKET sock = socket(domain, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET) {
uv__set_sys_error(handle->loop, WSAGetLastError());
return -1;
int addrsize,
unsigned int flags) {
int r;
- SOCKET sock;
DWORD no = 0, yes = 1;
if ((flags & UV_UDP_IPV6ONLY) && domain != AF_INET6) {
}
if (handle->socket == INVALID_SOCKET) {
- sock = socket(domain, SOCK_DGRAM, 0);
+ SOCKET sock = socket(domain, SOCK_DGRAM, 0);
if (sock == INVALID_SOCKET) {
uv__set_sys_error(handle->loop, WSAGetLastError());
return -1;
/* TODO: how to handle errors? This may fail if there is no ipv4 stack */
/* available, or when run on XP/2003 which have no support for dualstack */
/* sockets. For now we're silently ignoring the error. */
- setsockopt(sock,
+ setsockopt(handle->socket,
IPPROTO_IPV6,
IPV6_V6ONLY,
(char*) &no,
sizeof no);
}
- r = setsockopt(sock,
+ r = setsockopt(handle->socket,
SOL_SOCKET,
SO_REUSEADDR,
(char*) &yes,
uv_err_t uv_uptime(double* uptime) {
- *uptime = (double)GetTickCount()/1000.0;
- return uv_ok_;
+ uv_err_t err;
+ PERF_DATA_BLOCK *dataBlock = NULL;
+ PERF_OBJECT_TYPE *objType;
+ PERF_COUNTER_DEFINITION *counterDef;
+ PERF_COUNTER_DEFINITION *counterDefUptime = NULL;
+ DWORD dataSize = 4096;
+ DWORD getSize;
+ LONG lError = ERROR_MORE_DATA;
+ uint64_t upsec;
+ unsigned int i;
+ BYTE *counterData;
+
+ *uptime = 0;
+
+ while (lError == ERROR_MORE_DATA) {
+ if (dataBlock) {
+ free(dataBlock);
+ }
+ dataBlock = (PERF_DATA_BLOCK*)malloc(dataSize);
+ if (!dataBlock) {
+ uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ }
+ getSize = dataSize;
+
+ lError = RegQueryValueExW(HKEY_PERFORMANCE_DATA, "2", NULL, NULL,
+ (BYTE*)dataBlock, &getSize);
+ if (lError != ERROR_SUCCESS && getSize > 0) {
+ if (wcsncmp(dataBlock->Signature, "PERF", 4) == 0) {
+ break;
+ }
+ } else if (lError != ERROR_SUCCESS && lError != ERROR_MORE_DATA) {
+ err = uv__new_sys_error(GetLastError());
+ goto done;
+ }
+
+ dataSize += 1024;
+ }
+
+ RegCloseKey(HKEY_PERFORMANCE_DATA);
+
+ objType = (PERF_OBJECT_TYPE*)((BYTE*)dataBlock + dataBlock->HeaderLength);
+ counterDef = (PERF_COUNTER_DEFINITION*)((BYTE*)objType + objType->HeaderLength);
+
+ for (i = 0; i < objType->NumCounters; ++i) {
+ if (counterDef->CounterNameTitleIndex == 674) {
+ counterDefUptime = counterDef;
+ break;
+ }
+ counterDef = (PERF_COUNTER_DEFINITION*)((BYTE*)counterDef + counterDef->ByteLength);
+ }
+
+ counterData = (BYTE*)objType + objType->DefinitionLength;
+ counterData += counterDefUptime->CounterOffset;
+
+ upsec = *((uint64_t*)counterData);
+ *uptime = ((objType->PerfTime.QuadPart - upsec) / objType->PerfFreq.QuadPart);
+ err = uv_ok_;
+
+done:
+ if (dataBlock) {
+ free(dataBlock);
+ }
+
+ return err;
}
uv_pipe_open(&ctx.channel, 0);
ASSERT(uv_is_readable((uv_stream_t*)&ctx.channel));
ASSERT(uv_is_writable((uv_stream_t*)&ctx.channel));
+ ASSERT(!uv_is_closing((uv_handle_t*)&ctx.channel));
r = uv_read2_start((uv_stream_t*)&ctx.channel, alloc_cb, read2_cb);
ASSERT(r == 0);
ASSERT(uv_is_readable((uv_stream_t*) &channel));
ASSERT(uv_is_writable((uv_stream_t*) &channel));
+ ASSERT(!uv_is_closing((uv_handle_t*) &channel));
r = uv_tcp_init(uv_default_loop(), &tcp_server);
ASSERT(r == 0);
ASSERT(uv_is_readable((uv_stream_t*)&channel));
ASSERT(uv_is_writable((uv_stream_t*)&channel));
+ ASSERT(!uv_is_closing((uv_handle_t*)&channel));
r = uv_tcp_init(uv_default_loop(), &tcp_server);
ASSERT(r == 0);
ASSERT(uv_is_readable(req->handle));
ASSERT(uv_is_writable(req->handle));
+ ASSERT(!uv_is_closing((uv_handle_t *)req->handle));
pinger_write_ping(pinger);
ASSERT(connect_cb_called == 1);
return 0;
-}
\ No newline at end of file
+}
err = uv_uptime(&uptime);
ASSERT(UV_OK == err.code);
+ ASSERT(uptime > 0);
fprintf(stderr, "uv_uptime: %f\n", uptime);
err = uv_cpu_info(&cpus, &count);
r = uv_shutdown(&shutdown_req, req->handle, shutdown_cb);
ASSERT(r == 0);
+ ASSERT(!uv_is_closing((uv_handle_t*) req->handle));
uv_close((uv_handle_t*) req->handle, close_cb);
+ ASSERT(uv_is_closing((uv_handle_t*) req->handle));
connect_cb_called++;
}
'include/uv-private/ev.h',
'include/uv-private/ngx-queue.h',
'include/uv-private/uv-unix.h',
- 'src/unix/core.c',
- 'src/unix/uv-eio.c',
- 'src/unix/uv-eio.h',
- 'src/unix/fs.c',
- 'src/unix/udp.c',
- 'src/unix/tcp.c',
- 'src/unix/pipe.c',
- 'src/unix/tty.c',
- 'src/unix/stream.c',
+ 'src/unix/async.c',
'src/unix/cares.c',
+ 'src/unix/check.c',
+ 'src/unix/core.c',
'src/unix/dl.c',
- 'src/unix/error.c',
- 'src/unix/thread.c',
- 'src/unix/process.c',
- 'src/unix/internal.h',
'src/unix/eio/ecb.h',
'src/unix/eio/eio.c',
'src/unix/eio/xthread.h',
+ 'src/unix/error.c',
'src/unix/ev/ev.c',
'src/unix/ev/ev_vars.h',
'src/unix/ev/ev_wrap.h',
'src/unix/ev/event.h',
+ 'src/unix/fs.c',
+ 'src/unix/idle.c',
+ 'src/unix/internal.h',
+ 'src/unix/loop.c',
+ 'src/unix/pipe.c',
+ 'src/unix/prepare.c',
+ 'src/unix/process.c',
+ 'src/unix/stream.c',
+ 'src/unix/tcp.c',
+ 'src/unix/thread.c',
+ 'src/unix/timer.c',
+ 'src/unix/tty.c',
+ 'src/unix/udp.c',
+ 'src/unix/uv-eio.c',
+ 'src/unix/uv-eio.h',
],
'include_dirs': [ 'src/unix/ev', ],
'libraries': [ '-lm' ]
],
},
'defines': [
+ '_DARWIN_USE_64_BIT_INODE=1',
'EV_CONFIG_H="config_darwin.h"',
'EIO_CONFIG_H="config_darwin.h"',
]
'sources': [
'src/unix/linux/core.c',
'src/unix/linux/inotify.c',
+ 'src/unix/linux/syscalls.c',
+ 'src/unix/linux/syscalls.h',
],
'defines': [
'EV_CONFIG_H="config_linux.h"',