diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ef5c2b2f..aa97506d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -165,5 +165,5 @@ not send out notifications when you add commits. [issue tracker]: https://github.com/libuv/libuv/issues [libuv mailing list]: http://groups.google.com/group/libuv [IRC]: http://webchat.freelibuv.net/?channels=libuv -[Google C/C++ style guide]: http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml +[Google C/C++ style guide]: https://google.github.io/styleguide/cppguide.html [project maintainers]: https://github.com/libuv/libuv/blob/master/MAINTAINERS.md diff --git a/LICENSE b/LICENSE index 4d411670..41ba44c2 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,29 @@ -libuv is part of the Node project: http://nodejs.org/ -libuv may be distributed alone under Node's license: +libuv is licensed for use as follows: + +==== +Copyright (c) 2015-present libuv project contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +==== + +This license applies to parts of libuv originating from the +https://github.com/joyent/libuv repository: ==== diff --git a/MAINTAINERS.md b/MAINTAINERS.md index 2f0e618c..5974d9d3 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -7,8 +7,11 @@ libuv is currently managed by the following individuals: - GPG key: D77B 1E34 243F BAF0 5F8E 9CC3 4F55 C8C8 46AB 89B9 (pubkey-bnoordhuis) * **Bert Belder** ([@piscisaureus](https://github.com/piscisaureus)) * **Colin Ihrig** ([@cjihrig](https://github.com/cjihrig)) + - GPG key: 94AE 3667 5C46 4D64 BAFA 68DD 7434 390B DBE9 B9C5 (pubkey-cjihrig) * **Fedor Indutny** ([@indutny](https://github.com/indutny)) - GPG key: AF2E EA41 EC34 47BF DD86 FED9 D706 3CCE 19B7 E890 (pubkey-indutny) +* **Imran Iqbal** ([@iWuzHere](https://github.com/iWuzHere)) + - GPG key: 9DFE AA5F 481B BF77 2D90 03CE D592 4925 2F8E C41A (pubkey-iwuzhere) * **Saúl Ibarra Corretgé** ([@saghul](https://github.com/saghul)) - GPG key: FDF5 1936 4458 319F A823 3DC9 410E 5553 AE9B C059 (pubkey-saghul) @@ -34,4 +37,3 @@ be garbage collected since nothing references it, so we'll create a tag for it: Commit the changes and push: $ git push origin pubkey-saghul - diff --git a/Makefile.am b/Makefile.am index 05ccd58a..882bbef5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -128,7 +128,7 @@ EXTRA_DIST = test/fixtures/empty_file \ TESTS = test/run-tests check_PROGRAMS = test/run-tests -test_run_tests_CFLAGS = +test_run_tests_CFLAGS = -Wno-long-long test_run_tests_LDFLAGS = test_run_tests_SOURCES = test/blackhole-server.c \ test/dns-server.c \ @@ -312,6 +312,7 @@ endif if DRAGONFLY include_HEADERS += include/uv-bsd.h +libuv_la_SOURCES += src/unix/freebsd.c src/unix/kqueue.c test_run_tests_LDFLAGS += -lutil endif diff --git a/README.md b/README.md index e94fcc90..1b40e76e 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,10 @@ Starting with version 1.0.0 libuv follows the [semantic versioning](http://semve scheme. The API change and backwards compatibility rules are those indicated by SemVer. libuv will keep a stable ABI across major releases. +## Licensing + +libuv is licensed under the MIT license. Check the [LICENSE file](LICENSE). + ## Community * [Mailing list](http://groups.google.com/group/libuv) diff --git a/configure.ac b/configure.ac index d9251f31..4a106bec 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ AC_ENABLE_SHARED AC_ENABLE_STATIC AC_PROG_CC AM_PROG_CC_C_O -CC_CHECK_CFLAGS_APPEND([-fvisibility=hidden]) +CC_FLAG_VISIBILITY #[-fvisibility=hidden] CC_CHECK_CFLAGS_APPEND([-g]) CC_CHECK_CFLAGS_APPEND([-std=gnu89]) CC_CHECK_CFLAGS_APPEND([-pedantic]) diff --git a/docs/Makefile b/docs/Makefile index 9d461ff8..d23c6948 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -57,7 +57,7 @@ html: @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." -livehtml: +livehtml: html $(SPHINXAUTOBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html dirhtml: diff --git a/docs/src/errors.rst b/docs/src/errors.rst index cec25f51..2ebaf1e4 100644 --- a/docs/src/errors.rst +++ b/docs/src/errors.rst @@ -8,6 +8,9 @@ In libuv errors are negative numbered constants. As a rule of thumb, whenever there is a status parameter, or an API functions returns an integer, a negative number will imply an error. +When a function which takes a callback returns an error, the callback will never +be called. + .. note:: Implementation detail: on Unix error codes are the negated `errno` (or `-errno`), while on Windows they are defined by libuv to arbitrary negative numbers. diff --git a/docs/src/fs.rst b/docs/src/fs.rst index 69e283f4..50c0de46 100644 --- a/docs/src/fs.rst +++ b/docs/src/fs.rst @@ -91,7 +91,8 @@ Data types UV_FS_SYMLINK, UV_FS_READLINK, UV_FS_CHOWN, - UV_FS_FCHOWN + UV_FS_FCHOWN, + UV_FS_REALPATH } uv_fs_type; .. c:type:: uv_dirent_t @@ -258,6 +259,12 @@ API Equivalent to :man:`utime(2)` and :man:`futime(2)` respectively. + .. note:: + AIX: This function only works for AIX 7.1 and newer. It can still be called on older + versions but will return ``UV_ENOSYS``. + + .. versionchanged:: 1.10.0 sub-second precission is supported on Windows + .. c:function:: int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb) Equivalent to :man:`link(2)`. diff --git a/docs/src/fs_event.rst b/docs/src/fs_event.rst index c2d7f520..c08ade2e 100644 --- a/docs/src/fs_event.rst +++ b/docs/src/fs_event.rst @@ -8,6 +8,20 @@ FS Event handles allow the user to monitor a given path for changes, for example if the file was renamed or there was a generic change in it. This handle uses the best backend for the job on each platform. +.. note:: + For AIX, the non default IBM bos.ahafs package has to be installed. + The AIX Event Infrastructure file system (ahafs) has some limitations: + + - ahafs tracks monitoring per process and is not thread safe. A separate process + must be spawned for each monitor for the same event. + - Events for file modification (writing to a file) are not received if only the + containing folder is watched. + + See documentation_ for more details. + + .. _documentation: http://www.ibm.com/developerworks/aix/library/au-aix_event_infrastructure/ + + Data types ---------- diff --git a/docs/src/misc.rst b/docs/src/misc.rst index f32af48f..3b7f31aa 100644 --- a/docs/src/misc.rst +++ b/docs/src/misc.rst @@ -183,7 +183,9 @@ API .. c:function:: int uv_get_process_title(char* buffer, size_t size) - Gets the title of the current process. + Gets the title of the current process. If `buffer` is `NULL` or `size` is + zero, `UV_EINVAL` is returned. If `size` cannot accommodate the process + title and terminating `NULL` character, the function returns `UV_ENOBUFS`. .. c:function:: int uv_set_process_title(const char* title) diff --git a/docs/src/stream.rst b/docs/src/stream.rst index ed0c79d0..7989cd4f 100644 --- a/docs/src/stream.rst +++ b/docs/src/stream.rst @@ -26,7 +26,11 @@ Data types .. c:type:: uv_write_t - Write request type. + Write request type. Careful attention must be paid when reusing objects of + this type. When a stream is in non-blocking mode, write requests sent + with ``uv_write`` will be queued. Reusing objects at this point is undefined + behaviour. It is safe to reuse the ``uv_write_t`` object only after the + callback passed to ``uv_write`` is fired. .. c:type:: void (*uv_read_cb)(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) @@ -61,7 +65,7 @@ Data types .. c:type:: void (*uv_shutdown_cb)(uv_shutdown_t* req, int status) - Callback called after s shutdown request has been completed. `status` will + Callback called after a shutdown request has been completed. `status` will be 0 in case of success, < 0 otherwise. .. c:type:: void (*uv_connection_cb)(uv_stream_t* server, int status) @@ -92,7 +96,7 @@ Public members .. c:member:: uv_stream_t* uv_write_t.send_handle - Pointer to the stream being sent using this write request.. + Pointer to the stream being sent using this write request. .. seealso:: The :c:type:`uv_handle_t` members also apply. diff --git a/src/unix/aix.c b/src/unix/aix.c index 2276985f..652cd980 100644 --- a/src/unix/aix.c +++ b/src/unix/aix.c @@ -156,7 +156,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { pqry.fd = pc.fd; rc = pollset_query(loop->backend_fd, &pqry); switch (rc) { - case -1: + case -1: assert(0 && "Failed to query pollset for file descriptor"); abort(); case 0: @@ -333,20 +333,20 @@ int uv_exepath(char* buffer, size_t* size) { pi.pi_pid = getpid(); res = getargs(&pi, sizeof(pi), args, sizeof(args)); - if (res < 0) + if (res < 0) return -EINVAL; /* * Possibilities for args: * i) an absolute path such as: /home/user/myprojects/nodejs/node * ii) a relative path such as: ./node or ../myprojects/nodejs/node - * iii) a bare filename such as "node", after exporting PATH variable + * iii) a bare filename such as "node", after exporting PATH variable * to its location. */ /* Case i) and ii) absolute or relative paths */ if (strchr(args, '/') != NULL) { - if (realpath(args, abspath) != abspath) + if (realpath(args, abspath) != abspath) return -errno; abspath_size = strlen(abspath); @@ -360,7 +360,7 @@ int uv_exepath(char* buffer, size_t* size) { return 0; } else { - /* Case iii). Search PATH environment variable */ + /* Case iii). Search PATH environment variable */ char trypath[PATH_MAX]; char *clonedpath = NULL; char *token = NULL; @@ -376,7 +376,7 @@ int uv_exepath(char* buffer, size_t* size) { token = strtok(clonedpath, ":"); while (token != NULL) { snprintf(trypath, sizeof(trypath) - 1, "%s/%s", token, args); - if (realpath(trypath, abspath) == abspath) { + if (realpath(trypath, abspath) == abspath) { /* Check the match is executable */ if (access(abspath, X_OK) == 0) { abspath_size = strlen(abspath); @@ -452,7 +452,7 @@ static char *uv__rawname(char *cp) { } -/* +/* * Determine whether given pathname is a directory * Returns 0 if the path is a directory, -1 if not * @@ -472,7 +472,7 @@ static int uv__path_is_a_directory(char* filename) { } -/* +/* * Check whether AHAFS is mounted. * Returns 0 if AHAFS is mounted, or an error code < 0 on failure */ @@ -547,7 +547,7 @@ static int uv__makedir_p(const char *dir) { return mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); } -/* +/* * Creates necessary subdirectories in the AIX Event Infrastructure * file system for monitoring the object specified. * Returns code from mkdir call @@ -665,7 +665,7 @@ static int uv__skip_lines(char **p, int n) { /* * Parse the event occurrence data to figure out what event just occurred * and take proper action. - * + * * The buf is a pointer to the buffer containing the event occurrence data * Returns 0 on success, -1 if unrecoverable error in parsing * @@ -891,9 +891,10 @@ int uv_set_process_title(const char* title) { int uv_get_process_title(char* buffer, size_t size) { - if (size > 0) { - buffer[0] = '\0'; - } + if (buffer == NULL || size == 0) + return -EINVAL; + + buffer[0] = '\0'; return 0; } diff --git a/src/unix/core.c b/src/unix/core.c index cdcd0b50..64522383 100644 --- a/src/unix/core.c +++ b/src/unix/core.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -40,11 +41,8 @@ #include /* getrusage */ #include -#ifdef __linux__ -# include -#endif - #ifdef __sun +# include # include # include #endif @@ -52,7 +50,6 @@ #ifdef __APPLE__ # include /* _NSGetExecutablePath */ # include -# include # if defined(O_CLOEXEC) # define UV__O_CLOEXEC O_CLOEXEC # endif @@ -61,7 +58,6 @@ #if defined(__FreeBSD__) || defined(__DragonFly__) # include # include -# include # include # define UV__O_CLOEXEC O_CLOEXEC # if defined(__FreeBSD__) && __FreeBSD__ >= 10 @@ -74,10 +70,6 @@ # endif #endif -#ifdef _AIX -#include -#endif - #if defined(__ANDROID_API__) && __ANDROID_API__ < 21 # include /* for dlsym */ #endif @@ -508,8 +500,8 @@ int uv__close_nocheckstdio(int fd) { rc = close(fd); if (rc == -1) { rc = -errno; - if (rc == -EINTR) - rc = -EINPROGRESS; /* For platform/libc consistency. */ + if (rc == -EINTR || rc == -EINPROGRESS) + rc = 0; /* The close is in progress, not an error. */ errno = saved_errno; } @@ -523,10 +515,7 @@ int uv__close(int fd) { } -#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \ - defined(_AIX) || defined(__DragonFly__) - -int uv__nonblock(int fd, int set) { +int uv__nonblock_ioctl(int fd, int set) { int r; do @@ -540,7 +529,7 @@ int uv__nonblock(int fd, int set) { } -int uv__cloexec(int fd, int set) { +int uv__cloexec_ioctl(int fd, int set) { int r; do @@ -553,10 +542,8 @@ int uv__cloexec(int fd, int set) { return 0; } -#else /* !(defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \ - defined(_AIX) || defined(__DragonFly__)) */ -int uv__nonblock(int fd, int set) { +int uv__nonblock_fcntl(int fd, int set) { int flags; int r; @@ -587,7 +574,7 @@ int uv__nonblock(int fd, int set) { } -int uv__cloexec(int fd, int set) { +int uv__cloexec_fcntl(int fd, int set) { int flags; int r; @@ -617,9 +604,6 @@ int uv__cloexec(int fd, int set) { return 0; } -#endif /* defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \ - defined(_AIX) || defined(__DragonFly__) */ - /* This function is not execve-safe, there is a race window * between the call to dup() and fcntl(FD_CLOEXEC). diff --git a/src/unix/freebsd.c b/src/unix/freebsd.c index adc95235..cba44a3e 100644 --- a/src/unix/freebsd.c +++ b/src/unix/freebsd.c @@ -196,14 +196,24 @@ int uv_set_process_title(const char* title) { int uv_get_process_title(char* buffer, size_t size) { + size_t len; + + if (buffer == NULL || size == 0) + return -EINVAL; + if (process_title) { - strncpy(buffer, process_title, size); + len = strlen(process_title) + 1; + + if (size < len) + return -ENOBUFS; + + memcpy(buffer, process_title, len); } else { - if (size > 0) { - buffer[0] = '\0'; - } + len = 0; } + buffer[len] = '\0'; + return 0; } diff --git a/src/unix/fs.c b/src/unix/fs.c index 085970a0..0b2505e4 100644 --- a/src/unix/fs.c +++ b/src/unix/fs.c @@ -151,9 +151,9 @@ static ssize_t uv__fs_futime(uv_fs_t* req) { goto skip; ts[0].tv_sec = req->atime; - ts[0].tv_nsec = (unsigned long)(req->atime * 1000000) % 1000000 * 1000; + ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000; ts[1].tv_sec = req->mtime; - ts[1].tv_nsec = (unsigned long)(req->mtime * 1000000) % 1000000 * 1000; + ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000; r = uv__utimesat(req->file, NULL, ts, 0); if (r == 0) @@ -167,9 +167,9 @@ static ssize_t uv__fs_futime(uv_fs_t* req) { skip: tv[0].tv_sec = req->atime; - tv[0].tv_usec = (unsigned long)(req->atime * 1000000) % 1000000; + tv[0].tv_usec = (uint64_t)(req->atime * 1000000) % 1000000; tv[1].tv_sec = req->mtime; - tv[1].tv_usec = (unsigned long)(req->mtime * 1000000) % 1000000; + tv[1].tv_usec = (uint64_t)(req->mtime * 1000000) % 1000000; snprintf(path, sizeof(path), "/proc/self/fd/%d", (int) req->file); r = utimes(path, tv); @@ -198,9 +198,9 @@ skip: || defined(__sun) struct timeval tv[2]; tv[0].tv_sec = req->atime; - tv[0].tv_usec = (unsigned long)(req->atime * 1000000) % 1000000; + tv[0].tv_usec = (uint64_t)(req->atime * 1000000) % 1000000; tv[1].tv_sec = req->mtime; - tv[1].tv_usec = (unsigned long)(req->mtime * 1000000) % 1000000; + tv[1].tv_usec = (uint64_t)(req->mtime * 1000000) % 1000000; # if defined(__sun) return futimesat(req->file, NULL, tv); # else @@ -209,9 +209,9 @@ skip: #elif defined(_AIX71) struct timespec ts[2]; ts[0].tv_sec = req->atime; - ts[0].tv_nsec = (unsigned long)(req->atime * 1000000) % 1000000 * 1000; + ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000; ts[1].tv_sec = req->mtime; - ts[1].tv_nsec = (unsigned long)(req->mtime * 1000000) % 1000000 * 1000; + ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000; return futimens(req->file, ts); #else errno = ENOSYS; @@ -251,7 +251,7 @@ static ssize_t uv__fs_open(uv_fs_t* req) { */ if (r >= 0 && uv__cloexec(r, 1) != 0) { r = uv__close(r); - if (r != 0 && r != -EINPROGRESS) + if (r != 0) abort(); r = -1; } @@ -810,8 +810,11 @@ static void uv__to_stat(struct stat* src, uv_stat_t* dst) { static int uv__fs_stat(const char *path, uv_stat_t *buf) { struct stat pbuf; int ret; + ret = stat(path, &pbuf); - uv__to_stat(&pbuf, buf); + if (ret == 0) + uv__to_stat(&pbuf, buf); + return ret; } @@ -819,8 +822,11 @@ static int uv__fs_stat(const char *path, uv_stat_t *buf) { static int uv__fs_lstat(const char *path, uv_stat_t *buf) { struct stat pbuf; int ret; + ret = lstat(path, &pbuf); - uv__to_stat(&pbuf, buf); + if (ret == 0) + uv__to_stat(&pbuf, buf); + return ret; } @@ -828,8 +834,11 @@ static int uv__fs_lstat(const char *path, uv_stat_t *buf) { static int uv__fs_fstat(int fd, uv_stat_t *buf) { struct stat pbuf; int ret; + ret = fstat(fd, &pbuf); - uv__to_stat(&pbuf, buf); + if (ret == 0) + uv__to_stat(&pbuf, buf); + return ret; } diff --git a/src/unix/internal.h b/src/unix/internal.h index 670b14bc..4cae7376 100644 --- a/src/unix/internal.h +++ b/src/unix/internal.h @@ -152,11 +152,25 @@ struct uv__stream_queued_fds_s { }; +#if defined(_AIX) || \ + defined(__APPLE__) || \ + defined(__DragonFly__) || \ + defined(__FreeBSD__) || \ + defined(__linux__) +#define uv__cloexec uv__cloexec_ioctl +#define uv__nonblock uv__nonblock_ioctl +#else +#define uv__cloexec uv__cloexec_fcntl +#define uv__nonblock uv__nonblock_fcntl +#endif + /* core */ -int uv__nonblock(int fd, int set); +int uv__cloexec_ioctl(int fd, int set); +int uv__cloexec_fcntl(int fd, int set); +int uv__nonblock_ioctl(int fd, int set); +int uv__nonblock_fcntl(int fd, int set); int uv__close(int fd); int uv__close_nocheckstdio(int fd); -int uv__cloexec(int fd, int set); int uv__socket(int domain, int type, int protocol); int uv__dup(int fd); ssize_t uv__recvmsg(int fd, struct msghdr *msg, int flags); diff --git a/src/unix/linux-core.c b/src/unix/linux-core.c index b48a1111..58dd813d 100644 --- a/src/unix/linux-core.c +++ b/src/unix/linux-core.c @@ -289,11 +289,13 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { if (nfds == 0) { assert(timeout != -1); - timeout = real_timeout - timeout; - if (timeout > 0) - continue; + if (timeout == 0) + return; - return; + /* We may have been inside the system call for longer than |timeout| + * milliseconds so we need to update the timestamp to avoid drift. + */ + goto update_timeout; } if (nfds == -1) { @@ -484,12 +486,20 @@ int uv_exepath(char* buffer, size_t* size) { uint64_t uv_get_free_memory(void) { - return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_AVPHYS_PAGES); + struct sysinfo info; + + if (sysinfo(&info) == 0) + return (uint64_t) info.freeram * info.mem_unit; + return 0; } uint64_t uv_get_total_memory(void) { - return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_PHYS_PAGES); + struct sysinfo info; + + if (sysinfo(&info) == 0) + return (uint64_t) info.totalram * info.mem_unit; + return 0; } diff --git a/src/unix/loop.c b/src/unix/loop.c index 92e96f09..bd63c2f9 100644 --- a/src/unix/loop.c +++ b/src/unix/loop.c @@ -28,11 +28,15 @@ #include int uv_loop_init(uv_loop_t* loop) { + void* saved_data; int err; uv__signal_global_once_init(); + saved_data = loop->data; memset(loop, 0, sizeof(*loop)); + loop->data = saved_data; + heap_init((struct heap*) &loop->timer_heap); QUEUE_INIT(&loop->wq); QUEUE_INIT(&loop->active_reqs); diff --git a/src/unix/netbsd.c b/src/unix/netbsd.c index ca48550f..4a9e6cbc 100644 --- a/src/unix/netbsd.c +++ b/src/unix/netbsd.c @@ -147,14 +147,24 @@ int uv_set_process_title(const char* title) { int uv_get_process_title(char* buffer, size_t size) { + size_t len; + + if (buffer == NULL || size == 0) + return -EINVAL; + if (process_title) { - strncpy(buffer, process_title, size); + len = strlen(process_title) + 1; + + if (size < len) + return -ENOBUFS; + + memcpy(buffer, process_title, len); } else { - if (size > 0) { - buffer[0] = '\0'; - } + len = 0; } + buffer[len] = '\0'; + return 0; } diff --git a/src/unix/openbsd.c b/src/unix/openbsd.c index 8c40bde4..909288cc 100644 --- a/src/unix/openbsd.c +++ b/src/unix/openbsd.c @@ -169,14 +169,24 @@ int uv_set_process_title(const char* title) { int uv_get_process_title(char* buffer, size_t size) { + size_t len; + + if (buffer == NULL || size == 0) + return -EINVAL; + if (process_title) { - strncpy(buffer, process_title, size); + len = strlen(process_title) + 1; + + if (size < len) + return -ENOBUFS; + + memcpy(buffer, process_title, len); } else { - if (size > 0) { - buffer[0] = '\0'; - } + len = 0; } + buffer[len] = '\0'; + return 0; } diff --git a/src/unix/poll.c b/src/unix/poll.c index 0d5944b0..4c0d478e 100644 --- a/src/unix/poll.c +++ b/src/unix/poll.c @@ -59,7 +59,14 @@ int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) { if (err) return err; + /* If ioctl(FIONBIO) reports ENOTTY, try fcntl(F_GETFL) + fcntl(F_SETFL). + * Workaround for e.g. kqueue fds not supporting ioctls. + */ err = uv__nonblock(fd, 1); + if (err == -ENOTTY) + if (uv__nonblock == uv__nonblock_ioctl) + err = uv__nonblock_fcntl(fd, 1); + if (err) return err; diff --git a/src/unix/process.c b/src/unix/process.c index ef10a342..8a010edc 100644 --- a/src/unix/process.c +++ b/src/unix/process.c @@ -232,7 +232,7 @@ static int uv__process_open_stream(uv_stdio_container_t* container, return 0; err = uv__close(pipefds[1]); - if (err != 0 && err != -EINPROGRESS) + if (err != 0) abort(); pipefds[1] = -1; diff --git a/src/unix/proctitle.c b/src/unix/proctitle.c index 19214e5e..08d875f7 100644 --- a/src/unix/proctitle.c +++ b/src/unix/proctitle.c @@ -87,10 +87,13 @@ int uv_set_process_title(const char* title) { int uv_get_process_title(char* buffer, size_t size) { - if (process_title.len > 0) - strncpy(buffer, process_title.str, size); - else if (size > 0) - buffer[0] = '\0'; + if (buffer == NULL || size == 0) + return -EINVAL; + else if (size <= process_title.len) + return -ENOBUFS; + + memcpy(buffer, process_title.str, process_title.len + 1); + buffer[process_title.len] = '\0'; return 0; } diff --git a/src/unix/stream.c b/src/unix/stream.c index 7dbc556f..2143cd88 100644 --- a/src/unix/stream.c +++ b/src/unix/stream.c @@ -571,7 +571,6 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { int uv_accept(uv_stream_t* server, uv_stream_t* client) { int err; - /* TODO document this */ assert(server->loop == client->loop); if (server->accepted_fd == -1) @@ -962,8 +961,8 @@ uv_handle_type uv__handle_type(int fd) { return UV_UNKNOWN_HANDLE; if (type == SOCK_STREAM) { -#if defined(_AIX) - /* on AIX the getsockname call returns an empty sa structure +#if defined(_AIX) || defined(__DragonFly__) + /* on AIX/DragonFly the getsockname call returns an empty sa structure * for sockets of type AF_UNIX. For all other types it will * return a properly filled in structure. */ diff --git a/src/unix/sunos.c b/src/unix/sunos.c index e67be8fc..3e7a7592 100644 --- a/src/unix/sunos.c +++ b/src/unix/sunos.c @@ -33,6 +33,8 @@ #endif #include #include +#include +#include #include #include @@ -540,9 +542,10 @@ int uv_set_process_title(const char* title) { int uv_get_process_title(char* buffer, size_t size) { - if (size > 0) { - buffer[0] = '\0'; - } + if (buffer == NULL || size == 0) + return -EINVAL; + + buffer[0] = '\0'; return 0; } @@ -692,13 +695,57 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { uv__free(cpu_infos); } +/* + * Inspired By: + * https://blogs.oracle.com/paulie/entry/retrieving_mac_address_in_solaris + * http://www.pauliesworld.org/project/getmac.c + */ +static int uv__set_phys_addr(uv_interface_address_t* address, + struct ifaddrs* ent) { + + struct sockaddr_dl* sa_addr; + int sockfd; + int i; + struct arpreq arpreq; + + /* This appears to only work as root */ + sa_addr = (struct sockaddr_dl*)(ent->ifa_addr); + memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); + for (i = 0; i < sizeof(address->phys_addr); i++) { + if (address->phys_addr[i] != 0) + return 0; + } + memset(&arpreq, 0, sizeof(arpreq)); + if (address->address.address4.sin_family == AF_INET) { + struct sockaddr_in* sin = ((struct sockaddr_in*)&arpreq.arp_pa); + sin->sin_addr.s_addr = address->address.address4.sin_addr.s_addr; + } else if (address->address.address4.sin_family == AF_INET6) { + struct sockaddr_in6* sin = ((struct sockaddr_in6*)&arpreq.arp_pa); + memcpy(sin->sin6_addr.s6_addr, + address->address.address6.sin6_addr.s6_addr, + sizeof(address->address.address6.sin6_addr.s6_addr)); + } else { + return 0; + } + + sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sockfd < 0) + return -errno; + + if (ioctl(sockfd, SIOCGARP, (char*)&arpreq) == -1) { + uv__close(sockfd); + return -errno; + } + memcpy(address->phys_addr, arpreq.arp_ha.sa_data, sizeof(address->phys_addr)); + uv__close(sockfd); + return 0; +} int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { #ifdef SUNOS_NO_IFADDRS return -ENOSYS; #else uv_interface_address_t* address; - struct sockaddr_dl* sa_addr; struct ifaddrs* addrs; struct ifaddrs* ent; int i; @@ -751,28 +798,10 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { address->is_internal = !!((ent->ifa_flags & IFF_PRIVATE) || (ent->ifa_flags & IFF_LOOPBACK)); + uv__set_phys_addr(address, ent); address++; } - /* Fill in physical addresses for each interface */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family != AF_LINK)) { - continue; - } - - address = *addresses; - - for (i = 0; i < (*count); i++) { - if (strcmp(address->name, ent->ifa_name) == 0) { - sa_addr = (struct sockaddr_dl*)(ent->ifa_addr); - memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); - } - address++; - } - } - freeifaddrs(addrs); return 0; diff --git a/src/unix/tcp.c b/src/unix/tcp.c index 793e4c7d..46d8cd25 100644 --- a/src/unix/tcp.c +++ b/src/unix/tcp.c @@ -158,11 +158,17 @@ int uv__tcp_connect(uv_connect_t* req, handle->delayed_error = 0; - do + do { + errno = 0; r = connect(uv__stream_fd(handle), addr, addrlen); - while (r == -1 && errno == EINTR); + } while (r == -1 && errno == EINTR); - if (r == -1) { + /* We not only check the return value, but also check the errno != 0. + * Because in rare cases connect() will return -1 but the errno + * is 0 (for example, on Android 4.3, OnePlus phone A0001_12_150227) + * and actually the tcp three-way handshake is completed. + */ + if (r == -1 && errno != 0) { if (errno == EINPROGRESS) ; /* not an error */ else if (errno == ECONNREFUSED) diff --git a/src/unix/tty.c b/src/unix/tty.c index 32fa37ea..a56afe18 100644 --- a/src/unix/tty.c +++ b/src/unix/tty.c @@ -57,6 +57,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { int flags; int newfd; int r; + int saved_flags; char path[256]; /* File descriptors that refer to files cannot be monitored with epoll. @@ -113,6 +114,22 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { fd = newfd; } +#if defined(__APPLE__) + /* Save the fd flags in case we need to restore them due to an error. */ + do + saved_flags = fcntl(fd, F_GETFL); + while (saved_flags == -1 && errno == EINTR); + + if (saved_flags == -1) { + if (newfd != -1) + uv__close(newfd); + return -errno; + } +#endif + + /* Pacify the compiler. */ + (void) &saved_flags; + skip: uv__stream_init(loop, (uv_stream_t*) tty, UV_TTY); @@ -120,13 +137,20 @@ skip: * the handle queue, since it was added by uv__handle_init in uv_stream_init. */ + if (!(flags & UV_STREAM_BLOCKING)) + uv__nonblock(fd, 1); + #if defined(__APPLE__) r = uv__stream_try_select((uv_stream_t*) tty, &fd); if (r) { + int rc = r; if (newfd != -1) uv__close(newfd); QUEUE_REMOVE(&tty->handle_queue); - return r; + do + r = fcntl(fd, F_SETFL, saved_flags); + while (r == -1 && errno == EINTR); + return rc; } #endif @@ -135,9 +159,6 @@ skip: else flags |= UV_STREAM_WRITABLE; - if (!(flags & UV_STREAM_BLOCKING)) - uv__nonblock(fd, 1); - uv__stream_open((uv_stream_t*) tty, fd, flags); tty->mode = UV_TTY_MODE_NORMAL; @@ -268,14 +289,14 @@ uv_handle_type uv_guess_handle(uv_file file) { return UV_UDP; if (type == SOCK_STREAM) { -#if defined(_AIX) - /* on AIX the getsockname call returns an empty sa structure +#if defined(_AIX) || defined(__DragonFly__) + /* on AIX/DragonFly the getsockname call returns an empty sa structure * for sockets of type AF_UNIX. For all other types it will * return a properly filled in structure. */ if (len == 0) return UV_NAMED_PIPE; -#endif /* defined(_AIX) */ +#endif /* defined(_AIX) || defined(__DragonFly__) */ if (sa.sa_family == AF_INET || sa.sa_family == AF_INET6) return UV_TCP; diff --git a/src/uv-common.c b/src/uv-common.c index ba264469..434a5029 100644 --- a/src/uv-common.c +++ b/src/uv-common.c @@ -613,6 +613,7 @@ uv_loop_t* uv_loop_new(void) { int uv_loop_close(uv_loop_t* loop) { QUEUE* q; uv_handle_t* h; + void* saved_data; if (!QUEUE_EMPTY(&(loop)->active_reqs)) return UV_EBUSY; @@ -626,7 +627,9 @@ int uv_loop_close(uv_loop_t* loop) { uv__loop_close(loop); #ifndef NDEBUG + saved_data = loop->data; memset(loop, -1, sizeof(*loop)); + loop->data = saved_data; #endif if (loop == default_loop_ptr) default_loop_ptr = NULL; diff --git a/src/win/fs-event.c b/src/win/fs-event.c index e79a48d0..f96a7bfd 100644 --- a/src/win/fs-event.c +++ b/src/win/fs-event.c @@ -344,6 +344,22 @@ int uv_fs_event_stop(uv_fs_event_t* handle) { } +static int file_info_cmp(WCHAR* str, WCHAR* file_name, int file_name_len) { + int str_len; + + str_len = wcslen(str); + + /* + Since we only care about equality, return early if the strings + aren't the same length + */ + if (str_len != (file_name_len / sizeof(WCHAR))) + return -1; + + return _wcsnicmp(str, file_name, str_len); +} + + void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, uv_fs_event_t* handle) { FILE_NOTIFY_INFORMATION* file_info; @@ -383,10 +399,12 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, * or if the filename filter matches. */ if (handle->dirw || - _wcsnicmp(handle->filew, file_info->FileName, - file_info->FileNameLength / sizeof(WCHAR)) == 0 || - _wcsnicmp(handle->short_filew, file_info->FileName, - file_info->FileNameLength / sizeof(WCHAR)) == 0) { + file_info_cmp(handle->filew, + file_info->FileName, + file_info->FileNameLength) == 0 || + file_info_cmp(handle->short_filew, + file_info->FileName, + file_info->FileNameLength) == 0) { if (handle->dirw) { /* diff --git a/src/win/fs.c b/src/win/fs.c index 54dfea72..b6d43921 100644 --- a/src/win/fs.c +++ b/src/win/fs.c @@ -94,7 +94,7 @@ #define TIME_T_TO_FILETIME(time, filetime_ptr) \ do { \ - uint64_t bigtime = ((int64_t) (time) * 10000000LL) + \ + uint64_t bigtime = ((uint64_t) ((time) * 10000000ULL)) + \ 116444736000000000ULL; \ (filetime_ptr)->dwLowDateTime = bigtime & 0xFFFFFFFF; \ (filetime_ptr)->dwHighDateTime = bigtime >> 32; \ @@ -204,14 +204,11 @@ INLINE static int fs__capture_path(uv_fs_t* req, const char* path, req->fs.info.new_pathw = NULL; } - if (!copy_path) { - req->path = path; - } else if (path) { + req->path = path; + if (path != NULL && copy_path) { memcpy(pos, path, path_len); assert(path_len == buf_sz - (pos - buf)); req->path = pos; - } else { - req->path = NULL; } req->flags |= UV_FS_FREE_PATHS; @@ -1429,8 +1426,8 @@ static void fs__fchmod(uv_fs_t* req) { INLINE static int fs__utime_handle(HANDLE handle, double atime, double mtime) { FILETIME filetime_a, filetime_m; - TIME_T_TO_FILETIME((time_t) atime, &filetime_a); - TIME_T_TO_FILETIME((time_t) mtime, &filetime_m); + TIME_T_TO_FILETIME(atime, &filetime_a); + TIME_T_TO_FILETIME(mtime, &filetime_m); if (!SetFileTime(handle, NULL, &filetime_a, &filetime_m)) { return -1; diff --git a/src/win/pipe.c b/src/win/pipe.c index a784325c..2a949e79 100644 --- a/src/win/pipe.c +++ b/src/win/pipe.c @@ -85,7 +85,7 @@ static void eof_timer_close_cb(uv_handle_t* handle); static void uv_unique_pipe_name(char* ptr, char* name, size_t size) { - snprintf(name, size, "\\\\?\\pipe\\uv\\%p-%u", ptr, GetCurrentProcessId()); + snprintf(name, size, "\\\\?\\pipe\\uv\\%p-%lu", ptr, GetCurrentProcessId()); } diff --git a/src/win/tty.c b/src/win/tty.c index 9b963778..daa303f1 100644 --- a/src/win/tty.c +++ b/src/win/tty.c @@ -40,6 +40,9 @@ #include "stream-inl.h" #include "req-inl.h" +#ifndef InterlockedOr +# define InterlockedOr _InterlockedOr +#endif #define UNICODE_REPLACEMENT_CHARACTER (0xfffd) @@ -294,6 +297,8 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) { break; case UV_TTY_MODE_IO: return UV_ENOTSUP; + default: + return UV_EINVAL; } if (!SetConsoleMode(tty->handle, flags)) { diff --git a/src/win/util.c b/src/win/util.c index 4cebad39..84a0e467 100644 --- a/src/win/util.c +++ b/src/win/util.c @@ -416,6 +416,11 @@ static int uv__get_process_title() { int uv_get_process_title(char* buffer, size_t size) { + size_t len; + + if (buffer == NULL || size == 0) + return UV_EINVAL; + uv__once_init(); EnterCriticalSection(&process_title_lock); @@ -429,7 +434,14 @@ int uv_get_process_title(char* buffer, size_t size) { } assert(process_title); - strncpy(buffer, process_title, size); + len = strlen(process_title) + 1; + + if (size < len) { + LeaveCriticalSection(&process_title_lock); + return UV_ENOBUFS; + } + + memcpy(buffer, process_title, len); LeaveCriticalSection(&process_title_lock); return 0; diff --git a/test/runner-unix.c b/test/runner-unix.c index 2405fa87..0edd671b 100644 --- a/test/runner-unix.c +++ b/test/runner-unix.c @@ -43,11 +43,6 @@ /* Do platform-specific initialization. */ int platform_init(int argc, char **argv) { - const char* tap; - - tap = getenv("UV_TAP_OUTPUT"); - tap_output = (tap != NULL && atoi(tap) > 0); - /* Disable stdio output buffering. */ setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); @@ -294,8 +289,7 @@ long int process_output_size(process_info_t *p) { /* Copy the contents of the stdio output buffer to `fd`. */ -int process_copy_output(process_info_t *p, int fd) { - ssize_t nwritten; +int process_copy_output(process_info_t* p, FILE* stream) { char buf[1024]; int r; @@ -306,20 +300,8 @@ int process_copy_output(process_info_t *p, int fd) { } /* TODO: what if the line is longer than buf */ - while (fgets(buf, sizeof(buf), p->stdout_file) != NULL) { - /* TODO: what if write doesn't write the whole buffer... */ - nwritten = 0; - - if (tap_output) - nwritten += write(fd, "#", 1); - - nwritten += write(fd, buf, strlen(buf)); - - if (nwritten < 0) { - perror("write"); - return -1; - } - } + while (fgets(buf, sizeof(buf), p->stdout_file) != NULL) + print_lines(buf, strlen(buf), stream); if (ferror(p->stdout_file)) { perror("read"); diff --git a/test/runner-win.c b/test/runner-win.c index 97ef7599..1b4a569a 100644 --- a/test/runner-win.c +++ b/test/runner-win.c @@ -44,11 +44,6 @@ /* Do platform-specific initialization. */ int platform_init(int argc, char **argv) { - const char* tap; - - tap = getenv("UV_TAP_OUTPUT"); - tap_output = (tap != NULL && atoi(tap) > 0); - /* Disable the "application crashed" popup. */ SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); @@ -213,10 +208,9 @@ long int process_output_size(process_info_t *p) { } -int process_copy_output(process_info_t *p, int fd) { +int process_copy_output(process_info_t* p, FILE* stream) { DWORD read; char buf[1024]; - char *line, *start; if (SetFilePointer(p->stdio_out, 0, @@ -225,29 +219,8 @@ int process_copy_output(process_info_t *p, int fd) { return -1; } - if (tap_output) - write(fd, "#", 1); - - while (ReadFile(p->stdio_out, (void*)&buf, sizeof(buf), &read, NULL) && - read > 0) { - if (tap_output) { - start = buf; - - while ((line = strchr(start, '\n')) != NULL) { - write(fd, start, line - start + 1); - write(fd, "#", 1); - start = line + 1; - } - - if (start < buf + read) - write(fd, start, buf + read - start); - } else { - write(fd, buf, read); - } - } - - if (tap_output) - write(fd, "\n", 1); + while (ReadFile(p->stdio_out, &buf, sizeof(buf), &read, NULL) && read > 0) + print_lines(buf, read, stream); if (GetLastError() != ERROR_HANDLE_EOF) return -1; diff --git a/test/runner.c b/test/runner.c index c616d176..5e22c18f 100644 --- a/test/runner.c +++ b/test/runner.c @@ -28,31 +28,6 @@ char executable_path[sizeof(executable_path)]; -int tap_output = 0; - - -static void log_progress(int total, - int passed, - int failed, - int todos, - int skipped, - const char* name) { - int progress; - - if (total == 0) - total = 1; - - progress = 100 * (passed + failed + skipped + todos) / total; - fprintf(stderr, "[%% %3d|+ %3d|- %3d|T %3d|S %3d]: %s", - progress, - passed, - failed, - todos, - skipped, - name); - fflush(stderr); -} - const char* fmt(double d) { static char buf[1024]; @@ -95,7 +70,6 @@ int run_tests(int benchmark_output) { int total; int passed; int failed; - int todos; int skipped; int current; int test_result; @@ -109,15 +83,12 @@ int run_tests(int benchmark_output) { } } - if (tap_output) { - fprintf(stderr, "1..%d\n", total); - fflush(stderr); - } + fprintf(stderr, "1..%d\n", total); + fflush(stderr); /* Run all tests. */ passed = 0; failed = 0; - todos = 0; skipped = 0; current = 1; for (task = TASKS; task->main; task++) { @@ -125,30 +96,15 @@ int run_tests(int benchmark_output) { continue; } - if (!tap_output) - rewind_cursor(); - - if (!benchmark_output && !tap_output) { - log_progress(total, passed, failed, todos, skipped, task->task_name); - } - test_result = run_test(task->task_name, benchmark_output, current); switch (test_result) { case TEST_OK: passed++; break; - case TEST_TODO: todos++; break; case TEST_SKIP: skipped++; break; default: failed++; } current++; } - if (!tap_output) - rewind_cursor(); - - if (!benchmark_output && !tap_output) { - log_progress(total, passed, failed, todos, skipped, "Done.\n"); - } - return failed; } @@ -166,10 +122,6 @@ void log_tap_result(int test_count, result = "ok"; directive = ""; break; - case TEST_TODO: - result = "not ok"; - directive = " # TODO "; - break; case TEST_SKIP: result = "ok"; directive = " # SKIP "; @@ -179,8 +131,7 @@ void log_tap_result(int test_count, directive = ""; } - if ((status == TEST_SKIP || status == TEST_TODO) && - process_output_size(process) > 0) { + if (status == TEST_SKIP && process_output_size(process) > 0) { process_read_last_line(process, reason, sizeof reason); } else { reason[0] = '\0'; @@ -319,22 +270,11 @@ out: FATAL("process_wait failed"); } - if (tap_output) - log_tap_result(test_count, test, status, &processes[i]); + log_tap_result(test_count, test, status, &processes[i]); /* Show error and output from processes if the test failed. */ - if (status != 0 || task->show_output) { - if (tap_output) { - fprintf(stderr, "#"); - } else if (status == TEST_TODO) { - fprintf(stderr, "\n`%s` todo\n", test); - } else if (status == TEST_SKIP) { - fprintf(stderr, "\n`%s` skipped\n", test); - } else if (status != 0) { - fprintf(stderr, "\n`%s` failed: %s\n", test, errmsg); - } else { - fprintf(stderr, "\n"); - } + if ((status != TEST_OK && status != TEST_SKIP) || task->show_output) { + fprintf(stderr, "# "); fflush(stderr); for (i = 0; i < process_count; i++) { @@ -354,15 +294,11 @@ out: default: fprintf(stderr, "Output from process `%s`:\n", process_get_name(&processes[i])); fflush(stderr); - process_copy_output(&processes[i], fileno(stderr)); + process_copy_output(&processes[i], stderr); break; } } - if (!tap_output) { - fprintf(stderr, "=============================================================\n"); - } - /* In benchmark mode show concise output from the main process. */ } else if (benchmark_output) { switch (process_output_size(main_proc)) { @@ -378,7 +314,7 @@ out: default: for (i = 0; i < process_count; i++) { - process_copy_output(&processes[i], fileno(stderr)); + process_copy_output(&processes[i], stderr); } break; } @@ -464,3 +400,21 @@ void print_tests(FILE* stream) { } } } + + +void print_lines(const char* buffer, size_t size, FILE* stream) { + const char* start; + const char* end; + + start = buffer; + while ((end = memchr(start, '\n', &buffer[size] - start))) { + fprintf(stream, "# %.*s\n", (int) (end - start), start); + fflush(stream); + start = end + 1; + } + + if (start < &buffer[size]) { + fprintf(stream, "# %s\n", start); + fflush(stream); + } +} diff --git a/test/runner.h b/test/runner.h index 78f3c880..555f2f8e 100644 --- a/test/runner.h +++ b/test/runner.h @@ -126,6 +126,8 @@ int run_test_part(const char* test, const char* part); */ void print_tests(FILE* stream); +/* Print lines in |buffer| as TAP diagnostics to |stream|. */ +void print_lines(const char* buffer, size_t size, FILE* stream); /* * Stuff that should be implemented by test-runner-.h @@ -148,8 +150,8 @@ int process_wait(process_info_t *vec, int n, int timeout); /* Returns the number of bytes in the stdio output buffer for process `p`. */ long int process_output_size(process_info_t *p); -/* Copy the contents of the stdio output buffer to `fd`. */ -int process_copy_output(process_info_t *p, int fd); +/* Copy the contents of the stdio output buffer to `stream`. */ +int process_copy_output(process_info_t* p, FILE* stream); /* Copy the last line of the stdio output buffer to `buffer` */ int process_read_last_line(process_info_t *p, @@ -172,7 +174,4 @@ void process_cleanup(process_info_t *p); /* Move the console cursor one line up and back to the first column. */ void rewind_cursor(void); -/* trigger output as tap */ -extern int tap_output; - #endif /* RUNNER_H_ */ diff --git a/test/task.h b/test/task.h index 96cc6377..65a1132e 100644 --- a/test/task.h +++ b/test/task.h @@ -136,7 +136,6 @@ const char* fmt(double d); /* Reserved test exit codes. */ enum test_status { TEST_OK = 0, - TEST_TODO, TEST_SKIP }; @@ -145,13 +144,6 @@ enum test_status { return TEST_OK; \ } while (0) -#define RETURN_TODO(explanation) \ - do { \ - fprintf(stderr, "%s\n", explanation); \ - fflush(stderr); \ - return TEST_TODO; \ - } while (0) - #define RETURN_SKIP(explanation) \ do { \ fprintf(stderr, "%s\n", explanation); \ diff --git a/test/test-fs-event.c b/test/test-fs-event.c index 353c43b0..25eef07b 100644 --- a/test/test-fs-event.c +++ b/test/test-fs-event.c @@ -53,6 +53,14 @@ static char fs_event_filename[PATH_MAX]; static char fs_event_filename[1024]; #endif /* defined(PATH_MAX) */ static int timer_cb_touch_called; +static int timer_cb_exact_called; + +static void fs_event_fail(uv_fs_event_t* handle, + const char* filename, + int events, + int status) { + ASSERT(0 && "should never be called"); +} static void create_dir(const char* name) { int r; @@ -345,6 +353,21 @@ static void timer_cb_touch(uv_timer_t* timer) { timer_cb_touch_called++; } +static void timer_cb_exact(uv_timer_t* handle) { + int r; + + if (timer_cb_exact_called == 0) { + touch_file("watch_dir/file.js"); + } else { + uv_close((uv_handle_t*)handle, NULL); + r = uv_fs_event_stop(&fs_event); + ASSERT(r == 0); + uv_close((uv_handle_t*) &fs_event, NULL); + } + + ++timer_cb_exact_called; +} + static void timer_cb_watch_twice(uv_timer_t* handle) { uv_fs_event_t* handles = handle->data; uv_close((uv_handle_t*) (handles + 0), NULL); @@ -467,6 +490,45 @@ TEST_IMPL(fs_event_watch_file) { return 0; } +TEST_IMPL(fs_event_watch_file_exact_path) { + /* + This test watches a file named "file.jsx" and modifies a file named + "file.js". The test verifies that no events occur for file.jsx. + */ + uv_loop_t* loop; + int r; + + loop = uv_default_loop(); + + /* Setup */ + remove("watch_dir/file.js"); + remove("watch_dir/file.jsx"); + remove("watch_dir/"); + create_dir("watch_dir"); + create_file("watch_dir/file.js"); + create_file("watch_dir/file.jsx"); + + r = uv_fs_event_init(loop, &fs_event); + ASSERT(r == 0); + r = uv_fs_event_start(&fs_event, fs_event_fail, "watch_dir/file.jsx", 0); + ASSERT(r == 0); + r = uv_timer_init(loop, &timer); + ASSERT(r == 0); + r = uv_timer_start(&timer, timer_cb_exact, 100, 100); + ASSERT(r == 0); + r = uv_run(loop, UV_RUN_DEFAULT); + ASSERT(r == 0); + ASSERT(timer_cb_exact_called == 2); + + /* Cleanup */ + remove("watch_dir/file.js"); + remove("watch_dir/file.jsx"); + remove("watch_dir/"); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + TEST_IMPL(fs_event_watch_file_twice) { const char path[] = "test/fixtures/empty_file"; uv_fs_event_t watchers[2]; @@ -626,12 +688,6 @@ TEST_IMPL(fs_event_no_callback_on_close) { } -static void fs_event_fail(uv_fs_event_t* handle, const char* filename, - int events, int status) { - ASSERT(0 && "should never be called"); -} - - static void timer_cb(uv_timer_t* handle) { int r; diff --git a/test/test-fs.c b/test/test-fs.c index 1cc1a7c0..250d1350 100644 --- a/test/test-fs.c +++ b/test/test-fs.c @@ -662,8 +662,8 @@ static void check_utime(const char* path, double atime, double mtime) { ASSERT(req.result == 0); s = &req.statbuf; - ASSERT(s->st_atim.tv_sec == atime); - ASSERT(s->st_mtim.tv_sec == mtime); + ASSERT(s->st_atim.tv_sec + (s->st_atim.tv_nsec / 1000000000.0) == atime); + ASSERT(s->st_mtim.tv_sec + (s->st_mtim.tv_nsec / 1000000000.0) == mtime); uv_fs_req_cleanup(&req); } @@ -1968,6 +1968,15 @@ TEST_IMPL(fs_utime) { atime = mtime = 400497753; /* 1982-09-10 11:22:33 */ + /* + * Test sub-second timestamps only on Windows (assuming NTFS). Some other + * platforms support sub-second timestamps, but that support is filesystem- + * dependent. Notably OS X (HFS Plus) does NOT support sub-second timestamps. + */ +#ifdef _WIN32 + mtime += 0.444; /* 1982-09-10 11:22:33.444 */ +#endif + r = uv_fs_utime(NULL, &req, path, atime, mtime, NULL); ASSERT(r == 0); ASSERT(req.result == 0); @@ -2055,6 +2064,15 @@ TEST_IMPL(fs_futime) { atime = mtime = 400497753; /* 1982-09-10 11:22:33 */ + /* + * Test sub-second timestamps only on Windows (assuming NTFS). Some other + * platforms support sub-second timestamps, but that support is filesystem- + * dependent. Notably OS X (HFS Plus) does NOT support sub-second timestamps. + */ +#ifdef _WIN32 + mtime += 0.444; /* 1982-09-10 11:22:33.444 */ +#endif + r = uv_fs_open(NULL, &req, path, O_RDWR, 0, NULL); ASSERT(r >= 0); ASSERT(req.result >= 0); diff --git a/test/test-ipc-send-recv.c b/test/test-ipc-send-recv.c index c445483f..133ae901 100644 --- a/test/test-ipc-send-recv.c +++ b/test/test-ipc-send-recv.c @@ -68,8 +68,8 @@ static struct echo_ctx ctx2; /* Used in write2_cb to decide if we need to cleanup or not */ static int is_child_process; static int is_in_process; -static int read_cb_called; -static int recv_cb_called; +static int read_cb_count; +static int recv_cb_count; static int write2_cb_called; @@ -91,43 +91,46 @@ static void recv_cb(uv_stream_t* handle, int r; union handles* recv; - if (++recv_cb_called == 1) { - recv = &ctx.recv; - } else { - recv = &ctx.recv2; - } - pipe = (uv_pipe_t*) handle; ASSERT(pipe == &ctx.channel); - /* Depending on the OS, the final recv_cb can be called after the child - * process has terminated which can result in nread being UV_EOF instead of - * the number of bytes read. Since the other end of the pipe has closed this - * UV_EOF is an acceptable value. */ - if (nread == UV_EOF) { - /* UV_EOF is only acceptable for the final recv_cb call */ - ASSERT(recv_cb_called == 2); - } else { - ASSERT(nread >= 0); - ASSERT(1 == uv_pipe_pending_count(pipe)); + do { + if (++recv_cb_count == 1) { + recv = &ctx.recv; + } else { + recv = &ctx.recv2; + } - pending = uv_pipe_pending_type(pipe); - ASSERT(pending == ctx.expected_type); + /* Depending on the OS, the final recv_cb can be called after + * the child process has terminated which can result in nread + * being UV_EOF instead of the number of bytes read. Since + * the other end of the pipe has closed this UV_EOF is an + * acceptable value. */ + if (nread == UV_EOF) { + /* UV_EOF is only acceptable for the final recv_cb call */ + ASSERT(recv_cb_count == 2); + } else { + ASSERT(nread >= 0); + ASSERT(uv_pipe_pending_count(pipe) > 0); - if (pending == UV_NAMED_PIPE) - r = uv_pipe_init(ctx.channel.loop, &recv->pipe, 0); - else if (pending == UV_TCP) - r = uv_tcp_init(ctx.channel.loop, &recv->tcp); - else - abort(); - ASSERT(r == 0); + pending = uv_pipe_pending_type(pipe); + ASSERT(pending == ctx.expected_type); - r = uv_accept(handle, &recv->stream); - ASSERT(r == 0); - } + if (pending == UV_NAMED_PIPE) + r = uv_pipe_init(ctx.channel.loop, &recv->pipe, 0); + else if (pending == UV_TCP) + r = uv_tcp_init(ctx.channel.loop, &recv->tcp); + else + abort(); + ASSERT(r == 0); + + r = uv_accept(handle, &recv->stream); + ASSERT(r == 0); + } + } while (uv_pipe_pending_count(pipe) > 0); /* Close after two writes received */ - if (recv_cb_called == 2) { + if (recv_cb_count == 2) { uv_close((uv_handle_t*)&ctx.channel, NULL); } } @@ -186,7 +189,7 @@ static int run_test(int inprocess) { r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); ASSERT(r == 0); - ASSERT(recv_cb_called == 2); + ASSERT(recv_cb_count == 2); if (inprocess) { r = uv_thread_join(&tid); @@ -293,41 +296,43 @@ static void read_cb(uv_stream_t* handle, return; } - if (++read_cb_called == 2) { - recv = &ctx2.recv; - write_req = &ctx2.write_req; - } else { - recv = &ctx2.recv2; - write_req = &ctx2.write_req2; - } - pipe = (uv_pipe_t*) handle; - ASSERT(pipe == &ctx2.channel); - ASSERT(nread >= 0); - ASSERT(1 == uv_pipe_pending_count(pipe)); + do { + if (++read_cb_count == 2) { + recv = &ctx2.recv; + write_req = &ctx2.write_req; + } else { + recv = &ctx2.recv2; + write_req = &ctx2.write_req2; + } - pending = uv_pipe_pending_type(pipe); - ASSERT(pending == UV_NAMED_PIPE || pending == UV_TCP); + ASSERT(pipe == &ctx2.channel); + ASSERT(nread >= 0); + ASSERT(uv_pipe_pending_count(pipe) > 0); - if (pending == UV_NAMED_PIPE) - r = uv_pipe_init(ctx2.channel.loop, &recv->pipe, 0); - else if (pending == UV_TCP) - r = uv_tcp_init(ctx2.channel.loop, &recv->tcp); - else - abort(); - ASSERT(r == 0); + pending = uv_pipe_pending_type(pipe); + ASSERT(pending == UV_NAMED_PIPE || pending == UV_TCP); - r = uv_accept(handle, &recv->stream); - ASSERT(r == 0); + if (pending == UV_NAMED_PIPE) + r = uv_pipe_init(ctx2.channel.loop, &recv->pipe, 0); + else if (pending == UV_TCP) + r = uv_tcp_init(ctx2.channel.loop, &recv->tcp); + else + abort(); + ASSERT(r == 0); - wrbuf = uv_buf_init(".", 1); - r = uv_write2(write_req, - (uv_stream_t*)&ctx2.channel, - &wrbuf, - 1, - &recv->stream, - write2_cb); - ASSERT(r == 0); + r = uv_accept(handle, &recv->stream); + ASSERT(r == 0); + + wrbuf = uv_buf_init(".", 1); + r = uv_write2(write_req, + (uv_stream_t*)&ctx2.channel, + &wrbuf, + 1, + &recv->stream, + write2_cb); + ASSERT(r == 0); + } while (uv_pipe_pending_count(pipe) > 0); } static void send_recv_start() { diff --git a/test/test-list.h b/test/test-list.h index c93f0819..41ed64c6 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -19,6 +19,8 @@ * IN THE SOFTWARE. */ +#include "uv.h" + TEST_DECLARE (platform_output) TEST_DECLARE (callback_order) TEST_DECLARE (close_order) @@ -273,6 +275,7 @@ TEST_DECLARE (fs_read_file_eof) TEST_DECLARE (fs_event_watch_dir) TEST_DECLARE (fs_event_watch_dir_recursive) TEST_DECLARE (fs_event_watch_file) +TEST_DECLARE (fs_event_watch_file_exact_path) TEST_DECLARE (fs_event_watch_file_twice) TEST_DECLARE (fs_event_watch_file_current_dir) #ifdef _WIN32 @@ -314,13 +317,19 @@ TEST_DECLARE (poll_duplex) TEST_DECLARE (poll_unidirectional) TEST_DECLARE (poll_close) TEST_DECLARE (poll_bad_fdtype) +#ifdef __linux__ +TEST_DECLARE (poll_nested_epoll) +#endif +#ifdef UV_HAVE_KQUEUE +TEST_DECLARE (poll_nested_kqueue) +#endif TEST_DECLARE (ip4_addr) TEST_DECLARE (ip6_addr_link_local) -#ifdef _WIN32 TEST_DECLARE (poll_close_doesnt_corrupt_stack) TEST_DECLARE (poll_closesocket) +#ifdef _WIN32 TEST_DECLARE (spawn_detect_pipe_name_collisions_on_windows) #if !defined(USING_UV_SHARED) TEST_DECLARE (argument_escaping) @@ -624,6 +633,12 @@ TASK_LIST_START TEST_ENTRY (poll_unidirectional) TEST_ENTRY (poll_close) TEST_ENTRY (poll_bad_fdtype) +#ifdef __linux__ + TEST_ENTRY (poll_nested_epoll) +#endif +#ifdef UV_HAVE_KQUEUE + TEST_ENTRY (poll_nested_kqueue) +#endif TEST_ENTRY (socket_buffer_size) @@ -655,9 +670,9 @@ TASK_LIST_START TEST_ENTRY (fs_poll_getpath) TEST_ENTRY (kill) -#ifdef _WIN32 TEST_ENTRY (poll_close_doesnt_corrupt_stack) TEST_ENTRY (poll_closesocket) +#ifdef _WIN32 TEST_ENTRY (spawn_detect_pipe_name_collisions_on_windows) #if !defined(USING_UV_SHARED) TEST_ENTRY (argument_escaping) @@ -710,6 +725,7 @@ TASK_LIST_START TEST_ENTRY (fs_event_watch_dir) TEST_ENTRY (fs_event_watch_dir_recursive) TEST_ENTRY (fs_event_watch_file) + TEST_ENTRY (fs_event_watch_file_exact_path) TEST_ENTRY (fs_event_watch_file_twice) TEST_ENTRY (fs_event_watch_file_current_dir) #ifdef _WIN32 diff --git a/test/test-loop-close.c b/test/test-loop-close.c index 5aec234e..971c9d72 100644 --- a/test/test-loop-close.c +++ b/test/test-loop-close.c @@ -34,7 +34,9 @@ TEST_IMPL(loop_close) { int r; uv_loop_t loop; + loop.data = &loop; ASSERT(0 == uv_loop_init(&loop)); + ASSERT(loop.data == (void*) &loop); uv_timer_init(&loop, &timer_handle); uv_timer_start(&timer_handle, timer_cb, 100, 100); @@ -47,7 +49,9 @@ TEST_IMPL(loop_close) { r = uv_run(&loop, UV_RUN_DEFAULT); ASSERT(r == 0); + ASSERT(loop.data == (void*) &loop); ASSERT(0 == uv_loop_close(&loop)); + ASSERT(loop.data == (void*) &loop); return 0; } diff --git a/test/test-platform-output.c b/test/test-platform-output.c index bd61454f..b8955080 100644 --- a/test/test-platform-output.c +++ b/test/test-platform-output.c @@ -61,8 +61,6 @@ TEST_IMPL(platform_output) { ASSERT(rusage.ru_utime.tv_usec >= 0); ASSERT(rusage.ru_stime.tv_sec >= 0); ASSERT(rusage.ru_stime.tv_usec >= 0); - ASSERT(rusage.ru_majflt >= 0); - ASSERT(rusage.ru_maxrss >= 0); printf("uv_getrusage:\n"); printf(" user: %llu sec %llu microsec\n", (unsigned long long) rusage.ru_utime.tv_sec, diff --git a/test/test-poll-close-doesnt-corrupt-stack.c b/test/test-poll-close-doesnt-corrupt-stack.c index fc2cc004..1dfc80e3 100644 --- a/test/test-poll-close-doesnt-corrupt-stack.c +++ b/test/test-poll-close-doesnt-corrupt-stack.c @@ -19,8 +19,6 @@ * IN THE SOFTWARE. */ -#ifdef _WIN32 - #include #include @@ -37,6 +35,7 @@ uv_os_sock_t sock; uv_poll_t handle; +#ifdef _WIN32 static int close_cb_called = 0; @@ -69,9 +68,13 @@ static void NO_INLINE close_socket_and_verify_stack() { for (i = 0; i < ARRAY_SIZE(data); i++) ASSERT(data[i] == MARKER); } +#endif TEST_IMPL(poll_close_doesnt_corrupt_stack) { +#ifndef _WIN32 + RETURN_SKIP("Test only relevant on Windows"); +#else struct WSAData wsa_data; int r; unsigned long on; @@ -109,6 +112,5 @@ TEST_IMPL(poll_close_doesnt_corrupt_stack) { MAKE_VALGRIND_HAPPY(); return 0; +#endif } - -#endif /* _WIN32 */ diff --git a/test/test-poll-closesocket.c b/test/test-poll-closesocket.c index 4db74a01..ecaa9e54 100644 --- a/test/test-poll-closesocket.c +++ b/test/test-poll-closesocket.c @@ -19,7 +19,6 @@ * IN THE SOFTWARE. */ -#ifdef _WIN32 #include @@ -29,6 +28,7 @@ uv_os_sock_t sock; uv_poll_t handle; +#ifdef _WIN32 static int close_cb_called = 0; @@ -50,9 +50,13 @@ static void poll_cb(uv_poll_t* h, int status, int events) { uv_close((uv_handle_t*) &handle, close_cb); } +#endif TEST_IMPL(poll_closesocket) { +#ifndef _WIN32 + RETURN_SKIP("Test only relevant on Windows"); +#else struct WSAData wsa_data; int r; unsigned long on; @@ -85,5 +89,5 @@ TEST_IMPL(poll_closesocket) { MAKE_VALGRIND_HAPPY(); return 0; -} #endif +} diff --git a/test/test-poll.c b/test/test-poll.c index f3cfe797..33d0761a 100644 --- a/test/test-poll.c +++ b/test/test-poll.c @@ -31,6 +31,16 @@ #include "uv.h" #include "task.h" +#ifdef __linux__ +# include +#endif + +#ifdef UV_HAVE_KQUEUE +# include +# include +# include +#endif + #define NUM_CLIENTS 5 #define TRANSFER_BYTES (1 << 16) @@ -601,3 +611,47 @@ TEST_IMPL(poll_bad_fdtype) { MAKE_VALGRIND_HAPPY(); return 0; } + + +#ifdef __linux__ +TEST_IMPL(poll_nested_epoll) { + uv_poll_t poll_handle; + int fd; + + fd = epoll_create(1); + ASSERT(fd != -1); + + ASSERT(0 == uv_poll_init(uv_default_loop(), &poll_handle, fd)); + ASSERT(0 == uv_poll_start(&poll_handle, UV_READABLE, (uv_poll_cb) abort)); + ASSERT(0 != uv_run(uv_default_loop(), UV_RUN_NOWAIT)); + + uv_close((uv_handle_t*) &poll_handle, NULL); + ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); + ASSERT(0 == close(fd)); + + MAKE_VALGRIND_HAPPY(); + return 0; +} +#endif /* __linux__ */ + + +#ifdef UV_HAVE_KQUEUE +TEST_IMPL(poll_nested_kqueue) { + uv_poll_t poll_handle; + int fd; + + fd = kqueue(); + ASSERT(fd != -1); + + ASSERT(0 == uv_poll_init(uv_default_loop(), &poll_handle, fd)); + ASSERT(0 == uv_poll_start(&poll_handle, UV_READABLE, (uv_poll_cb) abort)); + ASSERT(0 != uv_run(uv_default_loop(), UV_RUN_NOWAIT)); + + uv_close((uv_handle_t*) &poll_handle, NULL); + ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); + ASSERT(0 == close(fd)); + + MAKE_VALGRIND_HAPPY(); + return 0; +} +#endif /* UV_HAVE_KQUEUE */ diff --git a/test/test-process-title.c b/test/test-process-title.c index 42ade441..00f164a4 100644 --- a/test/test-process-title.c +++ b/test/test-process-title.c @@ -41,6 +41,24 @@ static void set_title(const char* title) { } +static void uv_get_process_title_edge_cases() { + char buffer[512]; + int r; + + /* Test a NULL buffer */ + r = uv_get_process_title(NULL, 100); + ASSERT(r == UV_EINVAL); + + /* Test size of zero */ + r = uv_get_process_title(buffer, 0); + ASSERT(r == UV_EINVAL); + + /* Test for insufficient buffer size */ + r = uv_get_process_title(buffer, 1); + ASSERT(r == UV_ENOBUFS); +} + + TEST_IMPL(process_title) { #if defined(__sun) || defined(_AIX) RETURN_SKIP("uv_(get|set)_process_title is not implemented."); @@ -48,6 +66,10 @@ TEST_IMPL(process_title) { /* Check for format string vulnerabilities. */ set_title("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"); set_title("new title"); + + /* Check uv_get_process_title() edge cases */ + uv_get_process_title_edge_cases(); + return 0; #endif } diff --git a/test/test-tcp-close-accept.c b/test/test-tcp-close-accept.c index 5517aaf9..e4878398 100644 --- a/test/test-tcp-close-accept.c +++ b/test/test-tcp-close-accept.c @@ -40,6 +40,7 @@ static unsigned int got_connections; static unsigned int close_cb_called; static unsigned int write_cb_called; static unsigned int read_cb_called; +static unsigned int pending_incoming; static void close_cb(uv_handle_t* handle) { close_cb_called++; @@ -58,8 +59,11 @@ static void connect_cb(uv_connect_t* req, int status) { if (req == &tcp_check_req) { ASSERT(status != 0); - /* Close check and incoming[0], time to finish test */ - uv_close((uv_handle_t*) &tcp_incoming[0], close_cb); + /* + * Time to finish the test: close both the check and pending incoming + * connections + */ + uv_close((uv_handle_t*) &tcp_incoming[pending_incoming], close_cb); uv_close((uv_handle_t*) &tcp_check, close_cb); return; } @@ -84,8 +88,8 @@ static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { uv_loop_t* loop; unsigned int i; - /* Only first stream should receive read events */ - ASSERT(stream == (uv_stream_t*) &tcp_incoming[0]); + pending_incoming = (uv_tcp_t*) stream - &tcp_incoming[0]; + ASSERT(pending_incoming < got_connections); ASSERT(0 == uv_read_stop(stream)); ASSERT(1 == nread); @@ -93,8 +97,13 @@ static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { read_cb_called++; /* Close all active incomings, except current one */ - for (i = 1; i < got_connections; i++) - uv_close((uv_handle_t*) &tcp_incoming[i], close_cb); + for (i = 0; i < got_connections; i++) { + if (i != pending_incoming) + uv_close((uv_handle_t*) &tcp_incoming[i], close_cb); + } + + /* Close server, so no one will connect to it */ + uv_close((uv_handle_t*) &tcp_server, close_cb); /* Create new fd that should be one of the closed incomings */ ASSERT(0 == uv_tcp_init(loop, &tcp_check)); @@ -103,9 +112,6 @@ static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { (const struct sockaddr*) &addr, connect_cb)); ASSERT(0 == uv_read_start((uv_stream_t*) &tcp_check, alloc_cb, read_cb)); - - /* Close server, so no one will connect to it */ - uv_close((uv_handle_t*) &tcp_server, close_cb); } static void connection_cb(uv_stream_t* server, int status) { diff --git a/test/test-tty.c b/test/test-tty.c index 55cc0167..5787d1da 100644 --- a/test/test-tty.c +++ b/test/test-tty.c @@ -262,14 +262,17 @@ TEST_IMPL(tty_file) { TEST_IMPL(tty_pty) { # if defined(__linux__) || defined(__OpenBSD__) || defined(__NetBSD__) || \ defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__) - int master_fd, slave_fd; + int master_fd, slave_fd, r; struct winsize w; uv_loop_t loop; uv_tty_t master_tty, slave_tty; ASSERT(0 == uv_loop_init(&loop)); - ASSERT(0 == openpty(&master_fd, &slave_fd, NULL, NULL, &w)); + r = openpty(&master_fd, &slave_fd, NULL, NULL, &w); + if (r != 0) + RETURN_SKIP("No pty available, skipping."); + ASSERT(0 == uv_tty_init(&loop, &slave_tty, slave_fd, 0)); ASSERT(0 == uv_tty_init(&loop, &master_tty, master_fd, 0)); /* Check if the file descriptor was reopened. If it is, diff --git a/uv.gyp b/uv.gyp index 2fdd59ac..aa4a4244 100644 --- a/uv.gyp +++ b/uv.gyp @@ -426,6 +426,7 @@ 'libraries': [ '-lws2_32' ] }, { # POSIX 'defines': [ '_GNU_SOURCE' ], + 'cflags': [ '-Wno-long-long' ], 'sources': [ 'test/runner-unix.c', 'test/runner-unix.h',