Rui Abreu Ferreira <raf-ep@gmx.com>
João Reis <reis@janeasystems.com>
farblue68 <farblue68@gmail.com>
+Jason Williams <necmon@yahoo.com>
+Igor Soarez <igorsoarez@gmail.com>
+Miodrag Milanovic <mmicko@gmail.com>
+2015.06.04, Version 1.6.0 (Stable), adfccad76456061dfcf79b8df8e7dbfee51791d7
+
+Changes since version 1.5.0:
+
+* aix: fix setsockopt for multicast options (Michael)
+
+* unix: don't block for io if any io handle is primed (Saúl Ibarra Corretgé)
+
+* windows: MSVC 2015 has snprintf() (Rui Abreu Ferreira)
+
+* windows: Add VS2015 support to vcbuild.bat (Jason Williams)
+
+* doc: fix typo in tcp.rst (Igor Soarez)
+
+* linux: work around epoll bug in kernels < 2.6.37 (Ben Noordhuis)
+
+* unix,win: add uv_os_homedir() (cjihrig)
+
+* stream: fix `select()` race condition (Fedor Indutny)
+
+* unix: prevent infinite loop in uv__run_pending (Saúl Ibarra Corretgé)
+
+* unix: make sure UDP send callbacks are asynchronous (Saúl Ibarra Corretgé)
+
+* test: fix `platform_output` netmask printing. (Andrew Paprocki)
+
+* aix: add ahafs autoconf detection and README notes (Andrew Paprocki)
+
+* core: add ability to customize memory allocator (Saúl Ibarra Corretgé)
+
+
2015.05.07, Version 1.5.0 (Stable), 4e77f74c7b95b639b3397095db1bc5bcc016c203
Changes since version 1.4.2:
AM_CPPFLAGS += -I$(top_srcdir)/src/win \
-DWIN32_LEAN_AND_MEAN \
-D_WIN32_WINNT=0x0600
-LIBS += -lws2_32 -lpsapi -liphlpapi -lshell32
+LIBS += -lws2_32 -lpsapi -liphlpapi -lshell32 -luserenv
libuv_la_SOURCES += src/win/async.c \
src/win/atomicops-inl.h \
src/win/core.c \
test/test-getnameinfo.c \
test/test-getsockname.c \
test/test-handle-fileno.c \
+ test/test-homedir.c \
test/test-hrtime.c \
test/test-idle.c \
test/test-ip4-addr.c \
test/test-ping-pong.c \
test/test-pipe-bind-error.c \
test/test-pipe-connect-error.c \
+ test/test-pipe-connect-prepare.c \
test/test-pipe-getsockname.c \
test/test-pipe-sendmsg.c \
test/test-pipe-server-close.c \
Solaris 121 and later using GCC toolchain.
+AIX 6 and later using GCC toolchain (see notes).
+
+### AIX Notes
+
+AIX support for filesystem events requires the non-default IBM `bos.ahafs`
+package to be installed. This package provides the AIX Event Infrastructure
+that is detected by `autoconf`.
+[IBM documentation](http://www.ibm.com/developerworks/aix/library/au-aix_event_infrastructure/)
+describes the package in more detail.
+
+AIX support for filesystem events is not compiled when building with `gyp`.
+
## Patches
See the [guidelines for contributing][].
test/test-get-memory.c
test/test-getaddrinfo.c
test/test-getsockname.c
+test/test-homedir.c
test/test-hrtime.c
test/test-idle.c
test/test-ip6-addr.c
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
AC_PREREQ(2.57)
-AC_INIT([libuv], [1.5.0], [https://github.com/libuv/libuv/issues])
+AC_INIT([libuv], [1.6.0], [https://github.com/libuv/libuv/issues])
AC_CONFIG_MACRO_DIR([m4])
m4_include([m4/libuv-extra-automake-flags.m4])
m4_include([m4/as_case.m4])
AM_CONDITIONAL([OPENBSD], [AS_CASE([$host_os],[openbsd*], [true], [false])])
AM_CONDITIONAL([SUNOS], [AS_CASE([$host_os],[solaris*], [true], [false])])
AM_CONDITIONAL([WINNT], [AS_CASE([$host_os],[mingw*], [true], [false])])
+AC_CHECK_HEADERS([sys/ahafs_evProds.h])
AC_CHECK_PROG(PKG_CONFIG, pkg-config, yes)
AM_CONDITIONAL([HAVE_PKG_CONFIG], [test "x$PKG_CONFIG" != "x"])
AS_IF([test "x$PKG_CONFIG" != "x"], [
.. note::
On Windows this field is ULONG.
+.. c:type:: void* (*uv_malloc_func)(size_t size)
+
+ Replacement function for :man:`malloc(3)`.
+ See :c:func:`uv_replace_allocator`.
+
+.. c:type:: void* (*uv_realloc_func)(void* ptr, size_t size)
+
+ Replacement function for :man:`realloc(3)`.
+ See :c:func:`uv_replace_allocator`.
+
+.. c:type:: void* (*uv_calloc_func)(size_t count, size_t size)
+
+ Replacement function for :man:`calloc(3)`.
+ See :c:func:`uv_replace_allocator`.
+
+.. c:type:: void (*uv_free_func)(void* ptr)
+
+ Replacement function for :man:`free(3)`.
+ See :c:func:`uv_replace_allocator`.
+
.. c:type:: uv_file
Cross platform representation of a file handle.
Returns the libuv version number as a string. For non-release versions
"-pre" is appended, so the version number could be "1.2.3-pre".
+.. c:function:: int uv_replace_allocator(uv_malloc_func malloc_func, uv_realloc_func realloc_func, uv_calloc_func calloc_func, uv_free_func free_func)
+
+ .. versionadded:: 1.6.0
+
+ Override the use of the standard library's :man:`malloc(3)`,
+ :man:`calloc(3)`, :man:`realloc(3)`, :man:`free(3)`, memory allocation
+ functions.
+
+ This function must be called before any other libuv function is called or
+ after all resources have been freed and thus libuv doesn't reference
+ any allocated memory chunk.
+
+ On success, it returns 0, if any of the function pointers is NULL it
+ returns UV_EINVAL.
+
+ .. warning:: There is no protection against changing the allocator multiple
+ times. If the user changes it they are responsible for making
+ sure the allocator is changed while no memory was allocated with
+ the previous allocator, or that they are compatible.
+
.. c:function:: uv_buf_t uv_buf_init(char* base, unsigned int len)
Constructor for :c:type:`uv_buf_t`.
Changes the current working directory.
+.. c:function:: int uv_os_homedir(char* buffer, size_t* size)
+
+ Gets the current user's home directory. On Windows, `uv_os_homedir()` first
+ checks the `USERPROFILE` environment variable using
+ `GetEnvironmentVariableW()`. If `USERPROFILE` is not set,
+ `GetUserProfileDirectoryW()` is called. On all other operating systems,
+ `uv_os_homedir()` first checks the `HOME` environment variable using
+ :man:`getenv(3)`. If `HOME` is not set, :man:`getpwuid_r(3)` is called. The
+ user's home directory is stored in `buffer`. When `uv_os_homedir()` is
+ called, `size` indicates the maximum size of `buffer`. On success or
+ `UV_ENOBUFS` failure, `size` is set to the string length of `buffer`.
+
+ .. warning::
+ `uv_os_homedir()` is not thread safe.
+
+ .. versionadded:: 1.6.0
+
.. uint64_t uv_get_free_memory(void)
.. c:function:: uint64_t uv_get_total_memory(void)
not guarantee that the call to :c:func:`uv_listen` or :c:func:`uv_tcp_connect`
will succeed as well.
- `flags` con contain ``UV_TCP_IPV6ONLY``, in which case dual-stack support
+ `flags` can contain ``UV_TCP_IPV6ONLY``, in which case dual-stack support
is disabled and only IPv6 is used.
.. c:function:: int uv_tcp_getsockname(const uv_tcp_t* handle, struct sockaddr* name, int* namelen)
*/
#define UV_VERSION_MAJOR 1
-#define UV_VERSION_MINOR 5
+#define UV_VERSION_MINOR 6
#define UV_VERSION_PATCH 0
#define UV_VERSION_IS_RELEASE 1
#define UV_VERSION_SUFFIX ""
UV_EXTERN unsigned int uv_version(void);
UV_EXTERN const char* uv_version_string(void);
+typedef void* (*uv_malloc_func)(size_t size);
+typedef void* (*uv_realloc_func)(void* ptr, size_t size);
+typedef void* (*uv_calloc_func)(size_t count, size_t size);
+typedef void (*uv_free_func)(void* ptr);
+
+UV_EXTERN int uv_replace_allocator(uv_malloc_func malloc_func,
+ uv_realloc_func realloc_func,
+ uv_calloc_func calloc_func,
+ uv_free_func free_func);
+
UV_EXTERN uv_loop_t* uv_default_loop(void);
UV_EXTERN int uv_loop_init(uv_loop_t* loop);
UV_EXTERN int uv_loop_close(uv_loop_t* loop);
UV_EXTERN int uv_getrusage(uv_rusage_t* rusage);
+UV_EXTERN int uv_os_homedir(char* buffer, size_t* size);
+
UV_EXTERN int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count);
UV_EXTERN void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count);
loop = handle->loop;
len = strlen(path);
- ctx = calloc(1, sizeof(*ctx) + len);
+ ctx = uv__calloc(1, sizeof(*ctx) + len);
if (ctx == NULL)
return UV_ENOMEM;
return 0;
error:
- free(ctx);
+ uv__free(ctx);
return err;
}
static void timer_close_cb(uv_handle_t* handle) {
- free(container_of(handle, struct poll_ctx, timer_handle));
+ uv__free(container_of(handle, struct poll_ctx, timer_handle));
}
abort();
if (threads != default_threads)
- free(threads);
+ uv__free(threads);
uv_mutex_destroy(&mutex);
uv_cond_destroy(&cond);
threads = default_threads;
if (nthreads > ARRAY_SIZE(default_threads)) {
- threads = malloc(nthreads * sizeof(threads[0]));
+ threads = uv__malloc(nthreads * sizeof(threads[0]));
if (threads == NULL) {
nthreads = ARRAY_SIZE(default_threads);
threads = default_threads;
#include <sys/pollset.h>
#include <ctype.h>
+#ifdef HAVE_SYS_AHAFS_EVPRODS_H
#include <sys/ahafs_evProds.h>
+#endif
#include <sys/mntctl.h>
#include <sys/vmount.h>
}
+#ifdef HAVE_SYS_AHAFS_EVPRODS_H
static char *uv__rawname(char *cp) {
static char rawbuf[FILENAME_MAX+1];
char *dp = rindex(cp, '/');
const char *dev = "/aha";
char *obj, *stub;
- p = malloc(siz);
+ p = uv__malloc(siz);
if (p == NULL)
return -errno;
if (rv == 0) {
/* buffer was not large enough, reallocate to correct size */
siz = *(int*)p;
- free(p);
- p = malloc(siz);
+ uv__free(p);
+ p = uv__malloc(siz);
if (p == NULL)
return -errno;
rv = mntctl(MCTL_QUERY, siz, (char*)p);
stub = vmt2dataptr(vmt, VMT_STUB); /* mount point */
if (EQ(obj, dev) || EQ(uv__rawname(obj), dev) || EQ(stub, dev)) {
- free(p); /* Found a match */
+ uv__free(p); /* Found a match */
return 0;
}
vmt = (struct vmount *) ((char *) vmt + vmt->vmt_length);
/* Scan out the name of the file that triggered the event*/
if (sscanf(p, "BEGIN_EVPROD_INFO\n%sEND_EVPROD_INFO", filename) == 1) {
- handle->dir_filename = strdup((const char*)&filename);
+ handle->dir_filename = uv__strdup((const char*)&filename);
} else
return -1;
}
else /* Call the actual JavaScript callback function */
handle->cb(handle, (const char*)&fname, events, 0);
}
+#endif
int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
+#ifdef HAVE_SYS_AHAFS_EVPRODS_H
uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT);
return 0;
+#else
+ return -ENOSYS;
+#endif
}
uv_fs_event_cb cb,
const char* filename,
unsigned int flags) {
+#ifdef HAVE_SYS_AHAFS_EVPRODS_H
int fd, rc, i = 0, res = 0;
char cwd[PATH_MAX];
char absolute_path[PATH_MAX];
/* Setup/Initialize all the libuv routines */
uv__handle_start(handle);
uv__io_init(&handle->event_watcher, uv__ahafs_event, fd);
- handle->path = strdup((const char*)&absolute_path);
+ handle->path = uv__strdup((const char*)&absolute_path);
handle->cb = cb;
uv__io_start(handle->loop, &handle->event_watcher, UV__POLLIN);
return 0;
+#else
+ return -ENOSYS;
+#endif
}
int uv_fs_event_stop(uv_fs_event_t* handle) {
-
+#ifdef HAVE_SYS_AHAFS_EVPRODS_H
if (!uv__is_active(handle))
return 0;
uv__handle_stop(handle);
if (uv__path_is_a_directory(handle->path) == 0) {
- free(handle->dir_filename);
+ uv__free(handle->dir_filename);
handle->dir_filename = NULL;
}
- free(handle->path);
+ uv__free(handle->path);
handle->path = NULL;
uv__close(handle->event_watcher.fd);
handle->event_watcher.fd = -1;
return 0;
+#else
+ return -ENOSYS;
+#endif
}
void uv__fs_event_close(uv_fs_event_t* handle) {
+#ifdef HAVE_SYS_AHAFS_EVPRODS_H
uv_fs_event_stop(handle);
+#else
+ UNREACHABLE();
+#endif
}
return -ENOSYS;
}
- ps_cpus = (perfstat_cpu_t*) malloc(ncpus * sizeof(perfstat_cpu_t));
+ ps_cpus = (perfstat_cpu_t*) uv__malloc(ncpus * sizeof(perfstat_cpu_t));
if (!ps_cpus) {
return -ENOMEM;
}
strcpy(cpu_id.name, FIRST_CPU);
result = perfstat_cpu(&cpu_id, ps_cpus, sizeof(perfstat_cpu_t), ncpus);
if (result == -1) {
- free(ps_cpus);
+ uv__free(ps_cpus);
return -ENOSYS;
}
- *cpu_infos = (uv_cpu_info_t*) malloc(ncpus * sizeof(uv_cpu_info_t));
+ *cpu_infos = (uv_cpu_info_t*) uv__malloc(ncpus * sizeof(uv_cpu_info_t));
if (!*cpu_infos) {
- free(ps_cpus);
+ uv__free(ps_cpus);
return -ENOMEM;
}
cpu_info = *cpu_infos;
while (idx < ncpus) {
cpu_info->speed = (int)(ps_total.processorHZ / 1000000);
- cpu_info->model = strdup(ps_total.description);
+ cpu_info->model = uv__strdup(ps_total.description);
cpu_info->cpu_times.user = ps_cpus[idx].user;
cpu_info->cpu_times.sys = ps_cpus[idx].sys;
cpu_info->cpu_times.idle = ps_cpus[idx].idle;
idx++;
}
- free(ps_cpus);
+ uv__free(ps_cpus);
return 0;
}
int i;
for (i = 0; i < count; ++i) {
- free(cpu_infos[i].model);
+ uv__free(cpu_infos[i].model);
}
- free(cpu_infos);
+ uv__free(cpu_infos);
}
return -errno;
}
- ifc.ifc_req = (struct ifreq*)malloc(size);
+ ifc.ifc_req = (struct ifreq*)uv__malloc(size);
ifc.ifc_len = size;
if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) {
SAVE_ERRNO(uv__close(sockfd));
/* Alloc the return interface structs */
*addresses = (uv_interface_address_t*)
- malloc(*count * sizeof(uv_interface_address_t));
+ uv__malloc(*count * sizeof(uv_interface_address_t));
if (!(*addresses)) {
uv__close(sockfd);
return -ENOMEM;
/* All conditions above must match count loop */
- address->name = strdup(p->ifr_name);
+ address->name = uv__strdup(p->ifr_name);
if (p->ifr_addr.sa_family == AF_INET6) {
address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr);
int i;
for (i = 0; i < count; ++i) {
- free(addresses[i].name);
+ uv__free(addresses[i].name);
}
- free(addresses);
+ uv__free(addresses);
}
void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
{
int l_read;
- free(l_buffer);
- l_buffer = malloc(l_size);
+ uv__free(l_buffer);
+ l_buffer = uv__malloc(l_size);
if (l_buffer == NULL)
{
return NULL;
*p_size = l_read;
if(l_read == -2)
{
- free(l_buffer);
+ uv__free(l_buffer);
return NULL;
}
if(l_read >= 0)
if(l_hdr->nlmsg_type == NLMSG_ERROR)
{
- free(l_buffer);
+ uv__free(l_buffer);
return NULL;
}
}
static NetlinkList *newListItem(struct nlmsghdr *p_data, unsigned int p_size)
{
- NetlinkList *l_item = malloc(sizeof(NetlinkList));
+ NetlinkList *l_item = uv__malloc(sizeof(NetlinkList));
if (l_item == NULL)
{
return NULL;
{
l_cur = p_list;
p_list = p_list->m_next;
- free(l_cur->m_data);
- free(l_cur);
+ uv__free(l_cur->m_data);
+ uv__free(l_cur);
}
}
}
}
- l_entry = malloc(sizeof(struct ifaddrs) + sizeof(int) + l_nameSize + l_addrSize + l_dataSize);
+ l_entry = uv__malloc(sizeof(struct ifaddrs) + sizeof(int) + l_nameSize + l_addrSize + l_dataSize);
if (l_entry == NULL)
{
return -1;
}
}
- l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize);
+ l_entry = uv__malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize);
if (l_entry == NULL)
{
return -1;
{
l_cur = ifa;
ifa = ifa->ifa_next;
- free(l_cur);
+ uv__free(l_cur);
}
}
#include <limits.h> /* INT_MAX, PATH_MAX */
#include <sys/uio.h> /* writev */
#include <sys/resource.h> /* getrusage */
+#include <pwd.h>
#ifdef __linux__
# include <sys/ioctl.h>
if (!QUEUE_EMPTY(&loop->idle_handles))
return 0;
+ if (!QUEUE_EMPTY(&loop->pending_queue))
+ return 0;
+
if (loop->closing_handles)
return 0;
static int uv__run_pending(uv_loop_t* loop) {
QUEUE* q;
+ QUEUE pq;
uv__io_t* w;
if (QUEUE_EMPTY(&loop->pending_queue))
return 0;
- while (!QUEUE_EMPTY(&loop->pending_queue)) {
- q = QUEUE_HEAD(&loop->pending_queue);
+ QUEUE_INIT(&pq);
+ q = QUEUE_HEAD(&loop->pending_queue);
+ QUEUE_SPLIT(&loop->pending_queue, q, &pq);
+
+ while (!QUEUE_EMPTY(&pq)) {
+ q = QUEUE_HEAD(&pq);
QUEUE_REMOVE(q);
QUEUE_INIT(q);
-
w = QUEUE_DATA(q, uv__io_t, pending_queue);
w->cb(loop, w, UV__POLLOUT);
}
}
nwatchers = next_power_of_two(len + 2) - 2;
- watchers = realloc(loop->watchers,
- (nwatchers + 2) * sizeof(loop->watchers[0]));
+ watchers = uv__realloc(loop->watchers,
+ (nwatchers + 2) * sizeof(loop->watchers[0]));
if (watchers == NULL)
abort();
return r;
}
}
+
+
+int uv_os_homedir(char* buffer, size_t* size) {
+ struct passwd pw;
+ struct passwd* result;
+ char* buf;
+ uid_t uid;
+ size_t bufsize;
+ size_t len;
+ int r;
+
+ if (buffer == NULL || size == NULL || *size == 0)
+ return -EINVAL;
+
+ /* Check if the HOME environment variable is set first */
+ buf = getenv("HOME");
+
+ if (buf != NULL) {
+ len = strlen(buf);
+
+ if (len >= *size) {
+ *size = len;
+ return -ENOBUFS;
+ }
+
+ memcpy(buffer, buf, len + 1);
+ *size = len;
+
+ return 0;
+ }
+
+ /* HOME is not set, so call getpwuid() */
+ bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
+
+ if (bufsize <= 0)
+ return -EIO;
+
+ uid = getuid();
+ buf = NULL;
+
+ for (;;) {
+ uv__free(buf);
+ buf = uv__malloc(bufsize);
+
+ if (buf == NULL)
+ return -ENOMEM;
+
+ r = getpwuid_r(uid, &pw, buf, bufsize, &result);
+
+ if (r != ERANGE)
+ break;
+
+ bufsize *= 2;
+ }
+
+ if (r != 0) {
+ uv__free(buf);
+ return -r;
+ }
+
+ if (result == NULL) {
+ uv__free(buf);
+ return -ENOENT;
+ }
+
+ len = strlen(pw.pw_dir);
+
+ if (len >= *size) {
+ *size = len;
+ uv__free(buf);
+ return -ENOBUFS;
+ }
+
+ memcpy(buffer, pw.pw_dir, len + 1);
+ *size = len;
+ uv__free(buf);
+
+ return 0;
+}
return -EINVAL; /* FIXME(bnoordhuis) Translate error. */
}
- *cpu_infos = malloc(numcpus * sizeof(**cpu_infos));
+ *cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos));
if (!(*cpu_infos))
return -ENOMEM; /* FIXME(bnoordhuis) Deallocate info? */
cpu_info->cpu_times.idle = (uint64_t)(info[i].cpu_ticks[2]) * multiplier;
cpu_info->cpu_times.irq = 0;
- cpu_info->model = strdup(model);
+ cpu_info->model = uv__strdup(model);
cpu_info->speed = cpuspeed/1000000;
}
vm_deallocate(mach_task_self(), (vm_address_t)info, msg_type);
int i;
for (i = 0; i < count; i++) {
- free(cpu_infos[i].model);
+ uv__free(cpu_infos[i].model);
}
- free(cpu_infos);
+ uv__free(cpu_infos);
}
(*count)++;
}
- *addresses = malloc(*count * sizeof(**addresses));
+ *addresses = uv__malloc(*count * sizeof(**addresses));
if (!(*addresses))
return -ENOMEM;
if (ent->ifa_addr->sa_family == AF_LINK)
continue;
- address->name = strdup(ent->ifa_name);
+ address->name = uv__strdup(ent->ifa_name);
if (ent->ifa_addr->sa_family == AF_INET6) {
address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
int i;
for (i = 0; i < count; i++) {
- free(addresses[i].name);
+ uv__free(addresses[i].name);
}
- free(addresses);
+ uv__free(addresses);
}
void uv_dlclose(uv_lib_t* lib) {
if (lib->errmsg) {
- free(lib->errmsg);
+ uv__free(lib->errmsg);
lib->errmsg = NULL;
}
const char* errmsg;
if (lib->errmsg)
- free(lib->errmsg);
+ uv__free(lib->errmsg);
errmsg = dlerror();
if (errmsg) {
- lib->errmsg = strdup(errmsg);
+ lib->errmsg = uv__strdup(errmsg);
return -1;
}
else {
char** uv_setup_args(int argc, char** argv) {
- process_title = argc ? strdup(argv[0]) : NULL;
+ process_title = argc ? uv__strdup(argv[0]) : NULL;
return argv;
}
int uv_set_process_title(const char* title) {
int oid[4];
- if (process_title) free(process_title);
- process_title = strdup(title);
+ if (process_title) uv__free(process_title);
+ process_title = uv__strdup(title);
oid[0] = CTL_KERN;
oid[1] = KERN_PROC;
if (sysctlbyname("hw.ncpu", &numcpus, &size, NULL, 0))
return -errno;
- *cpu_infos = malloc(numcpus * sizeof(**cpu_infos));
+ *cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos));
if (!(*cpu_infos))
return -ENOMEM;
size = sizeof(cpuspeed);
if (sysctlbyname("hw.clockrate", &cpuspeed, &size, NULL, 0)) {
- SAVE_ERRNO(free(*cpu_infos));
+ SAVE_ERRNO(uv__free(*cpu_infos));
return -errno;
}
*/
size = sizeof(maxcpus);
if (sysctlbyname(maxcpus_key, &maxcpus, &size, NULL, 0)) {
- SAVE_ERRNO(free(*cpu_infos));
+ SAVE_ERRNO(uv__free(*cpu_infos));
return -errno;
}
size = maxcpus * CPUSTATES * sizeof(long);
- cp_times = malloc(size);
+ cp_times = uv__malloc(size);
if (cp_times == NULL) {
- free(*cpu_infos);
+ uv__free(*cpu_infos);
return -ENOMEM;
}
if (sysctlbyname(cptimes_key, cp_times, &size, NULL, 0)) {
- SAVE_ERRNO(free(cp_times));
- SAVE_ERRNO(free(*cpu_infos));
+ SAVE_ERRNO(uv__free(cp_times));
+ SAVE_ERRNO(uv__free(*cpu_infos));
return -errno;
}
cpu_info->cpu_times.idle = (uint64_t)(cp_times[CP_IDLE+cur]) * multiplier;
cpu_info->cpu_times.irq = (uint64_t)(cp_times[CP_INTR+cur]) * multiplier;
- cpu_info->model = strdup(model);
+ cpu_info->model = uv__strdup(model);
cpu_info->speed = cpuspeed;
cur+=CPUSTATES;
}
- free(cp_times);
+ uv__free(cp_times);
return 0;
}
int i;
for (i = 0; i < count; i++) {
- free(cpu_infos[i].model);
+ uv__free(cpu_infos[i].model);
}
- free(cpu_infos);
+ uv__free(cpu_infos);
}
(*count)++;
}
- *addresses = malloc(*count * sizeof(**addresses));
+ *addresses = uv__malloc(*count * sizeof(**addresses));
if (!(*addresses))
return -ENOMEM;
if (ent->ifa_addr->sa_family == AF_LINK)
continue;
- address->name = strdup(ent->ifa_name);
+ address->name = uv__strdup(ent->ifa_name);
if (ent->ifa_addr->sa_family == AF_INET6) {
address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
int i;
for (i = 0; i < count; i++) {
- free(addresses[i].name);
+ uv__free(addresses[i].name);
}
- free(addresses);
+ uv__free(addresses);
}
#define PATH \
do { \
- (req)->path = strdup(path); \
+ (req)->path = uv__strdup(path); \
if ((req)->path == NULL) \
return -ENOMEM; \
} \
size_t new_path_len; \
path_len = strlen((path)) + 1; \
new_path_len = strlen((new_path)) + 1; \
- (req)->path = malloc(path_len + new_path_len); \
+ (req)->path = uv__malloc(path_len + new_path_len); \
if ((req)->path == NULL) \
return -ENOMEM; \
(req)->new_path = (req)->path + path_len; \
done:
if (req->bufs != req->bufsml)
- free(req->bufs);
+ uv__free(req->bufs);
return result;
}
int i;
for (i = 0; i < n; i++)
- free(dents[i]);
- free(dents);
+ uv__free(dents[i]);
+ uv__free(dents);
}
errno = saved_errno;
#endif
}
- buf = malloc(len + 1);
+ buf = uv__malloc(len + 1);
if (buf == NULL) {
errno = ENOMEM;
len = readlink(req->path, buf, len);
if (len == -1) {
- free(buf);
+ uv__free(buf);
return -1;
}
#endif
if (req->bufs != req->bufsml)
- free(req->bufs);
+ uv__free(req->bufs);
return r;
}
const char* tpl,
uv_fs_cb cb) {
INIT(MKDTEMP);
- req->path = strdup(tpl);
+ req->path = uv__strdup(tpl);
if (req->path == NULL)
return -ENOMEM;
POST;
req->nbufs = nbufs;
req->bufs = req->bufsml;
if (nbufs > ARRAY_SIZE(req->bufsml))
- req->bufs = malloc(nbufs * sizeof(*bufs));
+ req->bufs = uv__malloc(nbufs * sizeof(*bufs));
if (req->bufs == NULL)
return -ENOMEM;
req->nbufs = nbufs;
req->bufs = req->bufsml;
if (nbufs > ARRAY_SIZE(req->bufsml))
- req->bufs = malloc(nbufs * sizeof(*bufs));
+ req->bufs = uv__malloc(nbufs * sizeof(*bufs));
if (req->bufs == NULL)
return -ENOMEM;
void uv_fs_req_cleanup(uv_fs_t* req) {
- free((void*) req->path);
+ uv__free((void*)req->path);
req->path = NULL;
req->new_path = NULL;
uv__fs_scandir_cleanup(req);
if (req->ptr != &req->statbuf)
- free(req->ptr);
+ uv__free(req->ptr);
req->ptr = NULL;
}
if (!uv__is_closing((handle)) && uv__is_active((handle))) \
block \
/* Free allocated data */ \
- free(event); \
+ uv__free(event); \
} \
if (err != 0 && !uv__is_closing((handle)) && uv__is_active((handle))) \
(handle)->cb((handle), NULL, 0, err); \
len = 0;
#endif /* MAC_OS_X_VERSION_10_7 */
- event = malloc(sizeof(*event) + len);
+ event = uv__malloc(sizeof(*event) + len);
if (event == NULL)
break;
uv_mutex_lock(&state->fsevent_mutex);
path_count = state->fsevent_handle_count;
if (path_count != 0) {
- paths = malloc(sizeof(*paths) * path_count);
+ paths = uv__malloc(sizeof(*paths) * path_count);
if (paths == NULL) {
uv_mutex_unlock(&state->fsevent_mutex);
goto final;
if (cf_paths == NULL) {
while (i != 0)
pCFRelease(paths[--i]);
- free(paths);
+ uv__free(paths);
} else {
/* CFArray takes ownership of both strings and original C-array */
pCFRelease(cf_paths);
if (err)
return err;
- state = calloc(1, sizeof(*state));
+ state = uv__calloc(1, sizeof(*state));
if (state == NULL)
return -ENOMEM;
uv_mutex_destroy(&loop->cf_mutex);
fail_mutex_init:
- free(state);
+ uv__free(state);
return err;
}
q = QUEUE_HEAD(&loop->cf_signals);
s = QUEUE_DATA(q, uv__cf_loop_signal_t, member);
QUEUE_REMOVE(q);
- free(s);
+ uv__free(s);
}
/* Destroy state */
uv_sem_destroy(&state->fsevent_sem);
uv_mutex_destroy(&state->fsevent_mutex);
pCFRelease(state->signal_source);
- free(state);
+ uv__free(state);
loop->cf_state = NULL;
}
uv__fsevents_reschedule(s->handle);
QUEUE_REMOVE(item);
- free(s);
+ uv__free(s);
}
}
uv__cf_loop_signal_t* item;
uv__cf_loop_state_t* state;
- item = malloc(sizeof(*item));
+ item = uv__malloc(sizeof(*item));
if (item == NULL)
return -ENOMEM;
* Events will occur in other thread.
* Initialize callback for getting them back into event loop's thread
*/
- handle->cf_cb = malloc(sizeof(*handle->cf_cb));
+ handle->cf_cb = uv__malloc(sizeof(*handle->cf_cb));
if (handle->cf_cb == NULL) {
err = -ENOMEM;
goto fail_cf_cb_malloc;
uv_mutex_destroy(&handle->cf_mutex);
fail_cf_mutex_init:
- free(handle->cf_cb);
+ uv__free(handle->cf_cb);
handle->cf_cb = NULL;
fail_cf_cb_malloc:
- free(handle->realpath);
+ uv__free(handle->realpath);
handle->realpath = NULL;
handle->realpath_len = 0;
/* Wait for deinitialization */
uv_sem_wait(&state->fsevent_sem);
- uv_close((uv_handle_t*) handle->cf_cb, (uv_close_cb) free);
+ uv_close((uv_handle_t*) handle->cf_cb, (uv_close_cb) uv__free);
handle->cf_cb = NULL;
/* Free data in queue */
});
uv_mutex_destroy(&handle->cf_mutex);
- free(handle->realpath);
+ uv__free(handle->realpath);
handle->realpath = NULL;
handle->realpath_len = 0;
/* See initialization in uv_getaddrinfo(). */
if (req->hints)
- free(req->hints);
+ uv__free(req->hints);
else if (req->service)
- free(req->service);
+ uv__free(req->service);
else if (req->hostname)
- free(req->hostname);
+ uv__free(req->hostname);
else
assert(0);
hostname_len = hostname ? strlen(hostname) + 1 : 0;
service_len = service ? strlen(service) + 1 : 0;
hints_len = hints ? sizeof(*hints) : 0;
- buf = malloc(hostname_len + service_len + hints_len);
+ buf = uv__malloc(hostname_len + service_len + hints_len);
if (buf == NULL)
return -ENOMEM;
UV_TCP_NODELAY = 0x400, /* Disable Nagle. */
UV_TCP_KEEPALIVE = 0x800, /* Turn on keep-alive. */
UV_TCP_SINGLE_ACCEPT = 0x1000, /* Only accept() when idle. */
- UV_HANDLE_IPV6 = 0x10000 /* Handle is bound to a IPv6 socket. */
+ UV_HANDLE_IPV6 = 0x10000, /* Handle is bound to a IPv6 socket. */
+ UV_UDP_PROCESSING = 0x20000 /* Handle is running the send callback queue. */
};
/* loop flags */
uv__handle_start(handle);
uv__io_init(&handle->event_watcher, uv__fs_event, fd);
- handle->path = strdup(path);
+ handle->path = uv__strdup(path);
handle->cb = cb;
#if defined(__APPLE__)
uv__io_close(handle->loop, &handle->event_watcher);
}
- free(handle->path);
+ uv__free(handle->path);
handle->path = NULL;
uv__close(handle->event_watcher.fd);
void uv__io_poll(uv_loop_t* loop, int timeout) {
+ /* A bug in kernels < 2.6.37 makes timeouts larger than ~30 minutes
+ * effectively infinite on 32 bits architectures. To avoid blocking
+ * indefinitely, we cap the timeout and poll again if necessary.
+ *
+ * Note that "30 minutes" is a simplification because it depends on
+ * the value of CONFIG_HZ. The magic constant assumes CONFIG_HZ=1200,
+ * that being the largest value I have seen in the wild (and only once.)
+ */
+ static const int max_safe_timeout = 1789569;
static int no_epoll_pwait;
static int no_epoll_wait;
struct uv__epoll_event events[1024];
struct uv__epoll_event* pe;
struct uv__epoll_event e;
+ int real_timeout;
QUEUE* q;
uv__io_t* w;
sigset_t sigset;
uint64_t sigmask;
uint64_t base;
- uint64_t diff;
int nevents;
int count;
int nfds;
assert(timeout >= -1);
base = loop->time;
count = 48; /* Benchmarks suggest this gives the best throughput. */
+ real_timeout = timeout;
for (;;) {
+ /* See the comment for max_safe_timeout for an explanation of why
+ * this is necessary. Executive summary: kernel bug workaround.
+ */
+ if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout)
+ timeout = max_safe_timeout;
+
if (sigmask != 0 && no_epoll_pwait != 0)
if (pthread_sigmask(SIG_BLOCK, &sigset, NULL))
abort();
if (nfds == 0) {
assert(timeout != -1);
+
+ timeout = real_timeout - timeout;
+ if (timeout > 0)
+ continue;
+
return;
}
update_timeout:
assert(timeout > 0);
- diff = loop->time - base;
- if (diff >= (uint64_t) timeout)
+ real_timeout -= (loop->time - base);
+ if (real_timeout <= 0)
return;
- timeout -= diff;
+ timeout = real_timeout;
}
}
assert(numcpus != (unsigned int) -1);
assert(numcpus != 0);
- ci = calloc(numcpus, sizeof(*ci));
+ ci = uv__calloc(numcpus, sizeof(*ci));
if (ci == NULL)
return -ENOMEM;
if (model_idx < numcpus) {
if (strncmp(buf, model_marker, sizeof(model_marker) - 1) == 0) {
model = buf + sizeof(model_marker) - 1;
- model = strndup(model, strlen(model) - 1); /* Strip newline. */
+ model = uv__strndup(model, strlen(model) - 1); /* Strip newline. */
if (model == NULL) {
fclose(fp);
return -ENOMEM;
#endif
if (strncmp(buf, model_marker, sizeof(model_marker) - 1) == 0) {
model = buf + sizeof(model_marker) - 1;
- model = strndup(model, strlen(model) - 1); /* Strip newline. */
+ model = uv__strndup(model, strlen(model) - 1); /* Strip newline. */
if (model == NULL) {
fclose(fp);
return -ENOMEM;
inferred_model = ci[model_idx - 1].model;
while (model_idx < numcpus) {
- model = strndup(inferred_model, strlen(inferred_model));
+ model = uv__strndup(inferred_model, strlen(inferred_model));
if (model == NULL)
return -ENOMEM;
ci[model_idx++].model = model;
int i;
for (i = 0; i < count; i++) {
- free(cpu_infos[i].model);
+ uv__free(cpu_infos[i].model);
}
- free(cpu_infos);
+ uv__free(cpu_infos);
}
if (*count == 0)
return 0;
- *addresses = malloc(*count * sizeof(**addresses));
+ *addresses = uv__malloc(*count * sizeof(**addresses));
if (!(*addresses))
return -ENOMEM;
if (ent->ifa_addr->sa_family == PF_PACKET)
continue;
- address->name = strdup(ent->ifa_name);
+ address->name = uv__strdup(ent->ifa_name);
if (ent->ifa_addr->sa_family == AF_INET6) {
address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
int i;
for (i = 0; i < count; i++) {
- free(addresses[i].name);
+ uv__free(addresses[i].name);
}
- free(addresses);
+ uv__free(addresses);
}
if (w)
goto no_insert;
- w = malloc(sizeof(*w) + strlen(path) + 1);
+ w = uv__malloc(sizeof(*w) + strlen(path) + 1);
if (w == NULL)
return -ENOMEM;
/* No watchers left for this path. Clean up. */
RB_REMOVE(watcher_root, CAST(&handle->loop->inotify_watchers), w);
uv__inotify_rm_watch(handle->loop->inotify_fd, w->wd);
- free(w);
+ uv__free(w);
}
return 0;
assert(loop->nfds == 0);
#endif
- free(loop->watchers);
+ uv__free(loop->watchers);
loop->watchers = NULL;
loop->nwatchers = 0;
}
char** uv_setup_args(int argc, char** argv) {
- process_title = argc ? strdup(argv[0]) : NULL;
+ process_title = argc ? uv__strdup(argv[0]) : NULL;
return argv;
}
int uv_set_process_title(const char* title) {
- if (process_title) free(process_title);
+ if (process_title) uv__free(process_title);
- process_title = strdup(title);
+ process_title = uv__strdup(title);
setproctitle("%s", title);
return 0;
cpuspeed = 0;
size = numcpus * CPUSTATES * sizeof(*cp_times);
- cp_times = malloc(size);
+ cp_times = uv__malloc(size);
if (cp_times == NULL)
return -ENOMEM;
if (sysctlbyname("kern.cp_time", cp_times, &size, NULL, 0))
return -errno;
- *cpu_infos = malloc(numcpus * sizeof(**cpu_infos));
+ *cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos));
if (!(*cpu_infos)) {
- free(cp_times);
- free(*cpu_infos);
+ uv__free(cp_times);
+ uv__free(*cpu_infos);
return -ENOMEM;
}
cpu_info->cpu_times.sys = (uint64_t)(cp_times[CP_SYS+cur]) * multiplier;
cpu_info->cpu_times.idle = (uint64_t)(cp_times[CP_IDLE+cur]) * multiplier;
cpu_info->cpu_times.irq = (uint64_t)(cp_times[CP_INTR+cur]) * multiplier;
- cpu_info->model = strdup(model);
+ cpu_info->model = uv__strdup(model);
cpu_info->speed = (int)(cpuspeed/(uint64_t) 1e6);
cur += CPUSTATES;
}
- free(cp_times);
+ uv__free(cp_times);
return 0;
}
int i;
for (i = 0; i < count; i++) {
- free(cpu_infos[i].model);
+ uv__free(cpu_infos[i].model);
}
- free(cpu_infos);
+ uv__free(cpu_infos);
}
(*count)++;
}
- *addresses = malloc(*count * sizeof(**addresses));
+ *addresses = uv__malloc(*count * sizeof(**addresses));
if (!(*addresses))
return -ENOMEM;
if (ent->ifa_addr->sa_family != PF_INET)
continue;
- address->name = strdup(ent->ifa_name);
+ address->name = uv__strdup(ent->ifa_name);
if (ent->ifa_addr->sa_family == AF_INET6) {
address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
int i;
for (i = 0; i < count; i++) {
- free(addresses[i].name);
+ uv__free(addresses[i].name);
}
- free(addresses);
+ uv__free(addresses);
}
mypid = getpid();
for (;;) {
err = -ENOMEM;
- argsbuf_tmp = realloc(argsbuf, argsbuf_size);
+ argsbuf_tmp = uv__realloc(argsbuf, argsbuf_size);
if (argsbuf_tmp == NULL)
goto out;
argsbuf = argsbuf_tmp;
err = 0;
out:
- free(argsbuf);
+ uv__free(argsbuf);
return err;
}
char** uv_setup_args(int argc, char** argv) {
- process_title = argc ? strdup(argv[0]) : NULL;
+ process_title = argc ? uv__strdup(argv[0]) : NULL;
return argv;
}
int uv_set_process_title(const char* title) {
- if (process_title) free(process_title);
- process_title = strdup(title);
+ if (process_title) uv__free(process_title);
+ process_title = uv__strdup(title);
setproctitle(title);
return 0;
}
if (sysctl(which, 2, &numcpus, &size, NULL, 0))
return -errno;
- *cpu_infos = malloc(numcpus * sizeof(**cpu_infos));
+ *cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos));
if (!(*cpu_infos))
return -ENOMEM;
which[1] = HW_CPUSPEED;
size = sizeof(cpuspeed);
if (sysctl(which, 2, &cpuspeed, &size, NULL, 0)) {
- SAVE_ERRNO(free(*cpu_infos));
+ SAVE_ERRNO(uv__free(*cpu_infos));
return -errno;
}
which[2] = i;
size = sizeof(info);
if (sysctl(which, 3, &info, &size, NULL, 0)) {
- SAVE_ERRNO(free(*cpu_infos));
+ SAVE_ERRNO(uv__free(*cpu_infos));
return -errno;
}
cpu_info->cpu_times.idle = (uint64_t)(info[CP_IDLE]) * multiplier;
cpu_info->cpu_times.irq = (uint64_t)(info[CP_INTR]) * multiplier;
- cpu_info->model = strdup(model);
+ cpu_info->model = uv__strdup(model);
cpu_info->speed = cpuspeed;
}
int i;
for (i = 0; i < count; i++) {
- free(cpu_infos[i].model);
+ uv__free(cpu_infos[i].model);
}
- free(cpu_infos);
+ uv__free(cpu_infos);
}
(*count)++;
}
- *addresses = malloc(*count * sizeof(**addresses));
+ *addresses = uv__malloc(*count * sizeof(**addresses));
if (!(*addresses))
return -ENOMEM;
if (ent->ifa_addr->sa_family != PF_INET)
continue;
- address->name = strdup(ent->ifa_name);
+ address->name = uv__strdup(ent->ifa_name);
if (ent->ifa_addr->sa_family == AF_INET6) {
address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
int i;
for (i = 0; i < count; i++) {
- free(addresses[i].name);
+ uv__free(addresses[i].name);
}
- free(addresses);
+ uv__free(addresses);
}
return -EINVAL;
/* Make a copy of the file name, it outlives this function's scope. */
- pipe_fname = strdup(name);
+ pipe_fname = uv__strdup(name);
if (pipe_fname == NULL)
return -ENOMEM;
uv__close(sockfd);
err_socket:
- free((void*)pipe_fname);
+ uv__free((void*)pipe_fname);
return err;
}
* another thread or process.
*/
unlink(handle->pipe_fname);
- free((void*)handle->pipe_fname);
+ uv__free((void*)handle->pipe_fname);
handle->pipe_fname = NULL;
}
stdio_count = 3;
err = -ENOMEM;
- pipes = malloc(stdio_count * sizeof(*pipes));
+ pipes = uv__malloc(stdio_count * sizeof(*pipes));
if (pipes == NULL)
goto error;
process->pid = pid;
process->exit_cb = options->exit_cb;
- free(pipes);
+ uv__free(pipes);
return exec_errorno;
error:
if (pipes[i][1] != -1)
close(pipes[i][1]);
}
- free(pipes);
+ uv__free(pipes);
}
return err;
/* Add space for the argv pointers. */
size += (argc + 1) * sizeof(char*);
- new_argv = malloc(size);
+ new_argv = uv__malloc(size);
if (new_argv == NULL)
return argv;
args_mem = new_argv;
UV_DESTRUCTOR(static void free_args_mem(void)) {
- free(args_mem); /* Keep valgrind happy. */
+ uv__free(args_mem); /* Keep valgrind happy. */
args_mem = NULL;
}
/* Get and reset stream's events */
events = s->events;
ACCESS_ONCE(int, s->events) = 0;
- uv_sem_post(&s->async_sem);
assert(events != 0);
assert(events == (events & (UV__POLLIN | UV__POLLOUT)));
if ((events & UV__POLLOUT) && uv__io_active(&stream->io_watcher, UV__POLLOUT))
uv__stream_io(stream->loop, &stream->io_watcher, UV__POLLOUT);
+
+ if (stream->flags & UV_CLOSING)
+ return;
+
+ /* NOTE: It is important to do it here, otherwise `select()` might be called
+ * before the actual `uv__read()`, leading to the blocking syscall
+ */
+ uv_sem_post(&s->async_sem);
}
uv__stream_select_t* s;
s = container_of(async, uv__stream_select_t, async);
- free(s);
+ uv__free(s);
}
sread_sz = ROUND_UP(max_fd + 1, sizeof(uint32_t) * NBBY) / NBBY;
swrite_sz = sread_sz;
- s = malloc(sizeof(*s) + sread_sz + swrite_sz);
+ s = uv__malloc(sizeof(*s) + sread_sz + swrite_sz);
if (s == NULL) {
err = -ENOMEM;
goto failed_malloc;
return err;
failed_async_init:
- free(s);
+ uv__free(s);
failed_malloc:
uv__close(fds[0]);
/* All read, free */
assert(queued_fds->offset > 0);
if (--queued_fds->offset == 0) {
- free(queued_fds);
+ uv__free(queued_fds);
server->queued_fds = NULL;
} else {
/* Shift rest */
*/
if (req->error == 0) {
if (req->bufs != req->bufsml)
- free(req->bufs);
+ uv__free(req->bufs);
req->bufs = NULL;
}
if (req->bufs != NULL) {
stream->write_queue_size -= uv__write_req_size(req);
if (req->bufs != req->bufsml)
- free(req->bufs);
+ uv__free(req->bufs);
req->bufs = NULL;
}
queued_fds = stream->queued_fds;
if (queued_fds == NULL) {
queue_size = 8;
- queued_fds = malloc((queue_size - 1) * sizeof(*queued_fds->fds) +
- sizeof(*queued_fds));
+ queued_fds = uv__malloc((queue_size - 1) * sizeof(*queued_fds->fds) +
+ sizeof(*queued_fds));
if (queued_fds == NULL)
return -ENOMEM;
queued_fds->size = queue_size;
/* Grow */
} else if (queued_fds->size == queued_fds->offset) {
queue_size = queued_fds->size + 8;
- queued_fds = realloc(queued_fds,
- (queue_size - 1) * sizeof(*queued_fds->fds) +
- sizeof(*queued_fds));
+ queued_fds = uv__realloc(queued_fds,
+ (queue_size - 1) * sizeof(*queued_fds->fds) +
+ sizeof(*queued_fds));
/*
* Allocation failure, report back.
req->bufs = req->bufsml;
if (nbufs > ARRAY_SIZE(req->bufsml))
- req->bufs = malloc(nbufs * sizeof(bufs[0]));
+ req->bufs = uv__malloc(nbufs * sizeof(bufs[0]));
if (req->bufs == NULL)
return -ENOMEM;
QUEUE_REMOVE(&req.queue);
uv__req_unregister(stream->loop, &req);
if (req.bufs != req.bufsml)
- free(req.bufs);
+ uv__free(req.bufs);
req.bufs = NULL;
/* Do not poll for writable, if we wasn't before calling this */
queued_fds = handle->queued_fds;
for (i = 0; i < queued_fds->offset; i++)
uv__close(queued_fds->fds[i]);
- free(handle->queued_fds);
+ uv__free(handle->queued_fds);
handle->queued_fds = NULL;
}
}
uv__handle_start(handle);
- handle->path = strdup(path);
+ handle->path = uv__strdup(path);
handle->fd = PORT_UNUSED;
handle->cb = cb;
}
handle->fd = PORT_DELETED;
- free(handle->path);
+ uv__free(handle->path);
handle->path = NULL;
handle->fo.fo_name = NULL;
uv__handle_stop(handle);
lookup_instance++;
}
- *cpu_infos = malloc(lookup_instance * sizeof(**cpu_infos));
+ *cpu_infos = uv__malloc(lookup_instance * sizeof(**cpu_infos));
if (!(*cpu_infos)) {
kstat_close(kc);
return -ENOMEM;
knp = kstat_data_lookup(ksp, (char*) "brand");
assert(knp->data_type == KSTAT_DATA_STRING);
- cpu_info->model = strdup(KSTAT_NAMED_STR_PTR(knp));
+ cpu_info->model = uv__strdup(KSTAT_NAMED_STR_PTR(knp));
}
lookup_instance++;
int i;
for (i = 0; i < count; i++) {
- free(cpu_infos[i].model);
+ uv__free(cpu_infos[i].model);
}
- free(cpu_infos);
+ uv__free(cpu_infos);
}
(*count)++;
}
- *addresses = malloc(*count * sizeof(**addresses));
+ *addresses = uv__malloc(*count * sizeof(**addresses));
if (!(*addresses))
return -ENOMEM;
if (ent->ifa_addr == NULL)
continue;
- address->name = strdup(ent->ifa_name);
+ address->name = uv__strdup(ent->ifa_name);
if (ent->ifa_addr->sa_family == AF_INET6) {
address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
int i;
for (i = 0; i < count; i++) {
- free(addresses[i].name);
+ uv__free(addresses[i].name);
}
- free(addresses);
+ uv__free(addresses);
}
ctx_p = arg;
ctx = *ctx_p;
- free(ctx_p);
+ uv__free(ctx_p);
ctx.entry(ctx.arg);
return 0;
struct thread_ctx* ctx;
int err;
- ctx = malloc(sizeof(*ctx));
+ ctx = uv__malloc(sizeof(*ctx));
if (ctx == NULL)
return UV_ENOMEM;
err = pthread_create(tid, NULL, uv__thread_start, ctx);
if (err)
- free(ctx);
+ uv__free(ctx);
return -err;
}
uv_udp_send_t* req;
QUEUE* q;
+ assert(!(handle->flags & UV_UDP_PROCESSING));
+ handle->flags |= UV_UDP_PROCESSING;
+
while (!QUEUE_EMPTY(&handle->write_completed_queue)) {
q = QUEUE_HEAD(&handle->write_completed_queue);
QUEUE_REMOVE(q);
handle->send_queue_count--;
if (req->bufs != req->bufsml)
- free(req->bufs);
+ uv__free(req->bufs);
req->bufs = NULL;
if (req->send_cb == NULL)
if (!uv__io_active(&handle->io_watcher, UV__POLLIN))
uv__handle_stop(handle);
}
+
+ handle->flags &= ~UV_UDP_PROCESSING;
}
req->bufs = req->bufsml;
if (nbufs > ARRAY_SIZE(req->bufsml))
- req->bufs = malloc(nbufs * sizeof(bufs[0]));
+ req->bufs = uv__malloc(nbufs * sizeof(bufs[0]));
if (req->bufs == NULL)
return -ENOMEM;
QUEUE_INSERT_TAIL(&handle->write_queue, &req->queue);
uv__handle_start(handle);
- if (empty_queue)
+ if (empty_queue && !(handle->flags & UV_UDP_PROCESSING)) {
uv__udp_sendmsg(handle);
- else
+ } else {
uv__io_start(handle->loop, &handle->io_watcher, UV__POLLOUT);
+ }
return 0;
}
* so hardcode the size of these options on this platform,
* and use the general uv__setsockopt_maybe_char call on other platforms.
*/
-#if defined(__sun)
+#if defined(__sun) || defined(_AIX)
return uv__setsockopt(handle,
IP_TTL,
IPV6_UNICAST_HOPS,
&ttl,
sizeof(ttl));
-#endif /* defined(__sun) */
+#endif /* defined(__sun) || defined(_AIX) */
return uv__setsockopt_maybe_char(handle,
IP_TTL,
* IP_MULTICAST_TTL, so hardcode the size of the option in the IPv6 case,
* and use the general uv__setsockopt_maybe_char call otherwise.
*/
-#if defined(__sun)
+#if defined(__sun) || defined(_AIX)
if (handle->flags & UV_HANDLE_IPV6)
return uv__setsockopt(handle,
IP_MULTICAST_TTL,
IPV6_MULTICAST_HOPS,
&ttl,
sizeof(ttl));
-#endif /* defined(__sun) */
+#endif /* defined(__sun) || defined(_AIX) */
return uv__setsockopt_maybe_char(handle,
IP_MULTICAST_TTL,
* IP_MULTICAST_LOOP, so hardcode the size of the option in the IPv6 case,
* and use the general uv__setsockopt_maybe_char call otherwise.
*/
-#if defined(__sun)
+#if defined(__sun) || defined(_AIX)
if (handle->flags & UV_HANDLE_IPV6)
return uv__setsockopt(handle,
IP_MULTICAST_LOOP,
IPV6_MULTICAST_LOOP,
&on,
sizeof(on));
-#endif /* defined(__sun) */
+#endif /* defined(__sun) || defined(_AIX) */
return uv__setsockopt_maybe_char(handle,
IP_MULTICAST_LOOP,
# include <net/if.h> /* if_nametoindex */
#endif
+
+typedef struct {
+ uv_malloc_func local_malloc;
+ uv_realloc_func local_realloc;
+ uv_calloc_func local_calloc;
+ uv_free_func local_free;
+} uv__allocator_t;
+
+static uv__allocator_t uv__allocator = {
+ malloc,
+ realloc,
+ calloc,
+ free,
+};
+
+char* uv__strdup(const char* s) {
+ size_t len = strlen(s) + 1;
+ char* m = uv__malloc(len);
+ if (m == NULL)
+ return NULL;
+ return memcpy(m, s, len);
+}
+
+char* uv__strndup(const char* s, size_t n) {
+ char* m;
+ size_t len = strlen(s);
+ if (n < len)
+ len = n;
+ m = uv__malloc(len + 1);
+ if (m == NULL)
+ return NULL;
+ m[len] = '\0';
+ return memcpy(m, s, len);
+}
+
+void* uv__malloc(size_t size) {
+ return uv__allocator.local_malloc(size);
+}
+
+void uv__free(void* ptr) {
+ uv__allocator.local_free(ptr);
+}
+
+void* uv__calloc(size_t count, size_t size) {
+ return uv__allocator.local_calloc(count, size);
+}
+
+void* uv__realloc(void* ptr, size_t size) {
+ return uv__allocator.local_realloc(ptr, size);
+}
+
+int uv_replace_allocator(uv_malloc_func malloc_func,
+ uv_realloc_func realloc_func,
+ uv_calloc_func calloc_func,
+ uv_free_func free_func) {
+ if (malloc_func == NULL || realloc_func == NULL ||
+ calloc_func == NULL || free_func == NULL) {
+ return UV_EINVAL;
+ }
+
+ uv__allocator.local_malloc = malloc_func;
+ uv__allocator.local_realloc = realloc_func;
+ uv__allocator.local_calloc = calloc_func;
+ uv__allocator.local_free = free_func;
+
+ return 0;
+}
+
#define XX(uc, lc) case UV_##uc: return sizeof(uv_##lc##_t);
size_t uv_handle_size(uv_handle_type type) {
if (*nbufs > 0 && *nbufs != (unsigned int) req->result)
(*nbufs)--;
for (; *nbufs < (unsigned int) req->result; (*nbufs)++)
- free(dents[*nbufs]);
+ uv__free(dents[*nbufs]);
}
/* Free previous entity */
if (*nbufs > 0)
- free(dents[*nbufs - 1]);
+ uv__free(dents[*nbufs - 1]);
/* End was already reached */
if (*nbufs == (unsigned int) req->result) {
- free(dents);
+ uv__free(dents);
req->ptr = NULL;
return UV_EOF;
}
uv_loop_t* uv_loop_new(void) {
uv_loop_t* loop;
- loop = malloc(sizeof(*loop));
+ loop = uv__malloc(sizeof(*loop));
if (loop == NULL)
return NULL;
if (uv_loop_init(loop)) {
- free(loop);
+ uv__free(loop);
return NULL;
}
(void) err; /* Squelch compiler warnings. */
assert(err == 0);
if (loop != default_loop)
- free(loop);
+ uv__free(loop);
}
} \
while (0)
+
+/* Allocator prototypes */
+void *uv__calloc(size_t count, size_t size);
+char *uv__strdup(const char* s);
+char *uv__strndup(const char* s, size_t n);
+void* uv__malloc(size_t size);
+void uv__free(void* ptr);
+void* uv__realloc(void* ptr, size_t size);
+
#endif /* UV_COMMON_H_ */
if (i == 0) {
if (dir) {
- *dir = (WCHAR*)malloc((MAX_PATH + 1) * sizeof(WCHAR));
+ *dir = (WCHAR*)uv__malloc((MAX_PATH + 1) * sizeof(WCHAR));
if (!*dir) {
- uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
if (!GetCurrentDirectoryW(MAX_PATH, *dir)) {
- free(*dir);
+ uv__free(*dir);
*dir = NULL;
return -1;
}
*file = wcsdup(filename);
} else {
if (dir) {
- *dir = (WCHAR*)malloc((i + 1) * sizeof(WCHAR));
+ *dir = (WCHAR*)uv__malloc((i + 1) * sizeof(WCHAR));
if (!*dir) {
- uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
wcsncpy(*dir, filename, i);
(*dir)[i] = L'\0';
}
- *file = (WCHAR*)malloc((len - i) * sizeof(WCHAR));
+ *file = (WCHAR*)uv__malloc((len - i) * sizeof(WCHAR));
if (!*file) {
- uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
wcsncpy(*file, filename + i + 1, len - i - 1);
(*file)[len - i - 1] = L'\0';
return UV_EINVAL;
handle->cb = cb;
- handle->path = strdup(path);
+ handle->path = uv__strdup(path);
if (!handle->path) {
- uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
uv__handle_start(handle);
/* Convert name to UTF16. */
name_size = uv_utf8_to_utf16(path, NULL, 0) * sizeof(WCHAR);
- pathw = (WCHAR*)malloc(name_size);
+ pathw = (WCHAR*)uv__malloc(name_size);
if (!pathw) {
- uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
if (!uv_utf8_to_utf16(path, pathw,
}
dir_to_watch = dir;
- free(pathw);
+ uv__free(pathw);
pathw = NULL;
}
NULL);
if (dir) {
- free(dir);
+ uv__free(dir);
dir = NULL;
}
}
if (!handle->buffer) {
- handle->buffer = (char*)_aligned_malloc(uv_directory_watcher_buffer_size,
- sizeof(DWORD));
+ handle->buffer = (char*)uv__malloc(uv_directory_watcher_buffer_size);
}
if (!handle->buffer) {
- uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
memset(&(handle->req.u.io.overlapped), 0,
error:
if (handle->path) {
- free(handle->path);
+ uv__free(handle->path);
handle->path = NULL;
}
if (handle->filew) {
- free(handle->filew);
+ uv__free(handle->filew);
handle->filew = NULL;
}
if (handle->short_filew) {
- free(handle->short_filew);
+ uv__free(handle->short_filew);
handle->short_filew = NULL;
}
- free(pathw);
+ uv__free(pathw);
if (handle->dir_handle != INVALID_HANDLE_VALUE) {
CloseHandle(handle->dir_handle);
}
if (handle->buffer) {
- _aligned_free(handle->buffer);
+ uv__free(handle->buffer);
handle->buffer = NULL;
}
uv__handle_stop(handle);
if (handle->filew) {
- free(handle->filew);
+ uv__free(handle->filew);
handle->filew = NULL;
}
if (handle->short_filew) {
- free(handle->short_filew);
+ uv__free(handle->short_filew);
handle->short_filew = NULL;
}
if (handle->path) {
- free(handle->path);
+ uv__free(handle->path);
handle->path = NULL;
}
if (handle->dirw) {
- free(handle->dirw);
+ uv__free(handle->dirw);
handle->dirw = NULL;
}
size = wcslen(handle->dirw) +
file_info->FileNameLength / sizeof(WCHAR) + 2;
- filenamew = (WCHAR*)malloc(size * sizeof(WCHAR));
+ filenamew = (WCHAR*)uv__malloc(size * sizeof(WCHAR));
if (!filenamew) {
- uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
_snwprintf(filenamew, size, L"%s\\%.*s", handle->dirw,
size = GetLongPathNameW(filenamew, NULL, 0);
if (size) {
- long_filenamew = (WCHAR*)malloc(size * sizeof(WCHAR));
+ long_filenamew = (WCHAR*)uv__malloc(size * sizeof(WCHAR));
if (!long_filenamew) {
- uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
size = GetLongPathNameW(filenamew, long_filenamew, size);
if (size) {
long_filenamew[size] = '\0';
} else {
- free(long_filenamew);
+ uv__free(long_filenamew);
long_filenamew = NULL;
}
}
- free(filenamew);
+ uv__free(filenamew);
if (long_filenamew) {
/* Get the file name out of the long path. */
result = uv_split_path(long_filenamew, NULL, &filenamew);
- free(long_filenamew);
+ uv__free(long_filenamew);
if (result == 0) {
long_filenamew = filenamew;
NULL,
0);
if (size) {
- filename = (char*)malloc(size + 1);
+ filename = (char*)uv__malloc(size + 1);
if (!filename) {
- uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
size = uv_utf16_to_utf8(filenamew,
if (size) {
filename[size] = '\0';
} else {
- free(filename);
+ uv__free(filename);
filename = NULL;
}
}
break;
}
- free(filename);
+ uv__free(filename);
filename = NULL;
- free(long_filenamew);
+ uv__free(long_filenamew);
long_filenamew = NULL;
}
assert(!(handle->flags & UV_HANDLE_CLOSED));
if (handle->buffer) {
- _aligned_free(handle->buffer);
+ uv__free(handle->buffer);
handle->buffer = NULL;
}
return 0;
}
- buf = (char*) malloc(buf_sz);
+ buf = (char*) uv__malloc(buf_sz);
if (buf == NULL) {
return ERROR_OUTOFMEMORY;
}
/* If requested, allocate memory and convert to UTF8. */
if (target_ptr != NULL) {
int r;
- target = (char*) malloc(target_len + 1);
+ target = (char*) uv__malloc(target_len + 1);
if (target == NULL) {
SetLastError(ERROR_OUTOFMEMORY);
return -1;
size_t new_dirents_size =
dirents_size == 0 ? dirents_initial_size : dirents_size << 1;
uv__dirent_t** new_dirents =
- realloc(dirents, new_dirents_size * sizeof *dirents);
+ uv__realloc(dirents, new_dirents_size * sizeof *dirents);
if (new_dirents == NULL)
goto out_of_memory_error;
* includes room for the first character of the filename, but `utf8_len`
* doesn't count the NULL terminator at this point.
*/
- dirent = malloc(sizeof *dirent + utf8_len);
+ dirent = uv__malloc(sizeof *dirent + utf8_len);
if (dirent == NULL)
goto out_of_memory_error;
if (dir_handle != INVALID_HANDLE_VALUE)
CloseHandle(dir_handle);
while (dirents_used > 0)
- free(dirents[--dirents_used]);
+ uv__free(dirents[--dirents_used]);
if (dirents != NULL)
- free(dirents);
+ uv__free(dirents);
}
size_t buf_size = length < max_buf_size ? length : max_buf_size;
int n, result = 0;
int64_t result_offset = 0;
- char* buf = (char*) malloc(buf_size);
+ char* buf = (char*) uv__malloc(buf_size);
if (!buf) {
- uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
if (offset != -1) {
}
}
- free(buf);
+ uv__free(buf);
SET_REQ_RESULT(req, result);
}
2 * (target_len + 2) * sizeof(WCHAR);
/* Allocate the buffer */
- buffer = (REPARSE_DATA_BUFFER*)malloc(needed_buf_size);
+ buffer = (REPARSE_DATA_BUFFER*)uv__malloc(needed_buf_size);
if (!buffer) {
- uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
/* Grab a pointer to the part of the buffer where filenames go */
/* Clean up */
CloseHandle(handle);
- free(buffer);
+ uv__free(buffer);
SET_REQ_RESULT(req, 0);
return;
error:
- free(buffer);
+ uv__free(buffer);
if (handle != INVALID_HANDLE_VALUE) {
CloseHandle(handle);
return;
if (req->flags & UV_FS_FREE_PATHS)
- free(req->file.pathw);
+ uv__free(req->file.pathw);
if (req->flags & UV_FS_FREE_PTR)
- free(req->ptr);
+ uv__free(req->ptr);
req->path = NULL;
req->file.pathw = NULL;
req->fs.info.nbufs = nbufs;
req->fs.info.bufs = req->fs.info.bufsml;
if (nbufs > ARRAY_SIZE(req->fs.info.bufsml))
- req->fs.info.bufs = malloc(nbufs * sizeof(*bufs));
+ req->fs.info.bufs = uv__malloc(nbufs * sizeof(*bufs));
if (req->fs.info.bufs == NULL)
return UV_ENOMEM;
req->fs.info.nbufs = nbufs;
req->fs.info.bufs = req->fs.info.bufsml;
if (nbufs > ARRAY_SIZE(req->fs.info.bufsml))
- req->fs.info.bufs = malloc(nbufs * sizeof(*bufs));
+ req->fs.info.bufs = uv__malloc(nbufs * sizeof(*bufs));
if (req->fs.info.bufs == NULL)
return UV_ENOMEM;
/* release input parameter memory */
if (req->alloc != NULL) {
- free(req->alloc);
+ uv__free(req->alloc);
req->alloc = NULL;
}
}
/* allocate memory for addrinfo results */
- alloc_ptr = (char*)malloc(addrinfo_len);
+ alloc_ptr = (char*)uv__malloc(addrinfo_len);
/* do conversions */
if (alloc_ptr != NULL) {
/* release copied result memory */
if (alloc_ptr != NULL) {
- free(alloc_ptr);
+ uv__free(alloc_ptr);
}
}
}
/* allocate memory for inputs, and partition it as needed */
- alloc_ptr = (char*)malloc(nodesize + servicesize + hintssize);
+ alloc_ptr = (char*)uv__malloc(nodesize + servicesize + hintssize);
if (!alloc_ptr) {
err = WSAENOBUFS;
goto error;
error:
if (req != NULL && req->alloc != NULL) {
- free(req->alloc);
+ uv__free(req->alloc);
}
return uv_translate_sys_error(err);
}
&item->socket_info_ex.socket_info,
0,
WSA_FLAG_OVERLAPPED);
- free(item);
+ uv__free(item);
if (socket != INVALID_SOCKET)
closesocket(socket);
if (handle->flags & UV_HANDLE_PIPESERVER) {
assert(handle->pipe.serv.accept_reqs);
- free(handle->pipe.serv.accept_reqs);
+ uv__free(handle->pipe.serv.accept_reqs);
handle->pipe.serv.accept_reqs = NULL;
}
}
handle->pipe.serv.accept_reqs = (uv_pipe_accept_t*)
- malloc(sizeof(uv_pipe_accept_t) * handle->pipe.serv.pending_instances);
+ uv__malloc(sizeof(uv_pipe_accept_t) * handle->pipe.serv.pending_instances);
if (!handle->pipe.serv.accept_reqs) {
- uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
for (i = 0; i < handle->pipe.serv.pending_instances; i++) {
/* Convert name to UTF16. */
nameSize = uv_utf8_to_utf16(name, NULL, 0) * sizeof(WCHAR);
- handle->name = (WCHAR*)malloc(nameSize);
+ handle->name = (WCHAR*)uv__malloc(nameSize);
if (!handle->name) {
- uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
if (!uv_utf8_to_utf16(name, handle->name, nameSize / sizeof(WCHAR))) {
error:
if (handle->name) {
- free(handle->name);
+ uv__free(handle->name);
handle->name = NULL;
}
/* Convert name to UTF16. */
nameSize = uv_utf8_to_utf16(name, NULL, 0) * sizeof(WCHAR);
- handle->name = (WCHAR*)malloc(nameSize);
+ handle->name = (WCHAR*)uv__malloc(nameSize);
if (!handle->name) {
- uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
if (!uv_utf8_to_utf16(name, handle->name, nameSize / sizeof(WCHAR))) {
error:
if (handle->name) {
- free(handle->name);
+ uv__free(handle->name);
handle->name = NULL;
}
uv__pipe_stop_read(handle);
if (handle->name) {
- free(handle->name);
+ uv__free(handle->name);
handle->name = NULL;
}
if (err != 0)
return err;
- free(item);
+ uv__free(item);
} else {
pipe_client = (uv_pipe_t*)client;
if (handle->pipe.conn.ipc_header_write_req.type != UV_WRITE) {
ipc_header_req = (uv_write_t*)&handle->pipe.conn.ipc_header_write_req;
} else {
- ipc_header_req = (uv_write_t*)malloc(sizeof(uv_write_t));
+ ipc_header_req = (uv_write_t*)uv__malloc(sizeof(uv_write_t));
if (!ipc_header_req) {
- uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
}
int tcp_connection) {
uv__ipc_queue_item_t* item;
- item = (uv__ipc_queue_item_t*) malloc(sizeof(*item));
+ item = (uv__ipc_queue_item_t*) uv__malloc(sizeof(*item));
if (item == NULL)
- uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
memcpy(&item->socket_info_ex, info, sizeof(item->socket_info_ex));
item->tcp_connection = tcp_connection;
if (req == &handle->pipe.conn.ipc_header_write_req) {
req->type = UV_UNKNOWN_REQ;
} else {
- free(req);
+ uv__free(req);
}
} else {
if (req->cb) {
assert(pipe->pipe.conn.eof_timer == NULL);
assert(pipe->flags & UV_HANDLE_CONNECTION);
- pipe->pipe.conn.eof_timer = (uv_timer_t*) malloc(sizeof *pipe->pipe.conn.eof_timer);
+ pipe->pipe.conn.eof_timer = (uv_timer_t*) uv__malloc(sizeof *pipe->pipe.conn.eof_timer);
r = uv_timer_init(pipe->loop, pipe->pipe.conn.eof_timer);
assert(r == 0); /* timers can't fail */
static void eof_timer_close_cb(uv_handle_t* handle) {
assert(handle->type == UV_TIMER);
- free(handle);
+ uv__free(handle);
}
FileNameInformation);
if (nt_status == STATUS_BUFFER_OVERFLOW) {
name_size = sizeof(*name_info) + tmp_name_info.FileNameLength;
- name_info = malloc(name_size);
+ name_info = uv__malloc(name_size);
if (!name_info) {
*size = 0;
err = UV_ENOMEM;
goto cleanup;
error:
- free(name_info);
+ uv__free(name_info);
cleanup:
uv__pipe_unpause_read((uv_pipe_t*)handle); /* cast away const warning */
}
/* Allocate the child stdio buffer */
- buffer = (BYTE*) malloc(CHILD_STDIO_SIZE(count));
+ buffer = (BYTE*) uv__malloc(CHILD_STDIO_SIZE(count));
if (buffer == NULL) {
return ERROR_OUTOFMEMORY;
}
}
}
- free(buffer);
+ uv__free(buffer);
}
#include <stdlib.h>
#include <signal.h>
#include <limits.h>
-#include <malloc.h>
#include <wchar.h>
+#include <malloc.h> /* alloca */
#include "uv.h"
#include "internal.h"
return GetLastError();
}
- ws = (WCHAR*) malloc(ws_len * sizeof(WCHAR));
+ ws = (WCHAR*) uv__malloc(ws_len * sizeof(WCHAR));
if (ws == NULL) {
return ERROR_OUTOFMEMORY;
}
}
/* Allocate buffer for output */
- result = result_pos = (WCHAR*)malloc(sizeof(WCHAR) *
+ result = result_pos = (WCHAR*)uv__malloc(sizeof(WCHAR) *
(cwd_len + 1 + dir_len + 1 + name_len + 1 + ext_len + 1));
/* Copy cwd */
return result;
}
- free(result);
+ uv__free(result);
return NULL;
}
dst_len = dst_len * 2 + arg_count * 2;
/* Allocate buffer for the final command line. */
- dst = (WCHAR*) malloc(dst_len * sizeof(WCHAR));
+ dst = (WCHAR*) uv__malloc(dst_len * sizeof(WCHAR));
if (dst == NULL) {
err = ERROR_OUTOFMEMORY;
goto error;
}
/* Allocate temporary working buffer. */
- temp_buffer = (WCHAR*) malloc(temp_buffer_len * sizeof(WCHAR));
+ temp_buffer = (WCHAR*) uv__malloc(temp_buffer_len * sizeof(WCHAR));
if (temp_buffer == NULL) {
err = ERROR_OUTOFMEMORY;
goto error;
*pos++ = *(arg + 1) ? L' ' : L'\0';
}
- free(temp_buffer);
+ uv__free(temp_buffer);
*dst_ptr = dst;
return 0;
error:
- free(dst);
- free(temp_buffer);
+ uv__free(dst);
+ uv__free(temp_buffer);
return err;
}
}
/* second pass: copy to UTF-16 environment block */
- dst_copy = malloc(env_len * sizeof(WCHAR));
+ dst_copy = (WCHAR*)uv__malloc(env_len * sizeof(WCHAR));
if (!dst_copy) {
return ERROR_OUTOFMEMORY;
}
(int) (env_len - (ptr - dst_copy)));
if (len <= 0) {
DWORD err = GetLastError();
- free(dst_copy);
+ uv__free(dst_copy);
return err;
}
*ptr_copy++ = ptr;
}
/* final pass: copy, in sort order, and inserting required variables */
- dst = malloc((1+env_len) * sizeof(WCHAR));
+ dst = uv__malloc((1+env_len) * sizeof(WCHAR));
if (!dst) {
- free(dst_copy);
+ uv__free(dst_copy);
return ERROR_OUTOFMEMORY;
}
assert(env_len == (ptr - dst));
*ptr = L'\0';
- free(dst_copy);
+ uv__free(dst_copy);
*dst_ptr = dst;
return 0;
}
goto done;
}
- cwd = (WCHAR*) malloc(cwd_len * sizeof(WCHAR));
+ cwd = (WCHAR*) uv__malloc(cwd_len * sizeof(WCHAR));
if (cwd == NULL) {
err = ERROR_OUTOFMEMORY;
goto done;
goto done;
}
- alloc_path = (WCHAR*) malloc(path_len * sizeof(WCHAR));
+ alloc_path = (WCHAR*) uv__malloc(path_len * sizeof(WCHAR));
if (alloc_path == NULL) {
err = ERROR_OUTOFMEMORY;
goto done;
/* Cleanup, whether we succeeded or failed. */
done:
- free(application);
- free(application_path);
- free(arguments);
- free(cwd);
- free(env);
- free(alloc_path);
+ uv__free(application);
+ uv__free(application_path);
+ uv__free(arguments);
+ uv__free(cwd);
+ uv__free(env);
+ uv__free(alloc_path);
if (process->child_stdio_buffer != NULL) {
/* Clean up child stdio handles. */
}
}
- free(handle->tcp.serv.accept_reqs);
+ uv__free(handle->tcp.serv.accept_reqs);
handle->tcp.serv.accept_reqs = NULL;
}
if(!handle->tcp.serv.accept_reqs) {
handle->tcp.serv.accept_reqs = (uv_tcp_accept_t*)
- malloc(uv_simultaneous_server_accepts * sizeof(uv_tcp_accept_t));
+ uv__malloc(uv_simultaneous_server_accepts * sizeof(uv_tcp_accept_t));
if (!handle->tcp.serv.accept_reqs) {
- uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
for (i = 0; i < simultaneous_accepts; i++) {
ctx_p = arg;
ctx = *ctx_p;
- free(ctx_p);
+ uv__free(ctx_p);
uv_once(&uv__current_thread_init_guard, uv__init_current_thread_key);
uv_key_set(&uv__current_thread_key, (void*) ctx.self);
int err;
HANDLE thread;
- ctx = malloc(sizeof(*ctx));
+ ctx = uv__malloc(sizeof(*ctx));
if (ctx == NULL)
return UV_ENOMEM;
NULL);
if (thread == NULL) {
err = errno;
- free(ctx);
+ uv__free(ctx);
} else {
err = 0;
*tid = thread;
#include <psapi.h>
#include <tlhelp32.h>
#include <windows.h>
+#include <userenv.h>
/*
InitializeCriticalSection(&process_title_lock);
/* Retrieve high-resolution timer frequency
- * and precompute its reciprocal.
+ * and precompute its reciprocal.
*/
if (QueryPerformanceFrequency(&perf_frequency)) {
hrtime_interval_ = 1.0 / perf_frequency.QuadPart;
utf16_buffer_len = (int) *size_ptr;
}
- utf16_buffer = (WCHAR*) malloc(sizeof(WCHAR) * utf16_buffer_len);
+ utf16_buffer = (WCHAR*) uv__malloc(sizeof(WCHAR) * utf16_buffer_len);
if (!utf16_buffer) {
return UV_ENOMEM;
}
goto error;
}
- free(utf16_buffer);
+ uv__free(utf16_buffer);
/* utf8_len *does* include the terminating null at this point, but the */
/* returned size shouldn't. */
return 0;
error:
- free(utf16_buffer);
+ uv__free(utf16_buffer);
return uv_translate_sys_error(err);
}
}
/* Convert to wide-char string */
- title_w = (WCHAR*)malloc(sizeof(WCHAR) * length);
+ title_w = (WCHAR*)uv__malloc(sizeof(WCHAR) * length);
if (!title_w) {
- uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
length = uv_utf8_to_utf16(title, title_w, length);
}
EnterCriticalSection(&process_title_lock);
- free(process_title);
- process_title = strdup(title);
+ uv__free(process_title);
+ process_title = uv__strdup(title);
LeaveCriticalSection(&process_title_lock);
err = 0;
done:
- free(title_w);
+ uv__free(title_w);
return uv_translate_sys_error(err);
}
}
assert(!process_title);
- process_title = (char*)malloc(length);
+ process_title = (char*)uv__malloc(length);
if (!process_title) {
- uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
/* Do utf16 -> utf8 conversion here */
if (!uv_utf16_to_utf8(title_w, -1, process_title, length)) {
- free(process_title);
+ uv__free(process_title);
return -1;
}
goto internalError;
}
- free(malloced_buffer);
+ uv__free(malloced_buffer);
- buffer = malloced_buffer = (BYTE*) malloc(buffer_size);
+ buffer = malloced_buffer = (BYTE*) uv__malloc(buffer_size);
if (malloced_buffer == NULL) {
*uptime = 0;
return UV_ENOMEM;
uint64_t value = *((uint64_t*) address);
*uptime = (double) (object_type->PerfTime.QuadPart - value) /
(double) object_type->PerfFreq.QuadPart;
- free(malloced_buffer);
+ uv__free(malloced_buffer);
return 0;
}
}
}
/* If we get here, the uptime value was not found. */
- free(malloced_buffer);
+ uv__free(malloced_buffer);
*uptime = 0;
return UV_ENOSYS;
internalError:
- free(malloced_buffer);
+ uv__free(malloced_buffer);
*uptime = 0;
return UV_EIO;
}
GetSystemInfo(&system_info);
cpu_count = system_info.dwNumberOfProcessors;
- cpu_infos = calloc(cpu_count, sizeof *cpu_infos);
+ cpu_infos = uv__calloc(cpu_count, sizeof *cpu_infos);
if (cpu_infos == NULL) {
err = ERROR_OUTOFMEMORY;
goto error;
}
sppi_size = cpu_count * sizeof(*sppi);
- sppi = malloc(sppi_size);
+ sppi = uv__malloc(sppi_size);
if (sppi == NULL) {
err = ERROR_OUTOFMEMORY;
goto error;
assert(len > 0);
/* Allocate 1 extra byte for the null terminator. */
- cpu_info->model = malloc(len + 1);
+ cpu_info->model = uv__malloc(len + 1);
if (cpu_info->model == NULL) {
err = ERROR_OUTOFMEMORY;
goto error;
cpu_info->model[len] = '\0';
}
- free(sppi);
+ uv__free(sppi);
*cpu_count_ptr = cpu_count;
*cpu_infos_ptr = cpu_infos;
error:
/* This is safe because the cpu_infos array is zeroed on allocation. */
for (i = 0; i < cpu_count; i++)
- free(cpu_infos[i].model);
+ uv__free(cpu_infos[i].model);
- free(cpu_infos);
- free(sppi);
+ uv__free(cpu_infos);
+ uv__free(sppi);
return uv_translate_sys_error(err);
}
int i;
for (i = 0; i < count; i++) {
- free(cpu_infos[i].model);
+ uv__free(cpu_infos[i].model);
}
- free(cpu_infos);
+ uv__free(cpu_infos);
}
/* Perform the test. */
return (int) VerifyVersionInfo(
- &osvi,
- VER_MAJORVERSION | VER_MINORVERSION |
+ &osvi,
+ VER_MAJORVERSION | VER_MINORVERSION |
VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
condition_mask);
}
flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST |
GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_PREFIX;
}
-
+
/* Fetch the size of the adapters reported by windows, and then get the */
/* list itself. */
if (r == ERROR_SUCCESS)
break;
- free(win_address_buf);
+ uv__free(win_address_buf);
switch (r) {
case ERROR_BUFFER_OVERFLOW:
/* This happens when win_address_buf is NULL or too small to hold */
/* all adapters. */
- win_address_buf = malloc(win_address_buf_size);
+ win_address_buf = uv__malloc(win_address_buf_size);
if (win_address_buf == NULL)
return UV_ENOMEM;
case ERROR_NO_DATA: {
/* No adapters were found. */
- uv_address_buf = malloc(1);
+ uv_address_buf = uv__malloc(1);
if (uv_address_buf == NULL)
return UV_ENOMEM;
NULL,
FALSE);
if (name_size <= 0) {
- free(win_address_buf);
+ uv__free(win_address_buf);
return uv_translate_sys_error(GetLastError());
}
uv_address_buf_size += name_size;
}
/* Allocate space to store interface data plus adapter names. */
- uv_address_buf = malloc(uv_address_buf_size);
+ uv_address_buf = uv__malloc(uv_address_buf_size);
if (uv_address_buf == NULL) {
- free(win_address_buf);
+ uv__free(win_address_buf);
return UV_ENOMEM;
}
NULL,
FALSE);
if (name_size <= 0) {
- free(win_address_buf);
- free(uv_address_buf);
+ uv__free(win_address_buf);
+ uv__free(uv_address_buf);
return uv_translate_sys_error(GetLastError());
}
prefix->PrefixLength <= prefix_len)
continue;
- if (address_prefix_match(sa->sa_family, sa,
+ if (address_prefix_match(sa->sa_family, sa,
prefix->Address.lpSockaddr, prefix->PrefixLength)) {
prefix_len = prefix->PrefixLength;
}
}
/* If there is no matching prefix information, return a single-host
- * subnet mask (e.g. 255.255.255.255 for IPv4).
+ * subnet mask (e.g. 255.255.255.255 for IPv4).
*/
if (!prefix_len)
prefix_len = (sa->sa_family == AF_INET6) ? 128 : 32;
name_buf += name_size;
}
- free(win_address_buf);
+ uv__free(win_address_buf);
*addresses_ptr = uv_address_buf;
*count_ptr = count;
void uv_free_interface_addresses(uv_interface_address_t* addresses,
int count) {
- free(addresses);
+ uv__free(addresses);
}
return 0;
}
+
+
+int uv_os_homedir(char* buffer, size_t* size) {
+ HANDLE token;
+ wchar_t path[MAX_PATH];
+ DWORD bufsize;
+ size_t len;
+ int r;
+
+ if (buffer == NULL || size == NULL || *size == 0)
+ return UV_EINVAL;
+
+ /* Check if the USERPROFILE environment variable is set first */
+ len = GetEnvironmentVariableW(L"USERPROFILE", path, MAX_PATH);
+
+ if (len == 0) {
+ r = GetLastError();
+ /* Don't return an error if USERPROFILE was not found */
+ if (r != ERROR_ENVVAR_NOT_FOUND)
+ return uv_translate_sys_error(r);
+ } else if (len > MAX_PATH) {
+ /* This should not be possible */
+ return UV_EIO;
+ } else {
+ goto convert_buffer;
+ }
+
+ /* USERPROFILE is not set, so call GetUserProfileDirectoryW() */
+ if (OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token) == 0)
+ return uv_translate_sys_error(GetLastError());
+
+ bufsize = MAX_PATH;
+ if (!GetUserProfileDirectoryW(token, path, &bufsize)) {
+ r = GetLastError();
+ CloseHandle(token);
+
+ /* This should not be possible */
+ if (r == ERROR_INSUFFICIENT_BUFFER)
+ return UV_EIO;
+
+ return uv_translate_sys_error(r);
+ }
+
+ CloseHandle(token);
+
+convert_buffer:
+
+ /* Check how much space we need */
+ bufsize = uv_utf16_to_utf8(path, -1, NULL, 0);
+ if (bufsize == 0) {
+ return uv_translate_sys_error(GetLastError());
+ } else if (bufsize > *size) {
+ *size = bufsize - 1;
+ return UV_ENOBUFS;
+ }
+
+ /* Convert to UTF-8 */
+ bufsize = uv_utf16_to_utf8(path, -1, buffer, *size);
+ if (bufsize == 0)
+ return uv_translate_sys_error(GetLastError());
+
+ *size = bufsize - 1;
+ return 0;
+}
# define inline __inline
# endif
-/* Emulate snprintf() on Windows, _snprintf() doesn't zero-terminate the buffer
+# if defined(_MSC_VER) && _MSC_VER < 1900
+/* Emulate snprintf() on MSVC<2015, _snprintf() doesn't zero-terminate the buffer
* on overflow...
*/
inline int snprintf(char* buf, size_t len, const char* fmt, ...) {
return n;
}
+# endif
#endif
--- /dev/null
+#include "uv.h"
+#include "task.h"
+#include <string.h>
+
+#define PATHMAX 1024
+#define SMALLPATH 1
+
+TEST_IMPL(homedir) {
+ char homedir[PATHMAX];
+ size_t len;
+ char last;
+ int r;
+
+ /* Test the normal case */
+ len = sizeof homedir;
+ homedir[0] = '\0';
+ ASSERT(strlen(homedir) == 0);
+ r = uv_os_homedir(homedir, &len);
+ ASSERT(r == 0);
+ ASSERT(strlen(homedir) == len);
+ ASSERT(len > 0);
+ ASSERT(homedir[len] == '\0');
+
+ if (len > 1) {
+ last = homedir[len - 1];
+#ifdef _WIN32
+ ASSERT(last != '\\');
+#else
+ ASSERT(last != '/');
+#endif
+ }
+
+ /* Test the case where the buffer is too small */
+ len = SMALLPATH;
+ r = uv_os_homedir(homedir, &len);
+ ASSERT(r == UV_ENOBUFS);
+ ASSERT(len > SMALLPATH);
+
+ /* Test invalid inputs */
+ r = uv_os_homedir(NULL, &len);
+ ASSERT(r == UV_EINVAL);
+ r = uv_os_homedir(homedir, NULL);
+ ASSERT(r == UV_EINVAL);
+ len = 0;
+ r = uv_os_homedir(homedir, &len);
+ ASSERT(r == UV_EINVAL);
+
+ return 0;
+}
TEST_DECLARE (pipe_listen_without_bind)
TEST_DECLARE (pipe_connect_bad_name)
TEST_DECLARE (pipe_connect_to_file)
+TEST_DECLARE (pipe_connect_on_prepare)
TEST_DECLARE (pipe_getsockname)
TEST_DECLARE (pipe_getsockname_abstract)
TEST_DECLARE (pipe_getsockname_blocking)
TEST_DECLARE (cwd_and_chdir)
TEST_DECLARE (get_memory)
TEST_DECLARE (handle_fileno)
+TEST_DECLARE (homedir)
TEST_DECLARE (hrtime)
TEST_DECLARE (getaddrinfo_fail)
TEST_DECLARE (getaddrinfo_fail_sync)
TEST_ENTRY (pipe_connect_bad_name)
TEST_ENTRY (pipe_connect_to_file)
+ TEST_ENTRY (pipe_connect_on_prepare)
TEST_ENTRY (pipe_server_close)
#ifndef _WIN32
TEST_ENTRY (handle_fileno)
+ TEST_ENTRY (homedir)
+
TEST_ENTRY (hrtime)
TEST_ENTRY_CUSTOM (getaddrinfo_fail, 0, 0, 10000)
--- /dev/null
+/* Copyright (c) 2015 Saúl Ibarra Corretgé <saghul@gmail.com>.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "task.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+
+#ifdef _WIN32
+# define BAD_PIPENAME "bad-pipe"
+#else
+# define BAD_PIPENAME "/path/to/unix/socket/that/really/should/not/be/there"
+#endif
+
+
+static int close_cb_called = 0;
+static int connect_cb_called = 0;
+
+static uv_pipe_t pipe_handle;
+static uv_prepare_t prepare_handle;
+static uv_connect_t conn_req;
+
+
+static void close_cb(uv_handle_t* handle) {
+ ASSERT(handle != NULL);
+ close_cb_called++;
+}
+
+
+static void connect_cb(uv_connect_t* connect_req, int status) {
+ ASSERT(status == UV_ENOENT);
+ connect_cb_called++;
+ uv_close((uv_handle_t*)&prepare_handle, close_cb);
+ uv_close((uv_handle_t*)&pipe_handle, close_cb);
+}
+
+
+static void prepare_cb(uv_prepare_t* handle) {
+ ASSERT(handle == &prepare_handle);
+ uv_pipe_connect(&conn_req, &pipe_handle, BAD_PIPENAME, connect_cb);
+}
+
+
+TEST_IMPL(pipe_connect_on_prepare) {
+ int r;
+
+ r = uv_pipe_init(uv_default_loop(), &pipe_handle, 0);
+ ASSERT(r == 0);
+
+ r = uv_prepare_init(uv_default_loop(), &prepare_handle);
+ ASSERT(r == 0);
+ r = uv_prepare_start(&prepare_handle, prepare_cb);
+ ASSERT(r == 0);
+
+ r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
+ ASSERT(r == 0);
+
+ ASSERT(close_cb_called == 2);
+ ASSERT(connect_cb_called == 1);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
if (interfaces[i].netmask.netmask4.sin_family == AF_INET) {
uv_ip4_name(&interfaces[i].netmask.netmask4, buffer, sizeof(buffer));
+ printf(" netmask: %s\n", buffer);
} else if (interfaces[i].netmask.netmask4.sin_family == AF_INET6) {
uv_ip6_name(&interfaces[i].netmask.netmask6, buffer, sizeof(buffer));
+ printf(" netmask: %s\n", buffer);
+ } else {
+ printf(" netmask: none\n");
}
-
- printf(" netmask: %s\n", buffer);
}
uv_free_interface_addresses(interfaces, count);
'-liphlpapi',
'-lpsapi',
'-lshell32',
+ '-luserenv',
'-lws2_32'
],
},
'test/test-getnameinfo.c',
'test/test-getsockname.c',
'test/test-handle-fileno.c',
+ 'test/test-homedir.c',
'test/test-hrtime.c',
'test/test-idle.c',
'test/test-ip6-addr.c',
'test/test-ping-pong.c',
'test/test-pipe-bind-error.c',
'test/test-pipe-connect-error.c',
+ 'test/test-pipe-connect-prepare.c',
'test/test-pipe-getsockname.c',
'test/test-pipe-sendmsg.c',
'test/test-pipe-server-close.c',
if defined WindowsSDKDir goto select-target
if defined VCINSTALLDIR goto select-target
+@rem Look for Visual Studio 2015
+if not defined VS140COMNTOOLS goto vc-set-2013
+if not exist "%VS140COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2013
+call "%VS140COMNTOOLS%\..\..\vc\vcvarsall.bat" %vs_toolset%
+set GYP_MSVS_VERSION=2015
+goto select-target
+
+:vc-set-2013
@rem Look for Visual Studio 2013
if not defined VS120COMNTOOLS goto vc-set-2012
if not exist "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2012