From a7cc53067d6113decc6755971358de2cb71e9cda Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Sat, 29 Dec 2012 17:34:41 +0100 Subject: [PATCH] deps: upgrade libuv to 4997738 --- deps/uv/src/unix/core.c | 7 +- deps/uv/src/unix/sunos.c | 2 +- deps/uv/src/win/error.c | 2 + deps/uv/src/win/util.c | 260 +++++++++++++++++++++++------------ deps/uv/test/test-fs-event.c | 30 ++++ deps/uv/test/test-list.h | 2 + 6 files changed, 212 insertions(+), 91 deletions(-) diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index 9f20d04b29..f3636e285a 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -291,7 +291,12 @@ static int uv_getaddrinfo_done(eio_req* req_) { uv_getaddrinfo_t* req = req_->data; struct addrinfo *res = req->res; #if __sun - size_t hostlen = strlen(req->hostname); + size_t hostlen; + + if (req->hostname) + hostlen = strlen(req->hostname); + else + hostlen = 0; #endif req->res = NULL; diff --git a/deps/uv/src/unix/sunos.c b/deps/uv/src/unix/sunos.c index b49e448311..0dbbe72aa5 100644 --- a/deps/uv/src/unix/sunos.c +++ b/deps/uv/src/unix/sunos.c @@ -218,7 +218,7 @@ int uv_fs_event_init(uv_loop_t* loop, void uv__fs_event_close(uv_fs_event_t* handle) { - if (handle->fd == PORT_FIRED) { + if (handle->fd == PORT_FIRED || handle->fd == PORT_LOADED) { port_dissociate(handle->loop->fs_fd, PORT_SOURCE_FILE, (uintptr_t)&handle->fo); } handle->fd = PORT_DELETED; diff --git a/deps/uv/src/win/error.c b/deps/uv/src/win/error.c index 1d2d2513f5..ba33963004 100644 --- a/deps/uv/src/win/error.c +++ b/deps/uv/src/win/error.c @@ -108,6 +108,7 @@ uv_err_code uv_translate_sys_error(int sys_errno) { case WSAECONNRESET: return UV_ECONNRESET; case ERROR_ALREADY_EXISTS: return UV_EEXIST; case ERROR_FILE_EXISTS: return UV_EEXIST; + case ERROR_BUFFER_OVERFLOW: return UV_EFAULT; case WSAEFAULT: return UV_EFAULT; case ERROR_HOST_UNREACHABLE: return UV_EHOSTUNREACH; case WSAEHOSTUNREACH: return UV_EHOSTUNREACH; @@ -124,6 +125,7 @@ uv_err_code uv_translate_sys_error(int sys_errno) { case ERROR_NETWORK_UNREACHABLE: return UV_ENETUNREACH; case WSAENETUNREACH: return UV_ENETUNREACH; case WSAENOBUFS: return UV_ENOBUFS; + case ERROR_NOT_ENOUGH_MEMORY: return UV_ENOMEM; case ERROR_OUTOFMEMORY: return UV_ENOMEM; case ERROR_CANNOT_MAKE: return UV_ENOSPC; case ERROR_DISK_FULL: return UV_ENOSPC; diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c index 49a3adc708..2461adc437 100644 --- a/deps/uv/src/win/util.c +++ b/deps/uv/src/win/util.c @@ -740,109 +740,201 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { } -uv_err_t uv_interface_addresses(uv_interface_address_t** addresses, - int* count) { - unsigned long size = 0; - IP_ADAPTER_ADDRESSES* adapter_addresses; - IP_ADAPTER_ADDRESSES* adapter_address; - uv_interface_address_t* address; - struct sockaddr* sock_addr; - int length; - char* name; - /* Use IP_ADAPTER_UNICAST_ADDRESS_XP to retain backwards compatibility */ - /* with Windows XP */ - IP_ADAPTER_UNICAST_ADDRESS_XP* unicast_address; +uv_err_t uv_interface_addresses(uv_interface_address_t** addresses_ptr, + int* count_ptr) { + IP_ADAPTER_ADDRESSES* win_address_buf; + ULONG win_address_buf_size; + IP_ADAPTER_ADDRESSES* win_address; - if (GetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &size) - != ERROR_BUFFER_OVERFLOW) { - return uv__new_sys_error(GetLastError()); - } + uv_interface_address_t* uv_address_buf; + char* name_buf; + size_t uv_address_buf_size; + uv_interface_address_t* uv_address; - adapter_addresses = (IP_ADAPTER_ADDRESSES*)malloc(size); - if (!adapter_addresses) { - uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); - } + int count; - if (GetAdaptersAddresses(AF_UNSPEC, 0, NULL, adapter_addresses, &size) - != ERROR_SUCCESS) { - return uv__new_sys_error(GetLastError()); - } + /* Fetch the size of the adapters reported by windows, and then get the */ + /* list itself. */ + win_address_buf_size = 0; + win_address_buf = NULL; - /* Count the number of interfaces */ - *count = 0; + for (;;) { + ULONG r; - for (adapter_address = adapter_addresses; - adapter_address != NULL; - adapter_address = adapter_address->Next) { + /* If win_address_buf is 0, then GetAdaptersAddresses will fail with */ + /* ERROR_BUFFER_OVERFLOW, and the required buffer size will be stored in */ + /* win_address_buf_size. */ + r = GetAdaptersAddresses(AF_UNSPEC, + 0, + NULL, + win_address_buf, + &win_address_buf_size); - if (adapter_address->OperStatus != IfOperStatusUp) - continue; + if (r == ERROR_SUCCESS) + break; + + 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); + if (win_address_buf == NULL) + return uv__new_artificial_error(UV_ENOMEM); + + continue; - unicast_address = (IP_ADAPTER_UNICAST_ADDRESS_XP*) - adapter_address->FirstUnicastAddress; + case ERROR_NO_DATA: { + /* No adapters were found. */ + uv_address_buf = malloc(1); + if (uv_address_buf == NULL) + return uv__new_artificial_error(UV_ENOMEM); - while (unicast_address) { - (*count)++; - unicast_address = unicast_address->Next; + *count_ptr = 0; + *addresses_ptr = uv_address_buf; + + return uv_ok_; + } + + case ERROR_ADDRESS_NOT_ASSOCIATED: + return uv__new_artificial_error(UV_EAGAIN); + + case ERROR_INVALID_PARAMETER: + /* MSDN says: + * "This error is returned for any of the following conditions: the + * SizePointer parameter is NULL, the Address parameter is not + * AF_INET, AF_INET6, or AF_UNSPEC, or the address information for + * the parameters requested is greater than ULONG_MAX." + * Since the first two conditions are not met, it must be that the + * adapter data is too big. + */ + return uv__new_artificial_error(UV_ENOBUFS); + + default: + /* Other (unspecified) errors can happen, but we don't have any */ + /* special meaning for them. */ + assert(r != ERROR_SUCCESS); + return uv__new_sys_error(r); } } - *addresses = (uv_interface_address_t*) - malloc(*count * sizeof(uv_interface_address_t)); - if (!(*addresses)) { - uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); + /* Count the number of enabled interfaces and compute how much space is */ + /* needed to store their info. */ + count = 0; + uv_address_buf_size = 0; + + for (win_address = win_address_buf; + win_address != NULL; + win_address = win_address->Next) { + /* Use IP_ADAPTER_UNICAST_ADDRESS_XP to retain backwards compatibility */ + /* with Windows XP */ + IP_ADAPTER_UNICAST_ADDRESS_XP* unicast_address; + int name_size; + + /* Interfaces that are not 'up' should not be reported. Also skip */ + /* interfaces that have no associated unicast address, as to avoid */ + /* allocating space for the name for this interface. */ + if (win_address->OperStatus != IfOperStatusUp || + win_address->FirstUnicastAddress == NULL) + continue; + + /* Compute the size of the interface name. */ + name_size = WideCharToMultiByte(CP_UTF8, + 0, + win_address->FriendlyName, + -1, + NULL, + 0, + NULL, + FALSE); + if (name_size <= 0) { + free(win_address_buf); + return uv__new_sys_error(GetLastError()); + } + uv_address_buf_size += name_size; + + /* Count the number of addresses associated with this interface, and */ + /* compute the size. */ + for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS_XP*) + win_address->FirstUnicastAddress; + unicast_address != NULL; + unicast_address = unicast_address->Next) { + count++; + uv_address_buf_size += sizeof(uv_interface_address_t); + } } - address = *addresses; + /* Allocate space to store interface data plus adapter names. */ + uv_address_buf = malloc(uv_address_buf_size); + if (uv_address_buf == NULL) { + free(win_address_buf); + return uv__new_artificial_error(UV_ENOMEM); + } - for (adapter_address = adapter_addresses; - adapter_address != NULL; - adapter_address = adapter_address->Next) { + /* Compute the start of the uv_interface_address_t array, and the place in */ + /* the buffer where the interface names will be stored. */ + uv_address = uv_address_buf; + name_buf = (char*) (uv_address_buf + count); - if (adapter_address->OperStatus != IfOperStatusUp) + /* Fill out the output buffer. */ + for (win_address = win_address_buf; + win_address != NULL; + win_address = win_address->Next) { + IP_ADAPTER_UNICAST_ADDRESS_XP* unicast_address; + int name_size; + size_t max_name_size; + + if (win_address->OperStatus != IfOperStatusUp || + win_address->FirstUnicastAddress == NULL) continue; - name = NULL; - unicast_address = (IP_ADAPTER_UNICAST_ADDRESS_XP*) - adapter_address->FirstUnicastAddress; + /* Convert the interface name to UTF8. */ + max_name_size = (char*) uv_address_buf + uv_address_buf_size - name_buf; + if (max_name_size > (size_t) INT_MAX) + max_name_size = INT_MAX; + name_size = WideCharToMultiByte(CP_UTF8, + 0, + win_address->FriendlyName, + -1, + name_buf, + (int) max_name_size, + NULL, + FALSE); + if (name_size <= 0) { + free(win_address_buf); + free(uv_address_buf); + return uv__new_sys_error(GetLastError()); + } - while (unicast_address) { - sock_addr = unicast_address->Address.lpSockaddr; - if (sock_addr->sa_family == AF_INET6) { - address->address.address6 = *((struct sockaddr_in6 *)sock_addr); - } else { - address->address.address4 = *((struct sockaddr_in *)sock_addr); - } + /* Add an uv_interface_address_t element for every unicast address. */ + for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS_XP*) + win_address->FirstUnicastAddress; + unicast_address != NULL; + unicast_address = unicast_address->Next) { + struct sockaddr* sa; - address->is_internal = - adapter_address->IfType == IF_TYPE_SOFTWARE_LOOPBACK ? 1 : 0; - - if (!name) { - /* Convert FriendlyName to utf8 */ - length = uv_utf16_to_utf8(adapter_address->FriendlyName, -1, NULL, 0); - if (length) { - name = (char*)malloc(length); - if (!name) { - uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); - } - - if (!uv_utf16_to_utf8(adapter_address->FriendlyName, -1, name, - length)) { - free(name); - name = NULL; - } - } - } + uv_address->name = name_buf; + + sa = unicast_address->Address.lpSockaddr; + if (sa->sa_family == AF_INET6) + uv_address->address.address6 = *((struct sockaddr_in6 *) sa); + else + uv_address->address.address4 = *((struct sockaddr_in *) sa); - assert(name); - address->name = name; + uv_address->is_internal = + (win_address->IfType == IF_TYPE_SOFTWARE_LOOPBACK); - unicast_address = unicast_address->Next; - address++; + uv_address++; } + + name_buf += name_size; } - free(adapter_addresses); + free(win_address_buf); + + *addresses_ptr = uv_address_buf; + *count_ptr = count; return uv_ok_; } @@ -850,15 +942,5 @@ uv_err_t uv_interface_addresses(uv_interface_address_t** addresses, void uv_free_interface_addresses(uv_interface_address_t* addresses, int count) { - int i; - char* freed_name = NULL; - - for (i = 0; i < count; i++) { - if (freed_name != addresses[i].name) { - freed_name = addresses[i].name; - free(freed_name); - } - } - free(addresses); } diff --git a/deps/uv/test/test-fs-event.c b/deps/uv/test/test-fs-event.c index 4d4cfbc31b..47a53bd3ba 100644 --- a/deps/uv/test/test-fs-event.c +++ b/deps/uv/test/test-fs-event.c @@ -294,6 +294,36 @@ TEST_IMPL(fs_event_watch_file_current_dir) { return 0; } +TEST_IMPL(fs_event_no_callback_after_close) { + uv_loop_t* loop = uv_default_loop(); + int r; + + /* Setup */ + remove("watch_dir/file1"); + remove("watch_dir/"); + create_dir(loop, "watch_dir"); + create_file(loop, "watch_dir/file1"); + + r = uv_fs_event_init(loop, + &fs_event, + "watch_dir/file1", + fs_event_cb_file, + 0); + ASSERT(r != -1); + + uv_close((uv_handle_t*)&fs_event, close_cb); + touch_file(loop, "watch_dir/file1"); + uv_run(loop); + + ASSERT(fs_event_cb_called == 0); + ASSERT(close_cb_called == 1); + + /* Cleanup */ + remove("watch_dir/file1"); + remove("watch_dir/"); + + return 0; +} TEST_IMPL(fs_event_no_callback_on_close) { uv_fs_t fs_req; diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index d37725885c..27e9d91c94 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -161,6 +161,7 @@ TEST_DECLARE (fs_event_watch_dir) TEST_DECLARE (fs_event_watch_file) TEST_DECLARE (fs_event_watch_file_twice) TEST_DECLARE (fs_event_watch_file_current_dir) +TEST_DECLARE (fs_event_no_callback_after_close) TEST_DECLARE (fs_event_no_callback_on_close) TEST_DECLARE (fs_event_immediate_close) TEST_DECLARE (fs_event_close_with_pending_event) @@ -401,6 +402,7 @@ TASK_LIST_START TEST_ENTRY (fs_event_watch_file) TEST_ENTRY (fs_event_watch_file_twice) TEST_ENTRY (fs_event_watch_file_current_dir) + TEST_ENTRY (fs_event_no_callback_after_close) TEST_ENTRY (fs_event_no_callback_on_close) TEST_ENTRY (fs_event_immediate_close) TEST_ENTRY (fs_event_close_with_pending_event)