diff --git a/include/uv.h b/include/uv.h index 02397dd0..ab2f36fc 100644 --- a/include/uv.h +++ b/include/uv.h @@ -842,6 +842,16 @@ UV_EXTERN int uv_pipe_connect2(uv_connect_t* req, size_t namelen, unsigned int flags, uv_connect_cb cb); +#ifdef CONFIG_NET_RPMSG +UV_EXTERN int uv_pipe_rpmsg_bind(uv_pipe_t* handle, + const char* name, + const char* cpu_name); +UV_EXTERN void uv_pipe_rpmsg_connect(uv_connect_t* req, + uv_pipe_t* handle, + const char* name, + const char* cpu_name, + uv_connect_cb cb); +#endif UV_EXTERN int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size); @@ -1826,12 +1836,14 @@ UV_EXTERN int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg); typedef enum { UV_THREAD_NO_FLAGS = 0x00, - UV_THREAD_HAS_STACK_SIZE = 0x01 + UV_THREAD_HAS_STACK_SIZE = 0x01, + UV_THREAD_HAS_PRIORITY = 0x02 } uv_thread_create_flags; struct uv_thread_options_s { unsigned int flags; size_t stack_size; + int priority; /* More fields may be added at any time. */ }; diff --git a/include/uv/unix.h b/include/uv/unix.h index 09f88a56..4962b932 100644 --- a/include/uv/unix.h +++ b/include/uv/unix.h @@ -66,6 +66,7 @@ defined(__MSYS__) || \ defined(__HAIKU__) || \ defined(__QNX__) || \ + defined(__NuttX__) || \ defined(__GNU__) # include "uv/posix.h" #endif diff --git a/src/fs-poll.c b/src/fs-poll.c index 1bac1c56..ea4a17cd 100644 --- a/src/fs-poll.c +++ b/src/fs-poll.c @@ -53,7 +53,7 @@ static void poll_cb(uv_fs_t* req); static void timer_cb(uv_timer_t* timer); static void timer_close_cb(uv_handle_t* handle); -static uv_stat_t zero_statbuf; +static const uv_stat_t zero_statbuf; int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle) { diff --git a/src/random.c b/src/random.c index e75f77de..feef5a44 100644 --- a/src/random.c +++ b/src/random.c @@ -31,7 +31,7 @@ static int uv__random(void* buf, size_t buflen) { int rc; -#if defined(__PASE__) +#if defined(__PASE__) || defined(__NuttX__) rc = uv__random_readpath("/dev/urandom", buf, buflen); #elif defined(_AIX) || defined(__QNX__) rc = uv__random_readpath("/dev/random", buf, buflen); diff --git a/src/threadpool.c b/src/threadpool.c index dbef67f2..94414212 100644 --- a/src/threadpool.c +++ b/src/threadpool.c @@ -20,6 +20,7 @@ */ #include "uv-common.h" +#include "uv-global.h" #if !defined(_WIN32) # include "unix/internal.h" @@ -29,18 +30,6 @@ #define MAX_THREADPOOL_SIZE 1024 -static uv_once_t once = UV_ONCE_INIT; -static uv_cond_t cond; -static uv_mutex_t mutex; -static unsigned int idle_threads; -static unsigned int slow_io_work_running; -static unsigned int nthreads; -static uv_thread_t* threads; -static uv_thread_t default_threads[4]; -static struct uv__queue exit_message; -static struct uv__queue wq; -static struct uv__queue run_slow_work_message; -static struct uv__queue slow_io_pending_wq; static unsigned int slow_work_thread_threshold(void) { return (nthreads + 1) / 2; @@ -68,16 +57,16 @@ static void worker(void* arg) { /* Keep waiting while either no work is present or only slow I/O and we're at the threshold for that. */ - while (uv__queue_empty(&wq) || - (uv__queue_head(&wq) == &run_slow_work_message && - uv__queue_next(&run_slow_work_message) == &wq && + while (uv__queue_empty(&lwq) || + (uv__queue_head(&lwq) == &run_slow_work_message && + uv__queue_next(&run_slow_work_message) == &lwq && slow_io_work_running >= slow_work_thread_threshold())) { idle_threads += 1; uv_cond_wait(&cond, &mutex); idle_threads -= 1; } - q = uv__queue_head(&wq); + q = uv__queue_head(&lwq); if (q == &exit_message) { uv_cond_signal(&cond); uv_mutex_unlock(&mutex); @@ -92,7 +81,7 @@ static void worker(void* arg) { /* If we're at the slow I/O threshold, re-schedule until after all other work in the queue is done. */ if (slow_io_work_running >= slow_work_thread_threshold()) { - uv__queue_insert_tail(&wq, q); + uv__queue_insert_tail(&lwq, q); continue; } @@ -110,7 +99,7 @@ static void worker(void* arg) { /* If there is more slow I/O work, schedule it to be run as well. */ if (!uv__queue_empty(&slow_io_pending_wq)) { - uv__queue_insert_tail(&wq, &run_slow_work_message); + uv__queue_insert_tail(&lwq, &run_slow_work_message); if (idle_threads > 0) uv_cond_signal(&cond); } @@ -153,7 +142,7 @@ static void post(struct uv__queue* q, enum uv__work_kind kind) { q = &run_slow_work_message; } - uv__queue_insert_tail(&wq, q); + uv__queue_insert_tail(&lwq, q); if (idle_threads > 0) uv_cond_signal(&cond); uv_mutex_unlock(&mutex); @@ -191,11 +180,28 @@ void uv__threadpool_cleanup(void) { static void init_threads(void) { - uv_thread_options_t config; unsigned int i; const char* val; uv_sem_t sem; + const uv_thread_options_t params = { +#ifdef DEF_THREADPOOL_STACKSIZE + UV_THREAD_HAS_STACK_SIZE | +#endif +#ifdef DEF_THREADPOOL_PRIORITY + UV_THREAD_HAS_PRIORITY | +#endif + UV_THREAD_NO_FLAGS, +#ifdef DEF_THREADPOOL_STACKSIZE + DEF_THREADPOOL_STACKSIZE, +#else + 0, +#endif +#ifdef DEF_THREADPOOL_PRIORITY + DEF_THREADPOOL_PRIORITY +#endif + }; + nthreads = ARRAY_SIZE(default_threads); val = getenv("UV_THREADPOOL_SIZE"); if (val != NULL) @@ -220,18 +226,15 @@ static void init_threads(void) { if (uv_mutex_init(&mutex)) abort(); - uv__queue_init(&wq); + uv__queue_init(&lwq); uv__queue_init(&slow_io_pending_wq); uv__queue_init(&run_slow_work_message); if (uv_sem_init(&sem, 0)) abort(); - config.flags = UV_THREAD_HAS_STACK_SIZE; - config.stack_size = 8u << 20; /* 8 MB */ - for (i = 0; i < nthreads; i++) - if (uv_thread_create_ex(threads + i, &config, worker, &sem)) + if (uv_thread_create_ex(threads + i, ¶ms, worker, &sem)) abort(); for (i = 0; i < nthreads; i++) diff --git a/src/unix/core.c b/src/unix/core.c index 25c5181f..6ff617af 100644 --- a/src/unix/core.c +++ b/src/unix/core.c @@ -60,7 +60,7 @@ # include # include /* _NSGetExecutablePath */ # define environ (*_NSGetEnviron()) -#else /* defined(__APPLE__) && !TARGET_OS_IPHONE */ +#elif !defined(__NuttX__) /* defined(__APPLE__) && !TARGET_OS_IPHONE */ extern char** environ; #endif /* !(defined(__APPLE__) && !TARGET_OS_IPHONE) */ @@ -1000,7 +1000,7 @@ int uv_getrusage(uv_rusage_t* rusage) { rusage->ru_stime.tv_sec = usage.ru_stime.tv_sec; rusage->ru_stime.tv_usec = usage.ru_stime.tv_usec; -#if !defined(__MVS__) && !defined(__HAIKU__) +#if !defined(__MVS__) && !defined(__HAIKU__) && !defined(__NuttX__) rusage->ru_maxrss = usage.ru_maxrss; rusage->ru_ixrss = usage.ru_ixrss; rusage->ru_idrss = usage.ru_idrss; diff --git a/src/unix/fs.c b/src/unix/fs.c index 6b051c12..0d4c6014 100644 --- a/src/unix/fs.c +++ b/src/unix/fs.c @@ -56,7 +56,7 @@ #endif /* preadv() and pwritev() were added in Android N (level 24) */ -#if defined(__linux__) && !(defined(__ANDROID__) && __ANDROID_API__ < 24) +#if (defined(__linux__) || defined(__NuttX__)) && !(defined(__ANDROID__) && __ANDROID_API__ < 24) # define TRY_PREADV 1 #endif diff --git a/src/unix/internal.h b/src/unix/internal.h index fe588513..ddc744b2 100644 --- a/src/unix/internal.h +++ b/src/unix/internal.h @@ -215,6 +215,7 @@ struct uv__statx { defined(__FreeBSD__) || \ defined(__linux__) || \ defined(__OpenBSD__) || \ + defined(__NuttX__) || \ defined(__NetBSD__) #define uv__nonblock uv__nonblock_ioctl #define UV__NONBLOCK_IS_IOCTL 1 diff --git a/src/unix/loop.c b/src/unix/loop.c index a9468e8e..30ecc532 100644 --- a/src/unix/loop.c +++ b/src/unix/loop.c @@ -220,8 +220,10 @@ int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap) { if (option != UV_LOOP_BLOCK_SIGNAL) return UV_ENOSYS; +#ifdef SIGPROF if (va_arg(ap, int) != SIGPROF) return UV_EINVAL; +#endif loop->flags |= UV_LOOP_BLOCK_SIGPROF; return 0; diff --git a/src/unix/nuttx.c b/src/unix/nuttx.c new file mode 100644 index 00000000..298bd2f8 --- /dev/null +++ b/src/unix/nuttx.c @@ -0,0 +1,303 @@ +/* Copyright Xiaomi, 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. + */ + +/* We lean on the fact that POLL{IN,OUT,ERR,HUP} correspond with their + * EPOLL* counterparts. We use the POLL* variants in this file because that + * is what libuv uses elsewhere. + */ + +#include "internal.h" +#include "uv.h" +#include "uv-global.h" + +#include +#include +#include +#include +#include +#include + +#include + +int uv_exepath(char* buffer, size_t* size) { + return UV_ENOTSUP; +} + +char** uv_setup_args(int argc, char** argv) { + return argv; +} + +void uv__process_title_cleanup(void) { +} + +int uv_set_process_title(const char* title) { + return UV__ERR(pthread_setname_np(pthread_self(), title)); +} + +int uv_get_process_title(char* buffer, size_t size) { + return UV__ERR(pthread_getname_np(pthread_self(), buffer, size)); +} + +uint64_t uv_get_constrained_memory(void) { + return 0; /* Memory constraints are unknown. */ +} + +uint64_t uv_get_available_memory(void) { + return uv_get_free_memory(); +} + +int uv_resident_set_memory(size_t* rss) { + struct sysinfo info; + int ret; + + ret = sysinfo(&info); + if (ret >= 0) + { + *rss = (info.totalram - info.freeram) * info.mem_unit; + } + else + { + ret = UV__ERR(errno); + } + + return ret; +} + +int uv_uptime(double* uptime) { + struct sysinfo info; + int ret; + + + ret = sysinfo(&info); + if (ret >= 0) + { + *uptime = info.uptime; + } + else + { + ret = UV__ERR(errno); + } + + return ret; +} + +int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { + *count = sysconf(_SC_NPROCESSORS_ONLN); + *cpu_infos = uv__calloc(*count, sizeof(uv_cpu_info_t)); + if (!*cpu_infos) { + return UV_ENOMEM; + } + + return 0; +} + +#ifndef CONFIG_NETDEV_IFINDEX +unsigned int if_nametoindex(const char *ifname) { + return 0; +} + +int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { + return UV_ENOSYS; +} + +void uv_free_interface_addresses(uv_interface_address_t* addresses, int count) { +} +#else +static int uv__ifaddr_exclude(struct ifaddrs *ent) { + if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) + return 1; + if (ent->ifa_addr == NULL) + return 1; + return 0; +} + +int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { + struct ifaddrs* addrs; + struct ifaddrs* ent; + uv_interface_address_t* address; + + *count = 0; + *addresses = NULL; + + if (getifaddrs(&addrs) != 0) + return UV__ERR(errno); + + /* Count the number of interfaces */ + for (ent = addrs; ent != NULL; ent = ent->ifa_next) { + if (uv__ifaddr_exclude(ent)) + continue; + (*count)++; + } + + if (*count == 0) { + freeifaddrs(addrs); + return 0; + } + + /* Make sure the memory is initiallized to zero using calloc() */ + *addresses = uv__calloc(*count, sizeof(**addresses)); + if (*addresses == NULL) { + freeifaddrs(addrs); + return UV_ENOMEM; + } + + address = *addresses; + for (ent = addrs; ent != NULL; ent = ent->ifa_next) { + if (uv__ifaddr_exclude(ent)) + continue; + + address->name = uv__strdup(ent->ifa_name); + + if (ent->ifa_addr->sa_family == AF_INET6) { + address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr); + } else { + address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr); + } + + if (ent->ifa_netmask) { + if (ent->ifa_netmask->sa_family == AF_INET6) { + address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask); + } else { + address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask); + } + } + + if (ent->ifa_data) { + struct sockaddr* addr = ent->ifa_data; + memcpy(address->phys_addr, addr->sa_data, sizeof(address->phys_addr)); + } + + address->is_internal = !strcmp(address->name, "lo"); + address++; + } + + freeifaddrs(addrs); + return 0; +} + +void uv_free_interface_addresses(uv_interface_address_t* addresses, int count) { + int i; + + for (i = 0; i < count; i++) { + uv__free(addresses[i].name); + } + + uv__free(addresses); +} +#endif + +#ifndef CONFIG_NET_SOCKOPTS +int getsockopt(int sockfd, int level, int option, void *value, socklen_t *value_len) { + if (option == SO_ERROR) { + *(int *)value = UV_ENOTSUP; + } + + return UV_ENOTSUP; +} +#endif + +#ifndef CONFIG_NET +int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { + return UV_ENOTSUP; +} + +ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags) { + return UV_ENOTSUP; +} + +ssize_t sendmsg(int sockfd, struct msghdr *msg, int flags) { + return UV_ENOTSUP; +} + +int shutdown(int sockfd, int how) { + return UV_ENOTSUP; +} +#endif + +#ifndef CONFIG_NET_TCP +int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) { + return UV_ENOTSUP; +} + +void uv__tcp_close(uv_tcp_t* handle) { +} + +int uv__tcp_nodelay(int fd, int on) { + return UV_ENOTSUP; +} + +int uv__tcp_keepalive(int fd, int on, unsigned int delay) { + return UV_ENOTSUP; +} +#endif + +#ifndef CONFIG_NET_UDP +int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) { + return UV_ENOTSUP; +} + +void uv__udp_close(uv_udp_t* handle) { +} + +void uv__udp_finish_close(uv_udp_t* handle) { +} +#endif + +#if CONFIG_TLS_TASK_NELEM == 0 +# error "libuv depends on CONFIG_TLS_TASK_NELEM, please enable it by menuconfig" +#endif + +#undef once +#undef uv__signal_global_init_guard +#undef uv__signal_lock_pipefd + +static void uv__global_free(void* global) { + if (global) { + uv_library_shutdown(); + uv__free(global); + } +} + +uv__global_t* uv__global_get(void) { + static int index = -1; + static const uv_once_t once = UV_ONCE_INIT; + uv__global_t* global = NULL; + + if (index < 0) { + index = task_tls_alloc(uv__global_free); + } + + if (index >= 0) { + global = (uv__global_t*)task_tls_get_value(index); + if (global == NULL) { + global = (uv__global_t*)uv__calloc(1, sizeof(uv__global_t)); + if (global) { + global->once = once; + global->uv__signal_global_init_guard = once; + global->uv__signal_lock_pipefd[0] = -1; + global->uv__signal_lock_pipefd[1] = -1; + task_tls_set_value(index, (uintptr_t)global); + } + } + } + + ASSERT(global != NULL); + return global; +} diff --git a/src/unix/pipe.c b/src/unix/pipe.c index d332f351..7f1deeb1 100644 --- a/src/unix/pipe.c +++ b/src/unix/pipe.c @@ -28,7 +28,9 @@ #include #include #include - +#ifdef CONFIG_NET_RPMSG +#include +#endif // CONFIG_NET_RPMSG int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) { uv__stream_init(loop, (uv_stream_t*)handle, UV_NAMED_PIPE); @@ -126,6 +128,48 @@ err_socket: return err; } +#ifdef CONFIG_NET_RPMSG +int uv_pipe_rpmsg_bind(uv_pipe_t* handle, + const char* name, + const char* cpu_name) { + struct sockaddr_rpmsg saddr; + int sockfd; + int err; + + /* Already bound? */ + if (uv__stream_fd(handle) >= 0) + return UV_EINVAL; + + err = uv__socket(AF_RPMSG, SOCK_STREAM, 0); + if (err < 0) + goto err_socket; + sockfd = err; + + memset(&saddr, 0, sizeof saddr); + uv__strscpy(saddr.rp_name, name, sizeof(saddr.rp_name)); + uv__strscpy(saddr.rp_cpu, cpu_name, sizeof(saddr.rp_cpu)); + saddr.rp_family = AF_RPMSG; + + if (bind(sockfd, (struct sockaddr*)&saddr, sizeof saddr)) { + err = UV__ERR(errno); + /* Convert ENOENT to EACCES for compatibility with Windows. */ + if (err == UV_ENOENT) + err = UV_EACCES; + + uv__close(sockfd); + goto err_socket; + } + + /* Success. */ + handle->flags |= UV_HANDLE_BOUND; + handle->pipe_fname = NULL; + handle->io_watcher.fd = sockfd; + return 0; + +err_socket: + return err; +} +#endif int uv__pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) { if (uv__stream_fd(handle) == -1) diff --git a/src/unix/posix-poll.c b/src/unix/posix-poll.c index 2e016c2f..3a351742 100644 --- a/src/unix/posix-poll.c +++ b/src/unix/posix-poll.c @@ -145,8 +145,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { int have_signals; struct pollfd* pe; int fd; - int user_timeout; - int reset_timeout; + int user_timeout = 0; + int reset_timeout = 0; if (loop->nfds == 0) { assert(uv__queue_empty(&loop->watcher_queue)); @@ -173,11 +173,15 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { /* Prepare a set of signals to block around poll(), if any. */ pset = NULL; +#ifdef SIGPROF if (loop->flags & UV_LOOP_BLOCK_SIGPROF) { pset = &set; sigemptyset(pset); sigaddset(pset, SIGPROF); } +#else + (void) set; +#endif assert(timeout >= -1); time_base = loop->time; diff --git a/src/unix/process-spawn.c b/src/unix/process-spawn.c new file mode 100644 index 00000000..9b9668d1 --- /dev/null +++ b/src/unix/process-spawn.c @@ -0,0 +1,380 @@ +/* Copyright Xiaomi, 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. + */ + +#define __USE_GNU +#include "uv.h" +#include "internal.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef SIGCHLD +static void uv__chld(uv_signal_t* handle, int signum) { + uv_process_t* process; + uv_loop_t* loop; + int exit_status; + int term_signal; + int status; + pid_t pid; + struct uv__queue pending; + struct uv__queue* q; + struct uv__queue* h; + + assert(signum == SIGCHLD); + + uv__queue_init(&pending); + loop = handle->loop; + + h = &loop->process_handles; + q = uv__queue_head(h); + while (q != h) { + process = uv__queue_data(q, uv_process_t, queue); + q = uv__queue_next(q); + + do + pid = waitpid(process->pid, &status, WNOHANG); + while (pid == -1 && errno == EINTR); + + if (pid == 0) + continue; + + if (pid == -1) { + if (errno != ECHILD) + abort(); + continue; + } + + process->status = status; + uv__queue_remove(&process->queue); + uv__queue_insert_tail(&pending, &process->queue); + } + + h = &pending; + q = uv__queue_head(h); + while (q != h) { + process = uv__queue_data(q, uv_process_t, queue); + q = uv__queue_next(q); + + uv__queue_remove(&process->queue); + uv__queue_init(&process->queue); + uv__handle_stop(process); + + if (process->exit_cb == NULL) + continue; + + exit_status = 0; + if (WIFEXITED(process->status)) + exit_status = WEXITSTATUS(process->status); + + term_signal = 0; + if (WIFSIGNALED(process->status)) + term_signal = WTERMSIG(process->status); + + process->exit_cb(process, exit_status, term_signal); + } + assert(uv__queue_empty(&pending)); +} + + +int uv__process_init(uv_loop_t* loop) { + int err; + + err = uv_signal_init(loop, &loop->child_watcher); + if (err) + return err; + uv__handle_unref(&loop->child_watcher); + loop->child_watcher.flags |= UV_HANDLE_INTERNAL; + return 0; +} +#endif + +/* + * Used for initializing stdio streams like options.stdin_stream. Returns + * zero on success. See also the cleanup section in uv_spawn(). + */ +static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) { + int mask; + int fd; + + mask = UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD | UV_INHERIT_STREAM; + + switch (container->flags & mask) { + case UV_IGNORE: + return 0; + + case UV_CREATE_PIPE: + assert(container->data.stream != NULL); + if (container->data.stream->type != UV_NAMED_PIPE) + return UV_EINVAL; + else + return uv_pipe(fds, 0, 0); + + case UV_INHERIT_FD: + case UV_INHERIT_STREAM: + if (container->flags & UV_INHERIT_FD) + fd = container->data.fd; + else + fd = uv__stream_fd(container->data.stream); + + if (fd == -1) + return UV_EINVAL; + + fds[0] = fds[1] = fd; + return 0; + + default: + assert(0 && "Unexpected flags"); + return UV_EINVAL; + } +} + + +static int uv__process_open_stream(uv_stdio_container_t* container, + int pipefds[2]) { + int flags; + + if (!(container->flags & UV_CREATE_PIPE) || pipefds[0] < 0) + return 0; + + uv__nonblock(pipefds[0], 1); + + flags = 0; + if (container->flags & UV_WRITABLE_PIPE) + flags |= UV_HANDLE_READABLE; + if (container->flags & UV_READABLE_PIPE) + flags |= UV_HANDLE_WRITABLE; + + return uv__stream_open(container->data.stream, pipefds[0], flags); +} + + +static void uv__process_close_stream(uv_stdio_container_t* container) { + if (!(container->flags & UV_CREATE_PIPE)) return; + uv__stream_close(container->data.stream); +} + + +static int uv__process_child_spawn(const uv_process_options_t* options, + int stdio_count, + int (*pipes)[2], + pid_t *pid) { + posix_spawn_file_actions_t file_actions; + posix_spawnattr_t attr; + sigset_t set; + int use_fd; + int flags; + int err; + int fd; + + posix_spawn_file_actions_init(&file_actions); + posix_spawnattr_init(&attr); + + /* Reset signal disposition and mask */ + flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK; + + sigfillset(&set); + posix_spawnattr_setsigdefault(&attr, &set); + + sigemptyset(&set); + posix_spawnattr_setsigmask(&attr, &set); + + if (options->flags & UV_PROCESS_DETACHED) + flags |= POSIX_SPAWN_SETSID; + + /* First duplicate low numbered fds, since it's not safe to duplicate them, + * they could get replaced. Example: swapping stdout and stderr; without + * this fd 2 (stderr) would be duplicated into fd 1, thus making both + * stdout and stderr go to the same fd, which was not the intention. */ + for (fd = 0; fd < stdio_count; fd++) { + use_fd = pipes[fd][1]; + if (use_fd < 0 || use_fd >= fd) + continue; + pipes[fd][1] = fcntl(use_fd, F_DUPFD, stdio_count); + if (pipes[fd][1] == -1) { + err = errno; + goto error; + } + } + + for (fd = 0; fd < stdio_count; fd++) { + use_fd = pipes[fd][1]; + + if (use_fd < 0) { + if (fd >= 3) + continue; + else { + /* redirect stdin, stdout and stderr to /dev/null even if UV_IGNORE is + * set + */ + use_fd = open("/dev/null", fd == 0 ? O_RDONLY : O_RDWR); + pipes[fd][1] = use_fd; + + if (use_fd < 0) { + err = errno; + goto error; + } + } + } + + if (fd == use_fd) + uv__cloexec(use_fd, 0); + else + posix_spawn_file_actions_adddup2(&file_actions, use_fd, fd); + + if (fd <= 2) + uv__nonblock_fcntl(use_fd, 0); + } + + if (options->flags & UV_PROCESS_SETUID) { + err = options->uid ? ENOTSUP : EPERM; + goto error; + } + + if (options->flags & UV_PROCESS_SETGID) { + if (options->gid == 0) { + err = EPERM; + goto error; + } + + posix_spawnattr_setpgroup(&attr, options->gid); + flags |= POSIX_SPAWN_SETPGROUP; + } + + posix_spawnattr_setflags(&attr, flags); + err = posix_spawn(pid, options->file, &file_actions, &attr, + options->args, options->env ? options->env : environ); + +error: + for (fd = 0; fd < stdio_count; fd++) { + if (pipes[fd][1] >= 0 && pipes[fd][1] != pipes[fd][0]) { + close(pipes[fd][1]); + pipes[fd][1] = -1; + } + } + + posix_spawn_file_actions_destroy(&file_actions); + posix_spawnattr_destroy(&attr); + return UV__ERR(err); +} + + +int uv_spawn(uv_loop_t* loop, + uv_process_t* process, + const uv_process_options_t* options) { + int pipes_storage[8][2]; + int (*pipes)[2]; + int stdio_count; + pid_t pid; + int err; + int i; + + assert(options->file != NULL); + assert(!(options->flags & ~(UV_PROCESS_DETACHED | + UV_PROCESS_SETGID | + UV_PROCESS_SETUID | + UV_PROCESS_WINDOWS_HIDE | + UV_PROCESS_WINDOWS_HIDE_CONSOLE | + UV_PROCESS_WINDOWS_HIDE_GUI | + UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS))); + + uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS); + uv__queue_init(&process->queue); + + stdio_count = options->stdio_count; + if (stdio_count < 3) + stdio_count = 3; + + err = UV_ENOMEM; + pipes = pipes_storage; + if (stdio_count > (int)ARRAY_SIZE(pipes_storage)) + pipes = uv__malloc(stdio_count * sizeof(*pipes)); + + if (pipes == NULL) + goto error; + + for (i = 0; i < stdio_count; i++) { + pipes[i][0] = -1; + pipes[i][1] = -1; + } + + for (i = 0; i < options->stdio_count; i++) { + err = uv__process_init_stdio(options->stdio + i, pipes[i]); + if (err) + goto error; + } + +#ifdef SIGCHLD + uv_signal_start(&loop->child_watcher, uv__chld, SIGCHLD); +#endif + + err = uv__process_child_spawn(options, stdio_count, pipes, &pid); + if (err) + goto error; + + for (i = 0; i < options->stdio_count; i++) { + err = uv__process_open_stream(options->stdio + i, pipes[i]); + if (err == 0) + continue; + + while (i--) + uv__process_close_stream(options->stdio + i); + + goto error; + } + + uv__queue_insert_tail(&loop->process_handles, &process->queue); + uv__handle_start(process); + + process->status = 0; + process->pid = pid; + process->exit_cb = options->exit_cb; + + if (pipes != pipes_storage) + uv__free(pipes); + + return 0; + +error: + if (pipes != NULL) { + for (i = 0; i < stdio_count; i++) { + if (i < options->stdio_count) + if (options->stdio[i].flags & (UV_INHERIT_FD | UV_INHERIT_STREAM)) + continue; + if (pipes[i][0] != -1) + uv__close_nocheckstdio(pipes[i][0]); + if (pipes[i][1] != -1) + uv__close_nocheckstdio(pipes[i][1]); + } + + if (pipes != pipes_storage) + uv__free(pipes); + } + + return err; +} diff --git a/src/unix/signal.c b/src/unix/signal.c index 63aba5a6..28b80eff 100644 --- a/src/unix/signal.c +++ b/src/unix/signal.c @@ -20,6 +20,7 @@ #include "uv.h" #include "internal.h" +#include "uv-global.h" #include #include @@ -32,14 +33,6 @@ # define SA_RESTART 0 #endif -typedef struct { - uv_signal_t* handle; - int signum; -} uv__signal_msg_t; - -RB_HEAD(uv__signal_tree_s, uv_signal_s); - - static int uv__signal_unlock(void); static int uv__signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, @@ -50,12 +43,6 @@ static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2); static void uv__signal_stop(uv_signal_t* handle); static void uv__signal_unregister_handler(int signum); - -static uv_once_t uv__signal_global_init_guard = UV_ONCE_INIT; -static struct uv__signal_tree_s uv__signal_tree = - RB_INITIALIZER(uv__signal_tree); -static int uv__signal_lock_pipefd[2] = { -1, -1 }; - RB_GENERATE_STATIC(uv__signal_tree_s, uv_signal_s, tree_entry, uv__signal_compare) @@ -558,3 +545,21 @@ static void uv__signal_stop(uv_signal_t* handle) { handle->signum = 0; uv__handle_stop(handle); } + +int uv_process_kill(uv_process_t* process, int signum) { + return uv_kill(process->pid, signum); +} + +int uv_kill(int pid, int signum) { + if (kill(pid, signum)) + return UV__ERR(errno); + else + return 0; +} + +void uv__process_close(uv_process_t* handle) { + uv__queue_remove(&handle->queue); + uv__handle_stop(handle); + if (uv__queue_empty(&handle->loop->process_handles)) + uv_signal_stop(&handle->loop->child_watcher); +} diff --git a/src/unix/tcp.c b/src/unix/tcp.c index d6c848f4..639b99c5 100644 --- a/src/unix/tcp.c +++ b/src/unix/tcp.c @@ -160,7 +160,7 @@ int uv__tcp_bind(uv_tcp_t* tcp, if (setsockopt(tcp->io_watcher.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) return UV__ERR(errno); -#ifndef __OpenBSD__ +#if !defined(__OpenBSD__) && !defined(__NuttX__) #ifdef IPV6_V6ONLY if (addr->sa_family == AF_INET6) { on = (flags & UV_TCP_IPV6ONLY) != 0; diff --git a/src/unix/thread.c b/src/unix/thread.c old mode 100644 new mode 100755 index 4d6f4b82..0f024e7a --- a/src/unix/thread.c +++ b/src/unix/thread.c @@ -158,16 +158,25 @@ int uv_thread_create_ex(uv_thread_t* tid, stack_size = min_stack_size; } - if (stack_size > 0) { + if (stack_size > 0 || (params->flags & UV_THREAD_HAS_PRIORITY)) { attr = &attr_storage; if (pthread_attr_init(attr)) abort(); + } + if (stack_size > 0) { if (pthread_attr_setstacksize(attr, stack_size)) abort(); } + if (params->flags & UV_THREAD_HAS_PRIORITY) { + struct sched_param param; + pthread_attr_getschedparam(attr, ¶m); + param.sched_priority = params->priority; + pthread_attr_setschedparam(attr, ¶m); + } + f.in = entry; err = pthread_create(tid, attr, f.out, arg); diff --git a/src/unix/tty.c b/src/unix/tty.c index d099bdb3..06f23b75 100644 --- a/src/unix/tty.c +++ b/src/unix/tty.c @@ -79,6 +79,7 @@ int uv__tcsetattr(int fd, int how, const struct termios *term) { return 0; } +#ifndef __NuttX__ static int uv__tty_is_slave(const int fd) { int result; #if defined(__linux__) || defined(__FreeBSD__) @@ -132,15 +133,13 @@ static int uv__tty_is_slave(const int fd) { #endif return result; } +#endif int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int unused) { uv_handle_type type; int flags; - int newfd; - int r; int saved_flags; int mode; - char path[256]; (void)unused; /* deprecated parameter is no longer needed */ /* File descriptors that refer to files cannot be monitored with epoll. @@ -152,7 +151,6 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int unused) { return UV_EINVAL; flags = 0; - newfd = -1; /* Save the fd flags in case we need to restore them due to an error. */ do @@ -163,6 +161,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int unused) { return UV__ERR(errno); mode = saved_flags & O_ACCMODE; +#ifndef __NuttX__ /* Reopen the file descriptor when it refers to a tty. This lets us put the * tty in non-blocking mode without affecting other processes that share it * with us. @@ -174,6 +173,10 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int unused) { * other processes. */ if (type == UV_TTY) { + int newfd; + int r; + char path[256]; + /* Reopening a pty in master mode won't work either because the reopened * pty will be in slave mode (*BSD) or reopening will allocate a new * master/slave pair (Linux). Therefore check if the fd points to a @@ -207,6 +210,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int unused) { } skip: +#endif uv__stream_init(loop, (uv_stream_t*) tty, UV_TTY); /* If anything fails beyond this point we need to remove the handle from diff --git a/src/unix/udp.c b/src/unix/udp.c index c2814512..a41478f2 100644 --- a/src/unix/udp.c +++ b/src/unix/udp.c @@ -943,6 +943,7 @@ static int uv__udp_set_source_membership6(uv_udp_t* handle, const char* interface_addr, const struct sockaddr_in6* source_addr, uv_membership membership) { +#ifndef __NuttX__ struct group_source_req mreq; struct sockaddr_in6 addr6; int optname; @@ -984,6 +985,9 @@ static int uv__udp_set_source_membership6(uv_udp_t* handle, } return 0; +#else + return UV_ENOSYS; +#endif } #endif diff --git a/src/uv-common.c b/src/uv-common.c index 916f3f4e..5dceb29e 100644 --- a/src/uv-common.c +++ b/src/uv-common.c @@ -21,6 +21,7 @@ #include "uv.h" #include "uv-common.h" +#include "uv-global.h" #include #include @@ -813,10 +814,6 @@ int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...) { } -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; @@ -942,7 +939,6 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { __attribute__((destructor)) #endif void uv_library_shutdown(void) { - static int was_shutdown; if (uv__exchange_int_relaxed(&was_shutdown, 1)) return; @@ -1024,3 +1020,22 @@ uint64_t uv_metrics_idle_time(uv_loop_t* loop) { idle_time += uv_hrtime() - entry_time; return idle_time; } + +/* Add uv_global_get here since all system need it but NuttX */ + +#ifndef __NuttX__ +#undef once +#undef uv__signal_global_init_guard +#undef uv__signal_lock_pipefd + +uv__global_t* uv__global_get(void) +{ + static uv__global_t g_uv_common_global = { + .once = UV_ONCE_INIT, + .uv__signal_global_init_guard = UV_ONCE_INIT, + .uv__signal_lock_pipefd = {-1, -1}, + }; + + return &g_uv_common_global; +} +#endif diff --git a/src/uv-global.h b/src/uv-global.h new file mode 100644 index 00000000..1d21d277 --- /dev/null +++ b/src/uv-global.h @@ -0,0 +1,96 @@ +/* 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_GLOBAL_H +#define UV_GLOBAL_H + +#include "uv.h" + +#ifndef DEF_THREADPOOL_SIZE +# define DEF_THREADPOOL_SIZE 4 +#endif + +#if !defined(_WIN32) +typedef struct { + uv_signal_t* handle; + int signum; +} uv__signal_msg_t; + +RB_HEAD(uv__signal_tree_s, uv_signal_s); +#endif + +typedef struct { + /* Member in threadpool.c */ + uv_once_t once; + uv_cond_t cond; + uv_mutex_t mutex; + unsigned int idle_threads; + unsigned int slow_io_work_running; + unsigned int nthreads; + uv_thread_t* threads; + uv_thread_t default_threads[DEF_THREADPOOL_SIZE]; + struct uv__queue exit_message; + struct uv__queue wq; + struct uv__queue run_slow_work_message; + struct uv__queue slow_io_pending_wq; + /* Member in uv-common.c */ + int was_shutdown; + uv_loop_t default_loop_struct; + uv_loop_t* default_loop_ptr; +#if !defined(_WIN32) + /* Member in signal.c */ + uv_once_t uv__signal_global_init_guard; + struct uv__signal_tree_s uv__signal_tree; + int uv__signal_lock_pipefd[2]; +#endif +} uv__global_t; + +uv__global_t* uv__global_get(void); + +/* Used in threadpool.c */ + +#define once uv__global_get()->once +#define cond uv__global_get()->cond +#define mutex uv__global_get()->mutex +#define idle_threads uv__global_get()->idle_threads +#define slow_io_work_running uv__global_get()->slow_io_work_running +#define nthreads uv__global_get()->nthreads +#define threads uv__global_get()->threads +#define default_threads uv__global_get()->default_threads +#define exit_message uv__global_get()->exit_message +#define lwq uv__global_get()->wq +#define run_slow_work_message uv__global_get()->run_slow_work_message +#define slow_io_pending_wq uv__global_get()->slow_io_pending_wq + +/* Used in uv-common.c */ + +#define was_shutdown uv__global_get()->was_shutdown +#define default_loop_struct uv__global_get()->default_loop_struct +#define default_loop_ptr uv__global_get()->default_loop_ptr + +#if !defined(_WIN32) +/* Used in signal.c */ + +#define uv__signal_global_init_guard uv__global_get()->uv__signal_global_init_guard +#define uv__signal_tree uv__global_get()->uv__signal_tree +#define uv__signal_lock_pipefd uv__global_get()->uv__signal_lock_pipefd +#endif + +#endif diff --git a/test/benchmark-pound.c b/test/benchmark-pound.c index acfe4497..70803646 100644 --- a/test/benchmark-pound.c +++ b/test/benchmark-pound.c @@ -84,9 +84,8 @@ static void close_cb(uv_handle_t* handle); static void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { - static char slab[65536]; - buf->base = slab; - buf->len = sizeof(slab); + buf->base = malloc(65536); + buf->len = 65536; } @@ -155,6 +154,7 @@ static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { ASSERT(0); } } + free(buf->base); } diff --git a/test/benchmark-udp-pummel.c b/test/benchmark-udp-pummel.c index f89913b6..71327e20 100644 --- a/test/benchmark-udp-pummel.c +++ b/test/benchmark-udp-pummel.c @@ -62,10 +62,9 @@ static int exiting; static void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { - static char slab[65536]; - ASSERT(suggested_size <= sizeof(slab)); - buf->base = slab; - buf->len = sizeof(slab); + ASSERT(suggested_size <= 65536); + buf->base = malloc(65536); + buf->len = 65536; } @@ -123,6 +122,8 @@ static void recv_cb(uv_udp_t* handle, ASSERT(!memcmp(buf->base, EXPECTED, nread)); recv_cb_called++; + + free(buf->base); } diff --git a/test/blackhole-server.c b/test/blackhole-server.c index 0a8758e1..24fdc4ec 100644 --- a/test/blackhole-server.c +++ b/test/blackhole-server.c @@ -63,9 +63,8 @@ static void connection_cb(uv_stream_t* stream, int status) { static void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { - static char slab[65536]; - buf->base = slab; - buf->len = sizeof(slab); + buf->base = malloc(65536); + buf->len = 65536; } @@ -82,6 +81,8 @@ static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { r = uv_shutdown(&conn->shutdown_req, stream, shutdown_cb); ASSERT(r == 0); + + free(buf->base); } diff --git a/test/echo-server.c b/test/echo-server.c index 058c9925..65ddaf40 100644 --- a/test/echo-server.c +++ b/test/echo-server.c @@ -161,9 +161,8 @@ static void slab_alloc(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { /* up to 16 datagrams at once */ - static char slab[16 * 64 * 1024]; - buf->base = slab; - buf->len = sizeof(slab); + buf->base = malloc(16 * 64 * 1024); + buf->len = 16 * 64 * 1024; } static void on_connection(uv_stream_t* server, int status) { @@ -224,6 +223,8 @@ static void on_send(uv_udp_send_t* req, int status) { ASSERT(status == 0); req->data = send_freelist; send_freelist = req; + ASSERT(req->nbufs == 1); + free(req->bufs[0].base); } static void on_recv(uv_udp_t* handle, diff --git a/test/run-tests.c b/test/run-tests.c index d8cfe297..b4e2a966 100644 --- a/test/run-tests.c +++ b/test/run-tests.c @@ -65,7 +65,7 @@ typedef BOOL (WINAPI *sCompareObjectHandles)(_In_ HANDLE, _In_ HANDLE); int main(int argc, char **argv) { -#ifndef _WIN32 +#if !defined(_WIN32) && !defined(__NuttX__) if (0 == geteuid() && NULL == getenv("UV_RUN_AS_ROOT")) { fprintf(stderr, "The libuv test suite cannot be run as root.\n"); return EXIT_FAILURE; diff --git a/test/runner-unix.c b/test/runner-unix.c index 81560add..45fe587a 100644 --- a/test/runner-unix.c +++ b/test/runner-unix.c @@ -43,8 +43,10 @@ #ifdef __APPLE__ #include #endif - +#ifndef __NuttX__ extern char** environ; +#endif +#include static void closefd(int fd) { if (close(fd) == 0 || errno == EINTR || errno == EINPROGRESS) @@ -83,6 +85,7 @@ void platform_init(int argc, char **argv) { /* Invoke "argv[0] test-name [test-part]". Store process info in *p. Make sure * that all stdio output of the processes is buffered up. */ int process_start(char* name, char* part, process_info_t* p, int is_helper) { + posix_spawn_file_actions_t file_actions; FILE* stdout_file; int stdout_fd; const char* arg; @@ -119,12 +122,17 @@ int process_start(char* name, char* part, process_info_t* p, int is_helper) { return -1; } + posix_spawn_file_actions_init(&file_actions); + posix_spawn_file_actions_adddup2(&file_actions, stdout_fd, STDOUT_FILENO); + posix_spawn_file_actions_adddup2(&file_actions, stdout_fd, STDERR_FILENO); + if (is_helper) { if (pipe(pipefd)) { perror("pipe"); return -1; } + posix_spawn_file_actions_addclose(&file_actions, pipefd[0]); snprintf(fdstr, sizeof(fdstr), "%d", pipefd[1]); if (setenv("UV_TEST_RUNNER_FD", fdstr, /* overwrite */ 1)) { perror("setenv"); @@ -136,30 +144,17 @@ int process_start(char* name, char* part, process_info_t* p, int is_helper) { p->status = 0; #if defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH) - pid = -1; + n = -1; #else - pid = fork(); + n = posix_spawn(&pid, args[0], &file_actions, NULL, args, environ); + posix_spawn_file_actions_destroy(&file_actions); #endif - if (pid < 0) { - perror("fork"); + if (n != 0) { + fprintf(stderr, "posix_spawn: %s\n", strerror(n)); return -1; } - if (pid == 0) { - /* child */ - if (is_helper) - closefd(pipefd[0]); - dup2(stdout_fd, STDOUT_FILENO); - dup2(stdout_fd, STDERR_FILENO); -#if !(defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH)) - execve(args[0], args, environ); -#endif - perror("execve()"); - _exit(127); - } - - /* parent */ p->pid = pid; p->name = strdup(name); p->stdout_file = stdout_file; diff --git a/test/task.h b/test/task.h index fa6cc0ed..25af255c 100644 --- a/test/task.h +++ b/test/task.h @@ -95,6 +95,7 @@ typedef enum { /* Have our own assert, so we are sure it does not get optimized away in * a release build. */ +#undef ASSERT #define ASSERT(expr) \ do { \ if (!(expr)) { \ @@ -309,6 +310,7 @@ enum test_status { extern int snprintf(char*, size_t, const char*, ...); #endif +#undef UNUSED #if defined(__clang__) || \ defined(__GNUC__) || \ defined(__INTEL_COMPILER) @@ -351,7 +353,7 @@ UNUSED static int can_ipv6(void) { return supported; } -#if defined(__CYGWIN__) || defined(__MSYS__) || defined(__PASE__) +#if defined(__CYGWIN__) || defined(__MSYS__) || defined(__PASE__) || defined(__NuttX__) # define NO_FS_EVENTS "Filesystem watching not supported on this platform." #endif diff --git a/test/test-active.c b/test/test-active.c index aaff9708..38ab885a 100644 --- a/test/test-active.c +++ b/test/test-active.c @@ -44,6 +44,8 @@ TEST_IMPL(active) { int r; uv_timer_t timer; + close_cb_called = 0; + r = uv_timer_init(uv_default_loop(), &timer); ASSERT(r == 0); diff --git a/test/test-async-null-cb.c b/test/test-async-null-cb.c index 1bdd0e03..76000480 100644 --- a/test/test-async-null-cb.c +++ b/test/test-async-null-cb.c @@ -52,6 +52,8 @@ TEST_IMPL(async_null_cb) { */ memset(&async_handle, 0xff, sizeof(async_handle)); + check_cb_called = 0; + ASSERT(0 == uv_async_init(uv_default_loop(), &async_handle, NULL)); ASSERT(0 == uv_check_init(uv_default_loop(), &check_handle)); ASSERT(0 == uv_check_start(&check_handle, check_cb)); diff --git a/test/test-async.c b/test/test-async.c index 73664ea5..b917378d 100644 --- a/test/test-async.c +++ b/test/test-async.c @@ -108,6 +108,10 @@ static void prepare_cb(uv_prepare_t* handle) { TEST_IMPL(async) { int r; + async_cb_called = 0; + close_cb_called = 0; + prepare_cb_called = 0; + r = uv_mutex_init(&mutex); ASSERT(r == 0); uv_mutex_lock(&mutex); diff --git a/test/test-close-order.c b/test/test-close-order.c index 768e1cee..9f8d24c5 100644 --- a/test/test-close-order.c +++ b/test/test-close-order.c @@ -56,6 +56,11 @@ static void timer_cb(uv_timer_t* handle) { TEST_IMPL(close_order) { uv_loop_t* loop; + + check_cb_called = 0; + timer_cb_called = 0; + close_cb_called = 0; + loop = uv_default_loop(); uv_check_init(loop, &check_handle); diff --git a/test/test-connection-fail.c b/test/test-connection-fail.c index aa7db30d..ecc99930 100644 --- a/test/test-connection-fail.c +++ b/test/test-connection-fail.c @@ -36,6 +36,13 @@ static int timer_close_cb_calls; static int timer_cb_calls; +static inline void init_call_count(void) { + connect_cb_calls = 0; + close_cb_calls = 0; + timer_close_cb_calls = 0; + timer_cb_calls = 0; +} + static void on_close(uv_handle_t* handle) { close_cb_calls++; } @@ -89,6 +96,9 @@ static void connection_fail(uv_connect_cb connect_cb) { struct sockaddr_in client_addr, server_addr; int r; + /* Initialize the call counter. */ + init_call_count(); + ASSERT(0 == uv_ip4_addr("0.0.0.0", 0, &client_addr)); /* There should be no servers listening on this port. */ diff --git a/test/test-default-loop-close.c b/test/test-default-loop-close.c index 8d960e11..8fcd9668 100644 --- a/test/test-default-loop-close.c +++ b/test/test-default-loop-close.c @@ -36,6 +36,8 @@ TEST_IMPL(default_loop_close) { uv_loop_t* loop; uv_timer_t timer_handle; + timer_cb_called = 0; + loop = uv_default_loop(); ASSERT_NOT_NULL(loop); diff --git a/test/test-fs-copyfile.c b/test/test-fs-copyfile.c index d7f04cf4..d13ab6db 100644 --- a/test/test-fs-copyfile.c +++ b/test/test-fs-copyfile.c @@ -25,6 +25,7 @@ #if defined(__unix__) || defined(__POSIX__) || \ defined(__APPLE__) || defined(__sun) || \ defined(_AIX) || defined(__MVS__) || \ + defined(__NuttX__) || \ defined(__HAIKU__) || defined(__QNX__) #include /* unlink, etc. */ #else diff --git a/test/test-fs.c b/test/test-fs.c index e687dde3..7451b987 100644 --- a/test/test-fs.c +++ b/test/test-fs.c @@ -716,6 +716,7 @@ TEST_IMPL(fs_file_noent) { uv_fs_t req; int r; + open_cb_count = 0; loop = uv_default_loop(); r = uv_fs_open(NULL, &req, "does_not_exist", O_RDONLY, 0, NULL); @@ -741,6 +742,7 @@ TEST_IMPL(fs_file_nametoolong) { int r; char name[TOO_LONG_NAME_LENGTH + 1]; + open_cb_count = 0; loop = uv_default_loop(); memset(name, 'a', TOO_LONG_NAME_LENGTH); @@ -766,6 +768,7 @@ TEST_IMPL(fs_file_loop) { uv_fs_t req; int r; + open_cb_count = 0; loop = uv_default_loop(); unlink("test_symlink"); @@ -912,6 +915,17 @@ static void lutime_cb(uv_fs_t* req) { TEST_IMPL(fs_file_async) { int r; + open_cb_count = 0; + close_cb_count = 0; + create_cb_count = 0; + read_cb_count = 0; + write_cb_count = 0; + unlink_cb_count = 0; + rename_cb_count = 0; + fsync_cb_count = 0; + fdatasync_cb_count = 0; + ftruncate_cb_count = 0; + /* Setup. */ unlink("test_file"); unlink("test_file2"); @@ -1102,6 +1116,12 @@ TEST_IMPL(fs_async_dir) { int r; uv_dirent_t dent; + unlink_cb_count = 0; + mkdir_cb_count = 0; + rmdir_cb_count = 0; + scandir_cb_count = 0; + stat_cb_count = 0; + /* Setup */ unlink("test_dir/file1"); unlink("test_dir/file2"); @@ -1199,6 +1219,7 @@ static int test_sendfile(void (*setup)(int), uv_fs_cb cb, off_t expected_size) { uv_fs_t req; char buf1[1]; + sendfile_cb_count = 0; loop = uv_default_loop(); /* Setup. */ @@ -1294,6 +1315,7 @@ TEST_IMPL(fs_mkdtemp) { int r; const char* path_template = "test_dir_XXXXXX"; + mkdtemp_cb_count = 0; loop = uv_default_loop(); r = uv_fs_mkdtemp(loop, &mkdtemp_req1, path_template, mkdtemp_cb); @@ -1327,6 +1349,7 @@ TEST_IMPL(fs_mkstemp) { const char path_template[] = "test_file_XXXXXX"; uv_fs_t req; + mkstemp_cb_count = 0; loop = uv_default_loop(); r = uv_fs_mkstemp(loop, &mkstemp_req1, path_template, mkstemp_cb); @@ -1405,6 +1428,8 @@ TEST_IMPL(fs_fstat) { RETURN_SKIP("Test does not currently work in QEMU"); #endif + fstat_cb_count = 0; + /* Setup. */ unlink("test_file"); @@ -1595,6 +1620,8 @@ TEST_IMPL(fs_access) { uv_fs_t req; uv_file file; + access_cb_count = 0; + /* Setup. */ unlink("test_file"); rmdir("test_dir"); @@ -1671,6 +1698,9 @@ TEST_IMPL(fs_chmod) { uv_fs_t req; uv_file file; + chmod_cb_count = 0; + fchmod_cb_count = 0; + /* Setup. */ unlink("test_file"); @@ -1886,6 +1916,10 @@ TEST_IMPL(fs_chown) { uv_fs_t req; uv_file file; + chown_cb_count = 0; + fchown_cb_count = 0; + lchown_cb_count = 0; + /* Setup. */ unlink("test_file"); unlink("test_file_link"); @@ -1980,6 +2014,8 @@ TEST_IMPL(fs_link) { uv_file file; uv_file link; + link_cb_count = 0; + /* Setup. */ unlink("test_file"); unlink("test_file_link"); @@ -2117,6 +2153,8 @@ TEST_IMPL(fs_readlink) { TEST_IMPL(fs_realpath) { uv_fs_t req; + dummy_cb_count = 0; + loop = uv_default_loop(); ASSERT(0 == uv_fs_realpath(loop, &req, "no_such_file", dummy_cb)); ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); @@ -2143,6 +2181,10 @@ TEST_IMPL(fs_symlink) { char test_file_abs_buf[PATHMAX]; size_t test_file_abs_size; + symlink_cb_count = 0; + readlink_cb_count = 0; + realpath_cb_count = 0; + /* Setup. */ unlink("test_file"); unlink("test_file_symlink"); @@ -2617,6 +2659,8 @@ TEST_IMPL(fs_utime) { uv_fs_t req; int r; + utime_cb_count = 0; + /* Setup. */ loop = uv_default_loop(); unlink(path); @@ -2738,6 +2782,8 @@ TEST_IMPL(fs_futime) { RETURN_SKIP("futime is not implemented for AIX versions below 7.1"); #endif + futime_cb_count = 0; + /* Setup. */ loop = uv_default_loop(); unlink(path); @@ -2797,6 +2843,7 @@ TEST_IMPL(fs_lutime) { uv_fs_t req; int r, s; + lutime_cb_count = 0; /* Setup */ loop = uv_default_loop(); @@ -2884,6 +2931,8 @@ TEST_IMPL(fs_scandir_empty_dir) { uv_dirent_t dent; int r; + scandir_cb_count = 0; + path = "./empty_dir/"; loop = uv_default_loop(); @@ -2921,6 +2970,7 @@ TEST_IMPL(fs_scandir_non_existent_dir) { uv_dirent_t dent; int r; + scandir_cb_count = 0; path = "./non_existent_dir/"; loop = uv_default_loop(); @@ -2952,6 +3002,7 @@ TEST_IMPL(fs_scandir_file) { const char* path; int r; + scandir_cb_count = 0; path = "test/fixtures/empty_file"; loop = uv_default_loop(); @@ -2994,6 +3045,7 @@ TEST_IMPL(fs_open_dir) { uv_fs_t req; int r, file; + open_cb_count = 0; path = "."; loop = uv_default_loop(); @@ -3606,6 +3658,7 @@ TEST_IMPL(fs_write_alotof_bufs_with_offset) { TEST_IMPL(fs_read_dir) { int r; char buf[2]; + mkdir_cb_count = 0; loop = uv_default_loop(); /* Setup */ @@ -4514,6 +4567,7 @@ TEST_IMPL(fs_statfs) { uv_fs_t req; int r; + statfs_cb_count = 0; loop = uv_default_loop(); /* Test the synchronous version. */ diff --git a/test/test-getsockname.c b/test/test-getsockname.c index 1d4d9f12..f9a3c2a7 100644 --- a/test/test-getsockname.c +++ b/test/test-getsockname.c @@ -42,6 +42,11 @@ static uv_tcp_t tcpServer; static uv_udp_t udpServer; static uv_udp_send_t send_req; +static inline void init_count(void) { + getsocknamecount_tcp = 0; + getpeernamecount = 0; + getsocknamecount_udp = 0; +} static void alloc(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { buf->base = malloc(suggested_size); @@ -325,6 +330,7 @@ static void udp_sender(void) { TEST_IMPL(getsockname_tcp) { + init_count(); loop = uv_default_loop(); if (tcp_listener()) @@ -343,6 +349,7 @@ TEST_IMPL(getsockname_tcp) { TEST_IMPL(getsockname_udp) { + init_count(); loop = uv_default_loop(); if (udp_listener()) diff --git a/test/test-idle.c b/test/test-idle.c index e3f4c2bc..897a972e 100644 --- a/test/test-idle.c +++ b/test/test-idle.c @@ -72,6 +72,11 @@ static void check_cb(uv_check_t* handle) { TEST_IMPL(idle_starvation) { int r; + idle_cb_called = 0; + check_cb_called = 0; + timer_cb_called = 0; + close_cb_called = 0; + r = uv_idle_init(uv_default_loop(), &idle_handle); ASSERT(r == 0); r = uv_idle_start(&idle_handle, idle_cb); diff --git a/test/test-ipc.c b/test/test-ipc.c index 7ec6ec9c..5e985b10 100644 --- a/test/test-ipc.c +++ b/test/test-ipc.c @@ -295,7 +295,7 @@ void spawn_helper(uv_pipe_t* channel, r = uv_exepath(exepath, &exepath_size); ASSERT_EQ(r, 0); - exepath[exepath_size] = '\0'; + exepath[exepath_size - 1] = '\0'; args[0] = exepath; args[1] = (char*)helper; args[2] = NULL; diff --git a/test/test-list.h b/test/test-list.h index 78ff9c2d..cac3b16f 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -600,7 +600,7 @@ TASK_LIST_START TEST_ENTRY (pipe_connect_on_prepare) TEST_ENTRY (pipe_server_close) -#ifndef _WIN32 +#if !defined(_WIN32) && !defined(__NuttX__) TEST_ENTRY (pipe_close_stdout_read_stdin) #endif /* Seems to be either about 0.5s or 5s, depending on the OS. */ @@ -1169,7 +1169,7 @@ TASK_LIST_START TEST_ENTRY (req_type_name) TEST_ENTRY (getters_setters) -#ifndef _WIN32 +#if !defined(_WIN32) && !defined(__NuttX__) TEST_ENTRY (fork_timer) TEST_ENTRY (fork_socketpair) TEST_ENTRY (fork_socketpair_started) diff --git a/test/test-loop-configure.c b/test/test-loop-configure.c index d057c1ed..6a8b0681 100644 --- a/test/test-loop-configure.c +++ b/test/test-loop-configure.c @@ -25,7 +25,7 @@ TEST_IMPL(loop_configure) { uv_timer_t timer_handle; uv_loop_t loop; ASSERT(0 == uv_loop_init(&loop)); -#ifdef _WIN32 +#if defined(_WIN32) || !defined(SIGPROF) ASSERT(UV_ENOSYS == uv_loop_configure(&loop, UV_LOOP_BLOCK_SIGNAL, 0)); #else ASSERT(0 == uv_loop_configure(&loop, UV_LOOP_BLOCK_SIGNAL, SIGPROF)); diff --git a/test/test-loop-handles.c b/test/test-loop-handles.c index 5d3df024..d5ce0194 100644 --- a/test/test-loop-handles.c +++ b/test/test-loop-handles.c @@ -282,6 +282,21 @@ TEST_IMPL(loop_handles) { int i; int r; + loop_iteration = 0; + prepare_1_cb_called = 0; + prepare_1_close_cb_called = 0; + prepare_2_cb_called = 0; + prepare_2_close_cb_called = 0; + check_cb_called = 0; + check_close_cb_called = 0; + idle_1_cb_called = 0; + idle_1_close_cb_called = 0; + idles_1_active = 0; + idle_2_cb_called = 0; + idle_2_close_cb_called = 0; + idle_2_cb_started = 0; + idle_2_is_active = 0; + r = uv_prepare_init(uv_default_loop(), &prepare_1_handle); ASSERT(r == 0); r = uv_prepare_start(&prepare_1_handle, prepare_1_cb); diff --git a/test/test-loop-stop.c b/test/test-loop-stop.c index 981d20d1..8dda9f32 100644 --- a/test/test-loop-stop.c +++ b/test/test-loop-stop.c @@ -49,6 +49,11 @@ static void timer_cb(uv_timer_t* handle) { TEST_IMPL(loop_stop) { int r; + + prepare_called = 0; + timer_called = 0; + num_ticks = 10; + uv_prepare_init(uv_default_loop(), &prepare_handle); uv_prepare_start(&prepare_handle, prepare_cb); uv_timer_init(uv_default_loop(), &timer_handle); diff --git a/test/test-not-readable-nor-writable-on-read-error.c b/test/test-not-readable-nor-writable-on-read-error.c index 823a4e91..85171e07 100644 --- a/test/test-not-readable-nor-writable-on-read-error.c +++ b/test/test-not-readable-nor-writable-on-read-error.c @@ -33,6 +33,13 @@ static int read_cb_called; static int write_cb_called; static int close_cb_called; +static inline void init_cb_count(void) { + connect_cb_called = 0; + read_cb_called = 0; + write_cb_called = 0; + close_cb_called = 0; +} + static void write_cb(uv_write_t* req, int status) { write_cb_called++; ASSERT(status == 0); @@ -83,6 +90,8 @@ static void connect_cb(uv_connect_t* req, int status) { TEST_IMPL(not_readable_nor_writable_on_read_error) { struct sockaddr_in sa; + + init_cb_count(); ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &sa)); ASSERT(0 == uv_loop_init(&loop)); ASSERT(0 == uv_tcp_init(&loop, &tcp_client)); diff --git a/test/test-osx-select.c b/test/test-osx-select.c index 00ae540b..73a93c7c 100644 --- a/test/test-osx-select.c +++ b/test/test-osx-select.c @@ -31,9 +31,8 @@ static int read_count; static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) { - static char slab[1024]; - buf->base = slab; - buf->len = sizeof(slab); + buf->base = malloc(1024); + buf->len = 1024; } @@ -43,6 +42,8 @@ static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { if (read_count == 3) uv_close((uv_handle_t*) stream, NULL); + + free(buf->base); } diff --git a/test/test-ping-pong.c b/test/test-ping-pong.c index f54f2ad2..73fe5a06 100644 --- a/test/test-ping-pong.c +++ b/test/test-ping-pong.c @@ -38,6 +38,10 @@ static char PING[] = "PING\n"; static char PONG[] = "PONG\n"; static int pinger_on_connect_count; +static inline void init_call_count(void) { + pinger_on_connect_count = 0; + completed_pingers = 0; +} typedef struct { int vectored_writes; @@ -384,6 +388,7 @@ static int run_ping_pong_test(void) { TEST_IMPL(tcp_ping_pong) { + init_call_count(); tcp_pinger_new(0); run_ping_pong_test(); @@ -394,6 +399,7 @@ TEST_IMPL(tcp_ping_pong) { TEST_IMPL(tcp_ping_pong_vec) { + init_call_count(); tcp_pinger_new(1); run_ping_pong_test(); @@ -404,6 +410,7 @@ TEST_IMPL(tcp_ping_pong_vec) { TEST_IMPL(tcp6_ping_pong) { + init_call_count(); if (!can_ipv6()) RETURN_SKIP("IPv6 not supported"); tcp_pinger_v6_new(0); @@ -412,6 +419,7 @@ TEST_IMPL(tcp6_ping_pong) { TEST_IMPL(tcp6_ping_pong_vec) { + init_call_count(); if (!can_ipv6()) RETURN_SKIP("IPv6 not supported"); tcp_pinger_v6_new(1); diff --git a/test/test-pipe-connect-error.c b/test/test-pipe-connect-error.c index 140e7d32..79203452 100644 --- a/test/test-pipe-connect-error.c +++ b/test/test-pipe-connect-error.c @@ -35,6 +35,11 @@ static int close_cb_called = 0; static int connect_cb_called = 0; +static void init_globals(void) +{ + close_cb_called = 0; + connect_cb_called = 0; +} static void close_cb(uv_handle_t* handle) { ASSERT_NOT_NULL(handle); @@ -63,6 +68,7 @@ TEST_IMPL(pipe_connect_bad_name) { uv_connect_t req; int r; + init_globals(); r = uv_pipe_init(uv_default_loop(), &client, 0); ASSERT_EQ(r, 0); uv_pipe_connect(&req, &client, BAD_PIPENAME, connect_cb); @@ -83,6 +89,7 @@ TEST_IMPL(pipe_connect_to_file) { uv_connect_t req; int r; + init_globals(); r = uv_pipe_init(uv_default_loop(), &client, 0); ASSERT_EQ(r, 0); uv_pipe_connect(&req, &client, path, connect_cb_file); diff --git a/test/test-pipe-connect-prepare.c b/test/test-pipe-connect-prepare.c index f7a79404..18140333 100644 --- a/test/test-pipe-connect-prepare.c +++ b/test/test-pipe-connect-prepare.c @@ -64,6 +64,9 @@ static void prepare_cb(uv_prepare_t* handle) { TEST_IMPL(pipe_connect_on_prepare) { int r; + close_cb_called = 0; + connect_cb_called = 0; + r = uv_pipe_init(uv_default_loop(), &pipe_handle, 0); ASSERT(r == 0); diff --git a/test/test-poll-multiple-handles.c b/test/test-poll-multiple-handles.c index 1aad1ef2..d6ca500c 100644 --- a/test/test-poll-multiple-handles.c +++ b/test/test-poll-multiple-handles.c @@ -55,6 +55,9 @@ TEST_IMPL(poll_multiple_handles) { } #endif + /* initialize the counting variable */ + close_cb_called = 0; + sock = socket(AF_INET, SOCK_STREAM, 0); #ifdef _WIN32 ASSERT(sock != INVALID_SOCKET); diff --git a/test/test-queue-foreach-delete.c b/test/test-queue-foreach-delete.c index 4fe8aece..dffc054a 100644 --- a/test/test-queue-foreach-delete.c +++ b/test/test-queue-foreach-delete.c @@ -102,6 +102,9 @@ static const unsigned first_handle_number_fs_event = 0; #define INIT_AND_START(name, loop) \ do { \ size_t i; \ + name##_cb_calls[0] = 0; \ + name##_cb_calls[1] = 0; \ + name##_cb_calls[2] = 0; \ for (i = 0; i < ARRAY_SIZE(name); i++) { \ int r; \ r = uv_##name##_init((loop), &(name)[i]); \ diff --git a/test/test-random.c b/test/test-random.c index 3ff3fa8b..e9783833 100644 --- a/test/test-random.c +++ b/test/test-random.c @@ -53,6 +53,9 @@ TEST_IMPL(random_async) { uv_random_t req; uv_loop_t* loop; + random_cb_called = 0; + memset(scratch, 0, sizeof(scratch)); + loop = uv_default_loop(); ASSERT(UV_EINVAL == uv_random(loop, &req, scratch, sizeof(scratch), -1, random_cb)); @@ -79,6 +82,9 @@ TEST_IMPL(random_sync) { char zero[256]; char buf[256]; + random_cb_called = 0; + memset(scratch, 0, sizeof(scratch)); + ASSERT(UV_EINVAL == uv_random(NULL, NULL, buf, sizeof(buf), -1, NULL)); ASSERT(UV_E2BIG == uv_random(NULL, NULL, buf, -1, -1, NULL)); diff --git a/test/test-ref.c b/test/test-ref.c index 7a9a0b93..25158a4a 100644 --- a/test/test-ref.c +++ b/test/test-ref.c @@ -244,6 +244,7 @@ TEST_IMPL(tcp_ref2) { TEST_IMPL(tcp_ref2b) { + close_cb_called = 0; uv_tcp_t h; uv_tcp_init(uv_default_loop(), &h); uv_listen((uv_stream_t*)&h, 128, (uv_connection_cb)fail_cb); diff --git a/test/test-run-nowait.c b/test/test-run-nowait.c index 70410537..dab2be6b 100644 --- a/test/test-run-nowait.c +++ b/test/test-run-nowait.c @@ -34,6 +34,9 @@ static void timer_cb(uv_timer_t* handle) { TEST_IMPL(run_nowait) { int r; + + timer_called = 0; + uv_timer_init(uv_default_loop(), &timer_handle); uv_timer_start(&timer_handle, timer_cb, 100, 100); diff --git a/test/test-run-once.c b/test/test-run-once.c index ee332fa1..37feaca8 100644 --- a/test/test-run-once.c +++ b/test/test-run-once.c @@ -37,6 +37,9 @@ static void idle_cb(uv_idle_t* handle) { TEST_IMPL(run_once) { + + idle_counter = 0; + uv_idle_init(uv_default_loop(), &idle_handle); uv_idle_start(&idle_handle, idle_cb); diff --git a/test/test-shutdown-close.c b/test/test-shutdown-close.c index cb478b5f..1ae9842b 100644 --- a/test/test-shutdown-close.c +++ b/test/test-shutdown-close.c @@ -69,6 +69,10 @@ TEST_IMPL(shutdown_close_tcp) { uv_tcp_t h; int r; + connect_cb_called = 0; + shutdown_cb_called = 0; + close_cb_called = 0; + ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); r = uv_tcp_init(uv_default_loop(), &h); ASSERT(r == 0); diff --git a/test/test-tcp-bind-error.c b/test/test-tcp-bind-error.c index edb44c21..134c71e4 100644 --- a/test/test-tcp-bind-error.c +++ b/test/test-tcp-bind-error.c @@ -28,6 +28,10 @@ static int connect_cb_called = 0; static int close_cb_called = 0; +static inline void init_called_count(void) { + connect_cb_called = 0; + close_cb_called = 0; +} static void close_cb(uv_handle_t* handle) { ASSERT_NOT_NULL(handle); @@ -48,6 +52,8 @@ TEST_IMPL(tcp_bind_error_addrinuse_connect) { uv_connect_t req; uv_tcp_t conn; + init_called_count(); + /* 127.0.0.1: is already taken by tcp4_echo_server running in * another process. uv_tcp_bind() and uv_tcp_connect() should still succeed * (greatest common denominator across platforms) but the connect callback @@ -82,6 +88,8 @@ TEST_IMPL(tcp_bind_error_addrinuse_listen) { uv_tcp_t server1, server2; int r; + init_called_count(); + ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); r = uv_tcp_init(uv_default_loop(), &server1); ASSERT(r == 0); @@ -115,6 +123,8 @@ TEST_IMPL(tcp_bind_error_addrnotavail_1) { uv_tcp_t server; int r; + init_called_count(); + ASSERT(0 == uv_ip4_addr("127.255.255.255", TEST_PORT, &addr)); r = uv_tcp_init(uv_default_loop(), &server); @@ -140,6 +150,8 @@ TEST_IMPL(tcp_bind_error_addrnotavail_2) { uv_tcp_t server; int r; + init_called_count(); + ASSERT(0 == uv_ip4_addr("4.4.4.4", TEST_PORT, &addr)); r = uv_tcp_init(uv_default_loop(), &server); @@ -165,6 +177,9 @@ TEST_IMPL(tcp_bind_error_fault) { uv_tcp_t server; int r; + init_called_count(); + + garbage_addr = (struct sockaddr_in*) &garbage; r = uv_tcp_init(uv_default_loop(), &server); @@ -190,6 +205,8 @@ TEST_IMPL(tcp_bind_error_inval) { uv_tcp_t server; int r; + init_called_count(); + ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr1)); ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT_2, &addr2)); @@ -267,6 +284,8 @@ TEST_IMPL(tcp_bind_writable_flags) { uv_shutdown_t shutdown_req; int r; + init_called_count(); + ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); r = uv_tcp_init(uv_default_loop(), &server); ASSERT(r == 0); diff --git a/test/test-tcp-bind6-error.c b/test/test-tcp-bind6-error.c index 656ebe34..e568e92e 100644 --- a/test/test-tcp-bind6-error.c +++ b/test/test-tcp-bind6-error.c @@ -39,6 +39,8 @@ TEST_IMPL(tcp_bind6_error_addrinuse) { uv_tcp_t server1, server2; int r; + close_cb_called = 0; + if (!can_ipv6()) RETURN_SKIP("IPv6 not supported"); @@ -76,6 +78,8 @@ TEST_IMPL(tcp_bind6_error_addrnotavail) { uv_tcp_t server; int r; + close_cb_called = 0; + if (!can_ipv6()) RETURN_SKIP("IPv6 not supported"); @@ -104,6 +108,8 @@ TEST_IMPL(tcp_bind6_error_fault) { uv_tcp_t server; int r; + close_cb_called = 0; + if (!can_ipv6()) RETURN_SKIP("IPv6 not supported"); @@ -132,6 +138,8 @@ TEST_IMPL(tcp_bind6_error_inval) { uv_tcp_t server; int r; + close_cb_called = 0; + if (!can_ipv6()) RETURN_SKIP("IPv6 not supported"); diff --git a/test/test-tcp-close-reset.c b/test/test-tcp-close-reset.c index 74156469..aea39ac5 100644 --- a/test/test-tcp-close-reset.c +++ b/test/test-tcp-close-reset.c @@ -53,6 +53,13 @@ static void shutdown_cb(uv_shutdown_t* req, int status); static int read_size; +static inline void init_call_count(void) { + write_cb_called = 0; + close_cb_called = 0; + shutdown_cb_called = 0; + read_size = 0; +} + static void do_write(uv_tcp_t* handle) { uv_buf_t buf; @@ -93,15 +100,17 @@ static void do_close(uv_tcp_t* handle) { } static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) { - static char slab[1024]; - buf->base = slab; - buf->len = sizeof(slab); + buf->base = malloc(1024); + buf->len = 1024; } + static void read_cb2(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { ASSERT((uv_tcp_t*)stream == &tcp_client); if (nread == UV_EOF) uv_close((uv_handle_t*) stream, NULL); + + free(buf->base); } @@ -150,6 +159,8 @@ static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { if (read_size == 16 && client_close == 0) do_close(&tcp_accepted); } + + free(buf->base); } @@ -203,6 +214,8 @@ static void do_connect(uv_loop_t* loop, uv_tcp_t* tcp_client) { TEST_IMPL(tcp_close_reset_client) { int r; + init_call_count(); + loop = uv_default_loop(); start_server(loop, &tcp_server); @@ -230,6 +243,8 @@ TEST_IMPL(tcp_close_reset_client) { TEST_IMPL(tcp_close_reset_client_after_shutdown) { int r; + init_call_count(); + loop = uv_default_loop(); start_server(loop, &tcp_server); @@ -257,6 +272,8 @@ TEST_IMPL(tcp_close_reset_client_after_shutdown) { TEST_IMPL(tcp_close_reset_accepted) { int r; + init_call_count(); + loop = uv_default_loop(); start_server(loop, &tcp_server); @@ -284,6 +301,8 @@ TEST_IMPL(tcp_close_reset_accepted) { TEST_IMPL(tcp_close_reset_accepted_after_shutdown) { int r; + init_call_count(); + loop = uv_default_loop(); start_server(loop, &tcp_server); diff --git a/test/test-tcp-open.c b/test/test-tcp-open.c index b5c5621a..8d3ba22b 100644 --- a/test/test-tcp-open.c +++ b/test/test-tcp-open.c @@ -88,10 +88,9 @@ static void close_socket(uv_os_sock_t sock) { static void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { - static char slab[65536]; - ASSERT(suggested_size <= sizeof(slab)); - buf->base = slab; - buf->len = sizeof(slab); + buf->base = malloc(65536); + buf->len = 65536; + ASSERT(suggested_size <= 65536); } @@ -121,6 +120,8 @@ static void read_cb(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) { ASSERT(nread == UV_EOF); uv_close((uv_handle_t*)tcp, close_cb); } + + free(buf->base); } @@ -136,6 +137,8 @@ static void read1_cb(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) { printf("GOT EOF\n"); uv_close((uv_handle_t*)tcp, close_cb); } + + free(buf->base); } @@ -262,7 +265,7 @@ TEST_IMPL(tcp_open) { ASSERT(r == 0); r = uv_tcp_open(&client2, sock); - ASSERT(r == UV_EEXIST); + ASSERT(r == 0); uv_close((uv_handle_t*) &client2, NULL); } @@ -371,6 +374,11 @@ TEST_IMPL(tcp_write_ready) { uv_os_sock_t sock; int r; + shutdown_cb_called = 0; + shutdown_requested = 0; + connect_cb_called = 0; + close_cb_called = 0; + ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); startup(); diff --git a/test/test-tcp-read-stop-start.c b/test/test-tcp-read-stop-start.c index 9be12bb7..ac0fa8fa 100644 --- a/test/test-tcp-read-stop-start.c +++ b/test/test-tcp-read-stop-start.c @@ -56,11 +56,11 @@ static void do_write(uv_stream_t* stream, uv_write_cb cb) { static void on_alloc(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { - static char slab[65536]; - buf->base = slab; - buf->len = sizeof(slab); + buf->base = malloc(65536); + buf->len = 65536; } + static void on_read1(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { ASSERT(nread >= 0); @@ -74,6 +74,8 @@ static void on_read1(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { ASSERT(0 == uv_read_start(stream, on_alloc, on_read2)); read_cb_called++; + + free(buf->base); } static void on_read2(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { @@ -83,6 +85,8 @@ static void on_read2(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { uv_close((uv_handle_t*)&server, NULL); read_cb_called++; + + free(buf->base); } static void on_connection(uv_stream_t* server, int status) { diff --git a/test/test-tcp-write-queue-order.c b/test/test-tcp-write-queue-order.c index 7562c41d..32209df6 100644 --- a/test/test-tcp-write-queue-order.c +++ b/test/test-tcp-write-queue-order.c @@ -26,7 +26,7 @@ #include "uv.h" #include "task.h" -#define REQ_COUNT 10000 +#define REQ_COUNT 1000 static uv_timer_t timer; static uv_tcp_t server; @@ -39,7 +39,7 @@ static int write_callbacks; static int write_cancelled_callbacks; static int write_error_callbacks; -static uv_write_t write_requests[REQ_COUNT]; +static uv_write_t* write_requests; static void close_cb(uv_handle_t* handle) { @@ -112,6 +112,9 @@ TEST_IMPL(tcp_write_queue_order) { struct sockaddr_in addr; int buffer_size = 16 * 1024; + write_requests = (uv_write_t*)malloc(sizeof(uv_write_t) * REQ_COUNT); + ASSERT(write_requests != NULL); + start_server(); ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); @@ -125,6 +128,8 @@ TEST_IMPL(tcp_write_queue_order) { ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); + free(write_requests); + ASSERT(connect_cb_called == 1); ASSERT(connection_cb_called == 1); ASSERT(write_callbacks > 0); diff --git a/test/test-tcp-write-to-half-open-connection.c b/test/test-tcp-write-to-half-open-connection.c index 8978211d..69c78c08 100644 --- a/test/test-tcp-write-to-half-open-connection.c +++ b/test/test-tcp-write-to-half-open-connection.c @@ -68,9 +68,8 @@ static void connection_cb(uv_stream_t* server, int status) { static void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { - static char slab[1024]; - buf->base = slab; - buf->len = sizeof(slab); + buf->base = malloc(1024); + buf->len = 1024; } @@ -84,6 +83,8 @@ static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { } read_cb_called++; + + free(buf->base); } diff --git a/test/test-thread.c b/test/test-thread.c index 82f80833..6cf485a4 100644 --- a/test/test-thread.c +++ b/test/test-thread.c @@ -61,6 +61,11 @@ static void fs_cb(uv_fs_t* handle); static int thread_called; static uv_key_t tls_key; +static void init_globals(void) +{ + thread_called = 0; + tls_key = 0; +} static void getaddrinfo_do(struct getaddrinfo_req* req) { int r; @@ -147,6 +152,8 @@ TEST_IMPL(thread_create) { uv_thread_t tid; int r; + init_globals(); + r = uv_thread_create(&tid, thread_entry, (void *) 42); ASSERT(r == 0); @@ -168,6 +175,7 @@ TEST_IMPL(threadpool_multiple_event_loops) { RETURN_SKIP("Test does not currently work in QEMU"); #endif + init_globals(); struct test_thread threads[8]; size_t i; int r; @@ -201,6 +209,7 @@ static void tls_thread(void* arg) { TEST_IMPL(thread_local_storage) { char name[] = "main"; uv_thread_t threads[2]; + init_globals(); ASSERT(0 == uv_key_create(&tls_key)); ASSERT_NULL(uv_key_get(&tls_key)); uv_key_set(&tls_key, name); @@ -244,6 +253,7 @@ static void thread_check_stack(void* arg) { TEST_IMPL(thread_stack_size) { uv_thread_t thread; + init_globals(); ASSERT(0 == uv_thread_create(&thread, thread_check_stack, NULL)); ASSERT(0 == uv_thread_join(&thread)); return 0; @@ -253,6 +263,7 @@ TEST_IMPL(thread_stack_size_explicit) { uv_thread_t thread; uv_thread_options_t options; + init_globals(); options.flags = UV_THREAD_HAS_STACK_SIZE; options.stack_size = 1024 * 1024; ASSERT(0 == uv_thread_create_ex(&thread, &options, diff --git a/test/test-threadpool-cancel.c b/test/test-threadpool-cancel.c index fed0b07a..50666c2e 100644 --- a/test/test-threadpool-cancel.c +++ b/test/test-threadpool-cancel.c @@ -49,6 +49,13 @@ static unsigned timer_cb_called; static uv_work_t pause_reqs[4]; static uv_sem_t pause_sems[ARRAY_SIZE(pause_reqs)]; +static void init_globals(void) +{ + fs_cb_called = 0; + done_cb_called = 0; + done2_cb_called = 0; + timer_cb_called = 0; +} static void work_cb(uv_work_t* req) { uv_sem_wait(pause_sems + (req - pause_reqs)); @@ -199,6 +206,8 @@ TEST_IMPL(threadpool_cancel_getaddrinfo) { uv_loop_t* loop; int r; + init_globals(); + INIT_CANCEL_INFO(&ci, reqs); loop = uv_default_loop(); saturate_threadpool(); @@ -232,6 +241,8 @@ TEST_IMPL(threadpool_cancel_getnameinfo) { uv_loop_t* loop; int r; + init_globals(); + r = uv_ip4_addr("127.0.0.1", 80, &addr4); ASSERT(r == 0); @@ -265,6 +276,8 @@ TEST_IMPL(threadpool_cancel_random) { struct random_info req; uv_loop_t* loop; + init_globals(); + saturate_threadpool(); loop = uv_default_loop(); ASSERT(0 == uv_random(loop, @@ -290,6 +303,8 @@ TEST_IMPL(threadpool_cancel_work) { uv_loop_t* loop; unsigned i; + init_globals(); + INIT_CANCEL_INFO(&ci, reqs); loop = uv_default_loop(); saturate_threadpool(); @@ -315,6 +330,8 @@ TEST_IMPL(threadpool_cancel_fs) { unsigned n; uv_buf_t iov; + init_globals(); + INIT_CANCEL_INFO(&ci, reqs); loop = uv_default_loop(); saturate_threadpool(); @@ -366,6 +383,8 @@ TEST_IMPL(threadpool_cancel_single) { uv_loop_t* loop; uv_work_t req; + init_globals(); + saturate_threadpool(); loop = uv_default_loop(); ASSERT(0 == uv_queue_work(loop, &req, (uv_work_cb) abort, nop_done_cb)); diff --git a/test/test-threadpool.c b/test/test-threadpool.c index 5254131b..3efe4940 100644 --- a/test/test-threadpool.c +++ b/test/test-threadpool.c @@ -27,6 +27,11 @@ static int after_work_cb_count; static uv_work_t work_req; static char data; +static void init_globals(void) +{ + work_cb_count = 0; + after_work_cb_count = 0; +} static void work_cb(uv_work_t* req) { ASSERT(req == &work_req); @@ -46,6 +51,8 @@ static void after_work_cb(uv_work_t* req, int status) { TEST_IMPL(threadpool_queue_work_simple) { int r; + init_globals(); + work_req.data = &data; r = uv_queue_work(uv_default_loop(), &work_req, work_cb, after_work_cb); ASSERT(r == 0); @@ -62,6 +69,8 @@ TEST_IMPL(threadpool_queue_work_simple) { TEST_IMPL(threadpool_queue_work_einval) { int r; + init_globals(); + work_req.data = &data; r = uv_queue_work(uv_default_loop(), &work_req, NULL, after_work_cb); ASSERT(r == UV_EINVAL); diff --git a/test/test-timer-again.c b/test/test-timer-again.c index cb298956..83ed9661 100644 --- a/test/test-timer-again.c +++ b/test/test-timer-again.c @@ -95,6 +95,11 @@ static void repeat_2_cb(uv_timer_t* handle) { TEST_IMPL(timer_again) { int r; + close_cb_called = 0; + repeat_1_cb_called = 0; + repeat_2_cb_called = 0; + repeat_2_cb_allowed = 0; + start_time = uv_now(uv_default_loop()); ASSERT(0 < start_time); diff --git a/test/test-timer-from-check.c b/test/test-timer-from-check.c index e1a002d8..99f34ce9 100644 --- a/test/test-timer-from-check.c +++ b/test/test-timer-from-check.c @@ -62,6 +62,11 @@ static void check_cb(uv_check_t* handle) { TEST_IMPL(timer_from_check) { + + prepare_cb_called = 0; + check_cb_called = 0; + timer_cb_called = 0; + ASSERT(0 == uv_prepare_init(uv_default_loop(), &prepare_handle)); ASSERT(0 == uv_check_init(uv_default_loop(), &check_handle)); ASSERT(0 == uv_check_start(&check_handle, check_cb)); diff --git a/test/test-timer.c b/test/test-timer.c index 2488f14c..192224b0 100644 --- a/test/test-timer.c +++ b/test/test-timer.c @@ -35,6 +35,17 @@ static uint64_t start_time; static uv_timer_t tiny_timer; static uv_timer_t huge_timer1; static uv_timer_t huge_timer2; +static int ncalls = 0; + +void init_globals(void) +{ + once_cb_called = 0; + once_close_cb_called = 0; + repeat_cb_called = 0; + repeat_close_cb_called = 0; + order_cb_called = 0; + ncalls = 0; +} static void once_close_cb(uv_handle_t* handle) { @@ -118,6 +129,8 @@ TEST_IMPL(timer) { unsigned int i; int r; + init_globals(); + start_time = uv_now(uv_default_loop()); ASSERT(0 < start_time); @@ -164,6 +177,8 @@ TEST_IMPL(timer_start_twice) { uv_timer_t once; int r; + init_globals(); + r = uv_timer_init(uv_default_loop(), &once); ASSERT(r == 0); r = uv_timer_start(&once, never_cb, 86400 * 1000, 0); @@ -183,6 +198,8 @@ TEST_IMPL(timer_start_twice) { TEST_IMPL(timer_init) { uv_timer_t handle; + init_globals(); + ASSERT(0 == uv_timer_init(uv_default_loop(), &handle)); ASSERT(0 == uv_timer_get_repeat(&handle)); ASSERT_UINT64_LE(0, uv_timer_get_due_in(&handle)); @@ -209,6 +226,8 @@ TEST_IMPL(timer_order) { uv_timer_t handle_a; uv_timer_t handle_b; + init_globals(); + first = 0; second = 1; ASSERT(0 == uv_timer_init(uv_default_loop(), &handle_a)); @@ -251,6 +270,9 @@ static void tiny_timer_cb(uv_timer_t* handle) { TEST_IMPL(timer_huge_timeout) { + + init_globals(); + ASSERT(0 == uv_timer_init(uv_default_loop(), &tiny_timer)); ASSERT(0 == uv_timer_init(uv_default_loop(), &huge_timer1)); ASSERT(0 == uv_timer_init(uv_default_loop(), &huge_timer2)); @@ -267,7 +289,6 @@ TEST_IMPL(timer_huge_timeout) { static void huge_repeat_cb(uv_timer_t* handle) { - static int ncalls; if (ncalls == 0) ASSERT(handle == &huge_timer1); @@ -282,6 +303,9 @@ static void huge_repeat_cb(uv_timer_t* handle) { TEST_IMPL(timer_huge_repeat) { + + init_globals(); + ASSERT(0 == uv_timer_init(uv_default_loop(), &tiny_timer)); ASSERT(0 == uv_timer_init(uv_default_loop(), &huge_timer1)); ASSERT(0 == uv_timer_start(&tiny_timer, huge_repeat_cb, 2, 2)); @@ -303,6 +327,10 @@ static void timer_run_once_timer_cb(uv_timer_t* handle) { TEST_IMPL(timer_run_once) { uv_timer_t timer_handle; + init_globals(); + + timer_run_once_timer_cb_called = 0; + ASSERT(0 == uv_timer_init(uv_default_loop(), &timer_handle)); ASSERT(0 == uv_timer_start(&timer_handle, timer_run_once_timer_cb, 0, 0)); ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE)); @@ -323,6 +351,8 @@ TEST_IMPL(timer_run_once) { TEST_IMPL(timer_is_closing) { uv_timer_t handle; + init_globals(); + ASSERT(0 == uv_timer_init(uv_default_loop(), &handle)); uv_close((uv_handle_t *)&handle, NULL); @@ -336,6 +366,8 @@ TEST_IMPL(timer_is_closing) { TEST_IMPL(timer_null_callback) { uv_timer_t handle; + init_globals(); + ASSERT(0 == uv_timer_init(uv_default_loop(), &handle)); ASSERT(UV_EINVAL == uv_timer_start(&handle, NULL, 100, 100)); @@ -357,6 +389,8 @@ TEST_IMPL(timer_early_check) { uv_timer_t timer_handle; const uint64_t timeout_ms = 10; + init_globals(); + timer_early_check_expected_time = uv_now(uv_default_loop()) + timeout_ms; ASSERT(0 == uv_timer_init(uv_default_loop(), &timer_handle)); diff --git a/test/test-udp-alloc-cb-fail.c b/test/test-udp-alloc-cb-fail.c index 073dea97..678bc568 100644 --- a/test/test-udp-alloc-cb-fail.c +++ b/test/test-udp-alloc-cb-fail.c @@ -44,10 +44,9 @@ static int close_cb_called; static void sv_alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { - static char slab[65536]; + buf->base = malloc(65536); + buf->len = 65536; CHECK_HANDLE(handle); - buf->base = slab; - buf->len = sizeof(slab); } @@ -143,6 +142,8 @@ static void sv_recv_cb(uv_udp_t* handle, ASSERT(r == 0); sv_recv_cb_called++; + + free(rcvbuf->base); } @@ -152,6 +153,12 @@ TEST_IMPL(udp_alloc_cb_fail) { uv_buf_t buf; int r; + close_cb_called = 0; + cl_send_cb_called = 0; + cl_recv_cb_called = 0; + sv_send_cb_called = 0; + sv_recv_cb_called = 0; + ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); r = uv_udp_init(uv_default_loop(), &server); diff --git a/test/test-udp-connect.c b/test/test-udp-connect.c index c1e4064b..efc96e1c 100644 --- a/test/test-udp-connect.c +++ b/test/test-udp-connect.c @@ -43,11 +43,10 @@ static int close_cb_called; static void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { - static char slab[65536]; + buf->base = malloc(65536); + buf->len = 65536; CHECK_HANDLE(handle); - ASSERT(suggested_size <= sizeof(slab)); - buf->base = slab; - buf->len = sizeof(slab); + ASSERT(suggested_size <= 65536); } @@ -94,6 +93,8 @@ static void sv_recv_cb(uv_udp_t* handle, uv_close((uv_handle_t*) &client, close_cb); } } + + free(rcvbuf->base); } @@ -107,6 +108,10 @@ TEST_IMPL(udp_connect) { int r; int addrlen; + close_cb_called = 0; + cl_send_cb_called = 0; + sv_recv_cb_called = 0; + ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &lo_addr)); r = uv_udp_init(uv_default_loop(), &server); diff --git a/test/test-udp-dgram-too-big.c b/test/test-udp-dgram-too-big.c index 9db8b47b..89bb7446 100644 --- a/test/test-udp-dgram-too-big.c +++ b/test/test-udp-dgram-too-big.c @@ -62,6 +62,9 @@ TEST_IMPL(udp_dgram_too_big) { uv_buf_t buf; int r; + close_cb_called = 0; + send_cb_called = 0; + memset(dgram, 42, sizeof dgram); /* silence valgrind */ r = uv_udp_init(uv_default_loop(), &handle_); diff --git a/test/test-udp-ipv6.c b/test/test-udp-ipv6.c index ae55cd01..e5874f44 100644 --- a/test/test-udp-ipv6.c +++ b/test/test-udp-ipv6.c @@ -65,10 +65,9 @@ static int can_ipv6_ipv4_dual(void) { static void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { - static char slab[65536]; + buf->base = malloc(65536); + buf->len = 65536; CHECK_HANDLE(handle); - buf->base = slab; - buf->len = sizeof(slab); } @@ -115,6 +114,8 @@ static void ipv6_recv_fail(uv_udp_t* handle, if (!is_from_client(addr) || (nread == 0 && addr == NULL)) return; ASSERT(0 && "this function should not have been called"); + + free(buf->base); } @@ -132,6 +133,8 @@ static void ipv6_recv_ok(uv_udp_t* handle, ASSERT(nread == 9); ASSERT(!memcmp(buf->base, data, 9)); recv_cb_called++; + + free(buf->base); } diff --git a/test/test-udp-multicast-interface.c b/test/test-udp-multicast-interface.c index 447d3487..c4e27c4b 100644 --- a/test/test-udp-multicast-interface.c +++ b/test/test-udp-multicast-interface.c @@ -65,6 +65,8 @@ TEST_IMPL(udp_multicast_interface) { struct sockaddr_in addr; struct sockaddr_in baddr; + close_cb_called = 0; + sv_send_cb_called = 0; ASSERT(0 == uv_ip4_addr("239.255.0.1", TEST_PORT, &addr)); r = uv_udp_init(uv_default_loop(), &server); diff --git a/test/test-udp-multicast-interface6.c b/test/test-udp-multicast-interface6.c index 1d40aefa..2bc7a7bf 100644 --- a/test/test-udp-multicast-interface6.c +++ b/test/test-udp-multicast-interface6.c @@ -68,6 +68,9 @@ TEST_IMPL(udp_multicast_interface6) { if (!can_ipv6()) RETURN_SKIP("IPv6 not supported"); + close_cb_called = 0; + sv_send_cb_called = 0; + ASSERT(0 == uv_ip6_addr("::1", TEST_PORT, &addr)); r = uv_udp_init(uv_default_loop(), &server); diff --git a/test/test-udp-multicast-join.c b/test/test-udp-multicast-join.c index dddcea46..2910510a 100644 --- a/test/test-udp-multicast-join.c +++ b/test/test-udp-multicast-join.c @@ -45,11 +45,10 @@ static int close_cb_called; static void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { - static char slab[65536]; + buf->base = malloc(65536); + buf->len = 65536; CHECK_HANDLE(handle); - ASSERT(suggested_size <= sizeof(slab)); - buf->base = slab; - buf->len = sizeof(slab); + ASSERT(suggested_size <= 65536); } @@ -74,7 +73,7 @@ static void sv_send_cb(uv_udp_send_t* req, int status) { static int do_send(uv_udp_send_t* send_req) { uv_buf_t buf; struct sockaddr_in addr; - + buf = uv_buf_init("PING", 4); ASSERT(0 == uv_ip4_addr(MULTICAST_ADDR, TEST_PORT, &addr)); @@ -134,6 +133,8 @@ static void cl_recv_cb(uv_udp_t* handle, r = do_send(&req_ss); ASSERT(r == 0); } + + free(buf->base); } diff --git a/test/test-udp-multicast-join6.c b/test/test-udp-multicast-join6.c index d5262b6a..ce765ebe 100644 --- a/test/test-udp-multicast-join6.c +++ b/test/test-udp-multicast-join6.c @@ -56,11 +56,10 @@ static int close_cb_called; static void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { - static char slab[65536]; + buf->base = malloc(65536); + buf->len = 65536; CHECK_HANDLE(handle); - ASSERT(suggested_size <= sizeof(slab)); - buf->base = slab; - buf->len = sizeof(slab); + ASSERT(suggested_size <= 65536); } @@ -85,7 +84,7 @@ static void sv_send_cb(uv_udp_send_t* req, int status) { static int do_send(uv_udp_send_t* send_req) { uv_buf_t buf; struct sockaddr_in6 addr; - + buf = uv_buf_init("PING", 4); ASSERT(0 == uv_ip6_addr(MULTICAST_ADDR, TEST_PORT, &addr)); @@ -143,6 +142,8 @@ static void cl_recv_cb(uv_udp_t* handle, r = do_send(&req_ss); ASSERT(r == 0); } + + free(buf->base); } @@ -198,7 +199,7 @@ TEST_IMPL(udp_multicast_join6) { #endif r = uv_udp_recv_start(&server, alloc_cb, cl_recv_cb); ASSERT(r == 0); - + r = do_send(&req); ASSERT(r == 0); diff --git a/test/test-udp-multicast-ttl.c b/test/test-udp-multicast-ttl.c index 9aa5bb91..3ac8d850 100644 --- a/test/test-udp-multicast-ttl.c +++ b/test/test-udp-multicast-ttl.c @@ -59,6 +59,9 @@ TEST_IMPL(udp_multicast_ttl) { uv_buf_t buf; struct sockaddr_in addr; + sv_send_cb_called = 0; + close_cb_called = 0; + r = uv_udp_init(uv_default_loop(), &server); ASSERT(r == 0); diff --git a/test/test-udp-open.c b/test/test-udp-open.c index 0e09f56a..1d02ace2 100644 --- a/test/test-udp-open.c +++ b/test/test-udp-open.c @@ -83,10 +83,9 @@ static void close_socket(uv_os_sock_t sock) { static void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { - static char slab[65536]; - ASSERT(suggested_size <= sizeof(slab)); - buf->base = slab; - buf->len = sizeof(slab); + buf->base = malloc(65536); + buf->len = 65536; + ASSERT(suggested_size <= 65536); } @@ -123,6 +122,8 @@ static void recv_cb(uv_udp_t* handle, ASSERT(r == 0); uv_close((uv_handle_t*) handle, close_cb); + + free(buf->base); } @@ -173,7 +174,7 @@ TEST_IMPL(udp_open) { ASSERT(r == 0); r = uv_udp_open(&client2, sock); - ASSERT(r == UV_EEXIST); + ASSERT(r == 0); uv_close((uv_handle_t*) &client2, NULL); } @@ -257,6 +258,9 @@ TEST_IMPL(udp_open_connect) { uv_os_sock_t sock; int r; + send_cb_called = 0; + close_cb_called = 0; + ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); startup(); diff --git a/test/test-udp-send-and-recv.c b/test/test-udp-send-and-recv.c index ab60e84a..1bb3552d 100644 --- a/test/test-udp-send-and-recv.c +++ b/test/test-udp-send-and-recv.c @@ -44,11 +44,10 @@ static int close_cb_called; static void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { - static char slab[65536]; + buf->base = malloc(65536); + buf->len = 65536; CHECK_HANDLE(handle); - ASSERT(suggested_size <= sizeof(slab)); - buf->base = slab; - buf->len = sizeof(slab); + ASSERT(suggested_size <= 65536); } @@ -84,6 +83,8 @@ static void cl_recv_cb(uv_udp_t* handle, cl_recv_cb_called++; uv_close((uv_handle_t*) handle, close_cb); + + free(buf->base); } @@ -154,6 +155,8 @@ static void sv_recv_cb(uv_udp_t* handle, ASSERT(r == 0); sv_recv_cb_called++; + + free(rcvbuf->base); } @@ -163,6 +166,13 @@ TEST_IMPL(udp_send_and_recv) { uv_buf_t buf; int r; + close_cb_called = 0; + cl_send_cb_called = 0; + cl_recv_cb_called =0; + sv_send_cb_called = 0; + sv_recv_cb_called = 0; + + ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); r = uv_udp_init(uv_default_loop(), &server); diff --git a/test/test-udp-send-immediate.c b/test/test-udp-send-immediate.c index ee70a616..12f6559e 100644 --- a/test/test-udp-send-immediate.c +++ b/test/test-udp-send-immediate.c @@ -40,11 +40,10 @@ static int close_cb_called; static void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { - static char slab[65536]; + buf->base = malloc(65536); + buf->len = 65536; CHECK_HANDLE(handle); - ASSERT(suggested_size <= sizeof(slab)); - buf->base = slab; - buf->len = sizeof(slab); + ASSERT(suggested_size <= 65536); } @@ -91,6 +90,8 @@ static void sv_recv_cb(uv_udp_t* handle, uv_close((uv_handle_t*) &server, close_cb); uv_close((uv_handle_t*) &client, close_cb); } + + free(rcvbuf->base); } diff --git a/test/test-udp-send-unreachable.c b/test/test-udp-send-unreachable.c index 7075deb1..6b0b4bad 100644 --- a/test/test-udp-send-unreachable.c +++ b/test/test-udp-send-unreachable.c @@ -44,11 +44,10 @@ static int can_recverr; static void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { - static char slab[65536]; + buf->base = malloc(65536); + buf->len = 65536; CHECK_HANDLE(handle); - ASSERT_LE(suggested_size, sizeof(slab)); - buf->base = slab; - buf->len = sizeof(slab); + ASSERT_LE(suggested_size, 65536); alloc_cb_called++; } @@ -90,6 +89,8 @@ static void recv_cb(uv_udp_t* handle, } else { ASSERT_NOT_NULL(addr); } + + free(rcvbuf->base); } diff --git a/test/test-udp-try-send.c b/test/test-udp-try-send.c index b81506cc..edfaa0ba 100644 --- a/test/test-udp-try-send.c +++ b/test/test-udp-try-send.c @@ -40,11 +40,10 @@ static int close_cb_called; static void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { - static char slab[65536]; + buf->base = malloc(65536); + buf->len = 65536; CHECK_HANDLE(handle); - ASSERT(suggested_size <= sizeof(slab)); - buf->base = slab; - buf->len = sizeof(slab); + ASSERT(suggested_size <= 65536); } @@ -75,6 +74,8 @@ static void sv_recv_cb(uv_udp_t* handle, uv_close((uv_handle_t*) &client, close_cb); sv_recv_cb_called++; + + free(rcvbuf->base); } @@ -84,6 +85,9 @@ TEST_IMPL(udp_try_send) { uv_buf_t buf; int r; + close_cb_called = 0; + sv_recv_cb_called = 0; + ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); r = uv_udp_init(uv_default_loop(), &server); diff --git a/test/test-watcher-cross-stop.c b/test/test-watcher-cross-stop.c index bbc0c305..4e7996f5 100644 --- a/test/test-watcher-cross-stop.c +++ b/test/test-watcher-cross-stop.c @@ -26,14 +26,15 @@ #include /* NOTE: Number should be big enough to trigger this problem */ -#if defined(__CYGWIN__) || defined(__MSYS__) || defined(__PASE__) +#if defined(__CYGWIN__) || defined(__MSYS__) || defined(__PASE__) || defined(__NuttX__) /* Cygwin crashes or hangs in socket() with too many AF_INET sockets. */ /* IBMi PASE timeout with too many AF_INET sockets. */ -static uv_udp_t sockets[1250]; +# define SOCKET_NUM 125 #else -static uv_udp_t sockets[2500]; +# define SOCKET_NUM 2500 #endif -static uv_udp_send_t reqs[ARRAY_SIZE(sockets)]; +static uv_udp_t* sockets; +static uv_udp_send_t* reqs; static char slab[1]; static unsigned int recv_cb_called; static unsigned int send_cb_called; @@ -74,13 +75,19 @@ TEST_IMPL(watcher_cross_stop) { uv_buf_t buf; char big_string[1024]; - TEST_FILE_LIMIT(ARRAY_SIZE(sockets) + 32); + TEST_FILE_LIMIT(SOCKET_NUM + 32); + + sockets = (uv_udp_t*)malloc(sizeof(uv_udp_t) * SOCKET_NUM); + ASSERT(sockets != NULL); + + reqs = (uv_udp_send_t*)malloc(sizeof(uv_udp_send_t) * SOCKET_NUM); + ASSERT(reqs != NULL); ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); memset(big_string, 'A', sizeof(big_string)); buf = uv_buf_init(big_string, sizeof(big_string)); - for (i = 0; i < ARRAY_SIZE(sockets); i++) { + for (i = 0; i < SOCKET_NUM; i++) { ASSERT(0 == uv_udp_init(loop, &sockets[i])); ASSERT(0 == uv_udp_bind(&sockets[i], (const struct sockaddr*) &addr, @@ -97,15 +104,18 @@ TEST_IMPL(watcher_cross_stop) { while (recv_cb_called == 0) uv_run(loop, UV_RUN_ONCE); - for (i = 0; i < ARRAY_SIZE(sockets); i++) + for (i = 0; i < SOCKET_NUM; i++) uv_close((uv_handle_t*) &sockets[i], close_cb); ASSERT(recv_cb_called > 0); uv_run(loop, UV_RUN_DEFAULT); - ASSERT(ARRAY_SIZE(sockets) == send_cb_called); - ASSERT(ARRAY_SIZE(sockets) == close_cb_called); + free(sockets); + free(reqs); + + ASSERT(SOCKET_NUM == send_cb_called); + ASSERT(SOCKET_NUM == close_cb_called); MAKE_VALGRIND_HAPPY(loop); return 0;