From 4e99cd4e29d3b6fae1dd9cd701997259f9040113 Mon Sep 17 00:00:00 2001 From: Igor Zinkovsky Date: Mon, 12 Dec 2011 12:15:29 -0800 Subject: [PATCH 1/4] windows: fix memory leak when non-zero tcp reads are used --- src/win/tcp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/win/tcp.c b/src/win/tcp.c index dee77875..7965f73a 100644 --- a/src/win/tcp.c +++ b/src/win/tcp.c @@ -822,7 +822,8 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, if (!REQ_SUCCESS(req)) { /* An error occurred doing the read. */ - if ((handle->flags & UV_HANDLE_READING)) { + if ((handle->flags & UV_HANDLE_READING) || + !(handle->flags & UV_HANDLE_ZERO_READ)) { handle->flags &= ~UV_HANDLE_READING; buf = (handle->flags & UV_HANDLE_ZERO_READ) ? uv_buf_init(NULL, 0) : handle->read_buffer; From a4c8ffa3c2f6f927bff10b9e684f4b9513a97826 Mon Sep 17 00:00:00 2001 From: Igor Zinkovsky Date: Mon, 12 Dec 2011 12:15:29 -0800 Subject: [PATCH 2/4] windows: correctly check the result of malloc --- src/win/pipe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/win/pipe.c b/src/win/pipe.c index 3bbfa833..5c20fe48 100644 --- a/src/win/pipe.c +++ b/src/win/pipe.c @@ -1047,7 +1047,7 @@ static int uv_pipe_write_impl(uv_loop_t* loop, uv_write_t* req, ipc_header_req = (uv_write_t*)&handle->ipc_header_write_req; } else { ipc_header_req = (uv_write_t*)malloc(sizeof(uv_write_t)); - if (!handle->accept_reqs) { + if (!ipc_header_req) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } } From 6b3075cd730ff1cb3cf16c68c7b68791c1068bff Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Thu, 17 Nov 2011 18:00:51 +0100 Subject: [PATCH 3/4] linux: improve kernel feature detection Do not check for minimum kernel and glibc versions, just check that the kernel headers export the syscall number and invoke the syscall directly. Effectively bypasses glibc. --- src/unix/core.c | 4 +-- src/unix/internal.h | 71 +++++++++++++++++++++++++++++++++++---------- src/unix/process.c | 4 +-- 3 files changed, 59 insertions(+), 20 deletions(-) diff --git a/src/unix/core.c b/src/unix/core.c index 60b0147b..cf323adc 100644 --- a/src/unix/core.c +++ b/src/unix/core.c @@ -735,8 +735,8 @@ int uv__accept(int sockfd, struct sockaddr* saddr, socklen_t slen) { assert(sockfd >= 0); while (1) { -#if HAVE_ACCEPT4 - peerfd = accept4(sockfd, saddr, &slen, SOCK_NONBLOCK | SOCK_CLOEXEC); +#if HAVE_SYS_ACCEPT4 + peerfd = sys_accept4(sockfd, saddr, &slen, SOCK_NONBLOCK | SOCK_CLOEXEC); if (peerfd != -1) break; diff --git a/src/unix/internal.h b/src/unix/internal.h index 6472baa8..1adb5f20 100644 --- a/src/unix/internal.h +++ b/src/unix/internal.h @@ -32,30 +32,69 @@ #endif #undef HAVE_FUTIMES -#undef HAVE_PIPE2 -#undef HAVE_ACCEPT4 #undef HAVE_KQUEUE #undef HAVE_PORTS_FS #if defined(__linux__) -#include -#include +# undef HAVE_SYS_UTIMESAT +# undef HAVE_SYS_PIPE2 +# undef HAVE_SYS_ACCEPT4 -/* futimes() requires linux >= 2.6.22 and glib >= 2.6 */ -#if LINUX_VERSION_CODE >= 0x20616 && __GLIBC_PREREQ(2, 6) -#define HAVE_FUTIMES 1 -#endif +# undef _GNU_SOURCE +# define _GNU_SOURCE -/* pipe2() requires linux >= 2.6.27 and glibc >= 2.9 */ -#if LINUX_VERSION_CODE >= 0x2061B && __GLIBC_PREREQ(2, 9) -#define HAVE_PIPE2 1 -#endif +# include +# include +# include +# include -/* accept4() requires linux >= 2.6.28 and glib >= 2.10 */ -#if LINUX_VERSION_CODE >= 0x2061C && __GLIBC_PREREQ(2, 10) -#define HAVE_ACCEPT4 1 -#endif +# if __NR_utimensat +# define HAVE_SYS_UTIMESAT 1 +# endif +# if __NR_pipe2 +# define HAVE_SYS_PIPE2 1 +# endif +# if __NR_accept4 +# define HAVE_SYS_ACCEPT4 1 +# endif + +# if HAVE_SYS_UTIMESAT +inline static int sys_utimesat(int dirfd, + const char* path, + const struct timespec times[2], + int flags) +{ + return syscall(__NR_utimensat, dirfd, path, times, flags); +} +inline static int sys_futimes(int fd, const struct timeval times[2]) +{ + struct timespec ts[2]; + ts[0].tv_sec = times[0].tv_sec, ts[0].tv_nsec = times[0].tv_usec * 1000; + ts[1].tv_sec = times[1].tv_sec, ts[1].tv_nsec = times[1].tv_usec * 1000; + return sys_utimesat(fd, NULL, ts, 0); +} +# undef HAVE_FUTIMES +# define HAVE_FUTIMES 1 +# define futimes(fd, times) sys_futimes(fd, times) +# endif /* HAVE_SYS_FUTIMESAT */ + +# if HAVE_SYS_PIPE2 +inline static int sys_pipe2(int pipefd[2], int flags) +{ + return syscall(__NR_pipe2, pipefd, flags); +} +# endif /* HAVE_SYS_PIPE2 */ + +# if HAVE_SYS_ACCEPT4 +inline static int sys_accept4(int fd, + struct sockaddr* addr, + socklen_t* addrlen, + int flags) +{ + return syscall(__NR_accept4, fd, addr, addrlen, flags); +} +# endif /* HAVE_SYS_ACCEPT4 */ #endif /* __linux__ */ diff --git a/src/unix/process.c b/src/unix/process.c index c5a45929..5581d8b8 100644 --- a/src/unix/process.c +++ b/src/unix/process.c @@ -104,7 +104,7 @@ static int uv__make_socketpair(int fds[2], int flags) { static int uv__make_pipe(int fds[2], int flags) { -#if HAVE_PIPE2 +#if HAVE_SYS_PIPE2 int fl; fl = O_CLOEXEC; @@ -112,7 +112,7 @@ static int uv__make_pipe(int fds[2], int flags) { if (flags & UV__F_NONBLOCK) fl |= O_NONBLOCK; - if (pipe2(fds, fl) == 0) + if (sys_pipe2(fds, fl) == 0) return 0; if (errno != ENOSYS) From d808cf9023844a71a606b4f94bf39c3ca565aa11 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Fri, 16 Dec 2011 15:50:19 +0100 Subject: [PATCH 4/4] linux: detect if inotify syscalls are supported --- src/unix/linux.c | 112 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 109 insertions(+), 3 deletions(-) diff --git a/src/unix/linux.c b/src/unix/linux.c index 4b796903..965de017 100644 --- a/src/unix/linux.c +++ b/src/unix/linux.c @@ -27,14 +27,98 @@ #include #include -#include #include #include +#include #include #undef NANOSEC #define NANOSEC 1000000000 +#undef HAVE_INOTIFY_INIT +#undef HAVE_INOTIFY_INIT1 +#undef HAVE_INOTIFY_ADD_WATCH +#undef HAVE_INOTIFY_RM_WATCH + +#if __NR_inotify_init +# define HAVE_INOTIFY_INIT 1 +#endif +#if __NR_inotify_init1 +# define HAVE_INOTIFY_INIT1 1 +#endif +#if __NR_inotify_add_watch +# define HAVE_INOTIFY_ADD_WATCH 1 +#endif +#if __NR_inotify_rm_watch +# define HAVE_INOTIFY_RM_WATCH 1 +#endif + +#if HAVE_INOTIFY_INIT || HAVE_INOTIFY_INIT1 +# undef IN_ACCESS +# undef IN_MODIFY +# undef IN_ATTRIB +# undef IN_CLOSE_WRITE +# undef IN_CLOSE_NOWRITE +# undef IN_OPEN +# undef IN_MOVED_FROM +# undef IN_MOVED_TO +# undef IN_CREATE +# undef IN_DELETE +# undef IN_DELETE_SELF +# undef IN_MOVE_SELF +# define IN_ACCESS 0x001 +# define IN_MODIFY 0x002 +# define IN_ATTRIB 0x004 +# define IN_CLOSE_WRITE 0x008 +# define IN_CLOSE_NOWRITE 0x010 +# define IN_OPEN 0x020 +# define IN_MOVED_FROM 0x040 +# define IN_MOVED_TO 0x080 +# define IN_CREATE 0x100 +# define IN_DELETE 0x200 +# define IN_DELETE_SELF 0x400 +# define IN_MOVE_SELF 0x800 +struct inotify_event { + int32_t wd; + uint32_t mask; + uint32_t cookie; + uint32_t len; + /* char name[0]; */ +}; +#endif /* HAVE_INOTIFY_INIT || HAVE_INOTIFY_INIT1 */ + +#undef IN_CLOEXEC +#undef IN_NONBLOCK + +#if HAVE_INOTIFY_INIT1 +# define IN_CLOEXEC O_CLOEXEC +# define IN_NONBLOCK O_NONBLOCK +#endif /* HAVE_INOTIFY_INIT1 */ + +#if HAVE_INOTIFY_INIT +inline static int inotify_init(void) { + return syscall(__NR_inotify_init); +} +#endif /* HAVE_INOTIFY_INIT */ + +#if HAVE_INOTIFY_INIT1 +inline static int inotify_init1(int flags) { + return syscall(__NR_inotify_init1, flags); +} +#endif /* HAVE_INOTIFY_INIT1 */ + +#if HAVE_INOTIFY_ADD_WATCH +inline static int inotify_add_watch(int fd, const char* path, uint32_t mask) { + return syscall(__NR_inotify_add_watch, fd, path, mask); +} +#endif /* HAVE_INOTIFY_ADD_WATCH */ + +#if HAVE_INOTIFY_RM_WATCH +inline static int inotify_rm_watch(int fd, uint32_t wd) { + return syscall(__NR_inotify_rm_watch, fd, wd); +} +#endif /* HAVE_INOTIFY_RM_WATCH */ + /* Don't look aghast, this is exactly how glibc's basename() works. */ static char* basename_r(const char* path) { @@ -83,8 +167,10 @@ uint64_t uv_get_total_memory(void) { return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_PHYS_PAGES); } +#if HAVE_INOTIFY_INIT || HAVE_INOTIFY_INIT1 + static int new_inotify_fd(void) { -#if defined(IN_NONBLOCK) && defined(IN_CLOEXEC) +#if HAVE_INOTIFY_INIT1 return inotify_init1(IN_NONBLOCK | IN_CLOEXEC); #else int fd; @@ -141,7 +227,7 @@ static void uv__inotify_read(EV_P_ ev_io* w, int revents) { * for modifications. Repurpose the filename for API compatibility. * I'm not convinced this is a good thing, maybe it should go. */ - filename = e->len ? e->name : basename_r(handle->filename); + filename = e->len ? (const char*) (e + 1) : basename_r(handle->filename); handle->cb(handle, filename, events, 0); @@ -209,3 +295,23 @@ void uv__fs_event_destroy(uv_fs_event_t* handle) { free(handle->filename); handle->filename = NULL; } + +#else /* !HAVE_INOTIFY_INIT || HAVE_INOTIFY_INIT1 */ + +int uv_fs_event_init(uv_loop_t* loop, + uv_fs_event_t* handle, + const char* filename, + uv_fs_event_cb cb, + int flags) { + loop->counters.fs_event_init++; + uv__set_sys_error(loop, ENOSYS); + return -1; +} + + +void uv__fs_event_destroy(uv_fs_event_t* handle) { + assert(0 && "unreachable"); + abort(); +} + +#endif /* HAVE_INOTIFY_INIT || HAVE_INOTIFY_INIT1 */