| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871 |
- /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
- #include "uv.h"
- #include "uv-common.h"
- #include <assert.h>
- #include <errno.h>
- #include <stdarg.h>
- #include <stddef.h> /* NULL */
- #include <stdio.h>
- #include <stdlib.h> /* malloc */
- #include <string.h> /* memset */
- #if defined(_WIN32)
- # include <malloc.h> /* malloc */
- #else
- # include <net/if.h> /* if_nametoindex */
- # include <sys/un.h> /* AF_UNIX, sockaddr_un */
- #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) {
- if (size > 0)
- return uv__allocator.local_malloc(size);
- return NULL;
- }
- void uv__free(void* ptr) {
- int saved_errno;
- /* Libuv expects that free() does not clobber errno. The system allocator
- * honors that assumption but custom allocators may not be so careful.
- */
- saved_errno = errno;
- uv__allocator.local_free(ptr);
- errno = saved_errno;
- }
- void* uv__calloc(size_t count, size_t size) {
- return uv__allocator.local_calloc(count, size);
- }
- void* uv__realloc(void* ptr, size_t size) {
- if (size > 0)
- return uv__allocator.local_realloc(ptr, size);
- uv__free(ptr);
- return NULL;
- }
- void* uv__reallocf(void* ptr, size_t size) {
- void* newptr;
- newptr = uv__realloc(ptr, size);
- if (newptr == NULL)
- if (size > 0)
- uv__free(ptr);
- return newptr;
- }
- 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) {
- switch (type) {
- UV_HANDLE_TYPE_MAP(XX)
- default:
- return -1;
- }
- }
- size_t uv_req_size(uv_req_type type) {
- switch(type) {
- UV_REQ_TYPE_MAP(XX)
- default:
- return -1;
- }
- }
- #undef XX
- size_t uv_loop_size(void) {
- return sizeof(uv_loop_t);
- }
- uv_buf_t uv_buf_init(char* base, unsigned int len) {
- uv_buf_t buf;
- buf.base = base;
- buf.len = len;
- return buf;
- }
- static const char* uv__unknown_err_code(int err) {
- char buf[32];
- char* copy;
- snprintf(buf, sizeof(buf), "Unknown system error %d", err);
- copy = uv__strdup(buf);
- return copy != NULL ? copy : "Unknown system error";
- }
- #define UV_ERR_NAME_GEN_R(name, _) \
- case UV_## name: \
- uv__strscpy(buf, #name, buflen); break;
- char* uv_err_name_r(int err, char* buf, size_t buflen) {
- switch (err) {
- UV_ERRNO_MAP(UV_ERR_NAME_GEN_R)
- default: snprintf(buf, buflen, "Unknown system error %d", err);
- }
- return buf;
- }
- #undef UV_ERR_NAME_GEN_R
- #define UV_ERR_NAME_GEN(name, _) case UV_ ## name: return #name;
- const char* uv_err_name(int err) {
- switch (err) {
- UV_ERRNO_MAP(UV_ERR_NAME_GEN)
- }
- return uv__unknown_err_code(err);
- }
- #undef UV_ERR_NAME_GEN
- #define UV_STRERROR_GEN_R(name, msg) \
- case UV_ ## name: \
- snprintf(buf, buflen, "%s", msg); break;
- char* uv_strerror_r(int err, char* buf, size_t buflen) {
- switch (err) {
- UV_ERRNO_MAP(UV_STRERROR_GEN_R)
- default: snprintf(buf, buflen, "Unknown system error %d", err);
- }
- return buf;
- }
- #undef UV_STRERROR_GEN_R
- #define UV_STRERROR_GEN(name, msg) case UV_ ## name: return msg;
- const char* uv_strerror(int err) {
- switch (err) {
- UV_ERRNO_MAP(UV_STRERROR_GEN)
- }
- return uv__unknown_err_code(err);
- }
- #undef UV_STRERROR_GEN
- #if !defined(CMAKE_BOOTSTRAP) || defined(_WIN32)
- int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr) {
- memset(addr, 0, sizeof(*addr));
- addr->sin_family = AF_INET;
- addr->sin_port = htons(port);
- #ifdef SIN6_LEN
- addr->sin_len = sizeof(*addr);
- #endif
- return uv_inet_pton(AF_INET, ip, &(addr->sin_addr.s_addr));
- }
- int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr) {
- char address_part[40];
- size_t address_part_size;
- const char* zone_index;
- memset(addr, 0, sizeof(*addr));
- addr->sin6_family = AF_INET6;
- addr->sin6_port = htons(port);
- #ifdef SIN6_LEN
- addr->sin6_len = sizeof(*addr);
- #endif
- zone_index = strchr(ip, '%');
- if (zone_index != NULL) {
- address_part_size = zone_index - ip;
- if (address_part_size >= sizeof(address_part))
- address_part_size = sizeof(address_part) - 1;
- memcpy(address_part, ip, address_part_size);
- address_part[address_part_size] = '\0';
- ip = address_part;
- zone_index++; /* skip '%' */
- /* NOTE: unknown interface (id=0) is silently ignored */
- #ifdef _WIN32
- addr->sin6_scope_id = atoi(zone_index);
- #else
- addr->sin6_scope_id = if_nametoindex(zone_index);
- #endif
- }
- return uv_inet_pton(AF_INET6, ip, &addr->sin6_addr);
- }
- int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size) {
- return uv_inet_ntop(AF_INET, &src->sin_addr, dst, size);
- }
- int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size) {
- return uv_inet_ntop(AF_INET6, &src->sin6_addr, dst, size);
- }
- int uv_tcp_bind(uv_tcp_t* handle,
- const struct sockaddr* addr,
- unsigned int flags) {
- unsigned int addrlen;
- if (handle->type != UV_TCP)
- return UV_EINVAL;
- if (addr->sa_family == AF_INET)
- addrlen = sizeof(struct sockaddr_in);
- else if (addr->sa_family == AF_INET6)
- addrlen = sizeof(struct sockaddr_in6);
- else
- return UV_EINVAL;
- return uv__tcp_bind(handle, addr, addrlen, flags);
- }
- int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned flags) {
- unsigned extra_flags;
- int domain;
- int rc;
- /* Use the lower 8 bits for the domain. */
- domain = flags & 0xFF;
- if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)
- return UV_EINVAL;
- /* Use the higher bits for extra flags. */
- extra_flags = flags & ~0xFF;
- if (extra_flags & ~UV_UDP_RECVMMSG)
- return UV_EINVAL;
- rc = uv__udp_init_ex(loop, handle, flags, domain);
- if (rc == 0)
- if (extra_flags & UV_UDP_RECVMMSG)
- handle->flags |= UV_HANDLE_UDP_RECVMMSG;
- return rc;
- }
- int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) {
- return uv_udp_init_ex(loop, handle, AF_UNSPEC);
- }
- int uv_udp_bind(uv_udp_t* handle,
- const struct sockaddr* addr,
- unsigned int flags) {
- unsigned int addrlen;
- if (handle->type != UV_UDP)
- return UV_EINVAL;
- if (addr->sa_family == AF_INET)
- addrlen = sizeof(struct sockaddr_in);
- else if (addr->sa_family == AF_INET6)
- addrlen = sizeof(struct sockaddr_in6);
- else
- return UV_EINVAL;
- return uv__udp_bind(handle, addr, addrlen, flags);
- }
- int uv_tcp_connect(uv_connect_t* req,
- uv_tcp_t* handle,
- const struct sockaddr* addr,
- uv_connect_cb cb) {
- unsigned int addrlen;
- if (handle->type != UV_TCP)
- return UV_EINVAL;
- if (addr->sa_family == AF_INET)
- addrlen = sizeof(struct sockaddr_in);
- else if (addr->sa_family == AF_INET6)
- addrlen = sizeof(struct sockaddr_in6);
- else
- return UV_EINVAL;
- return uv__tcp_connect(req, handle, addr, addrlen, cb);
- }
- int uv_udp_connect(uv_udp_t* handle, const struct sockaddr* addr) {
- unsigned int addrlen;
- if (handle->type != UV_UDP)
- return UV_EINVAL;
- /* Disconnect the handle */
- if (addr == NULL) {
- if (!(handle->flags & UV_HANDLE_UDP_CONNECTED))
- return UV_ENOTCONN;
- return uv__udp_disconnect(handle);
- }
- if (addr->sa_family == AF_INET)
- addrlen = sizeof(struct sockaddr_in);
- else if (addr->sa_family == AF_INET6)
- addrlen = sizeof(struct sockaddr_in6);
- else
- return UV_EINVAL;
- if (handle->flags & UV_HANDLE_UDP_CONNECTED)
- return UV_EISCONN;
- return uv__udp_connect(handle, addr, addrlen);
- }
- int uv__udp_is_connected(uv_udp_t* handle) {
- struct sockaddr_storage addr;
- int addrlen;
- if (handle->type != UV_UDP)
- return 0;
- addrlen = sizeof(addr);
- if (uv_udp_getpeername(handle, (struct sockaddr*) &addr, &addrlen) != 0)
- return 0;
- return addrlen > 0;
- }
- int uv__udp_check_before_send(uv_udp_t* handle, const struct sockaddr* addr) {
- unsigned int addrlen;
- if (handle->type != UV_UDP)
- return UV_EINVAL;
- if (addr != NULL && (handle->flags & UV_HANDLE_UDP_CONNECTED))
- return UV_EISCONN;
- if (addr == NULL && !(handle->flags & UV_HANDLE_UDP_CONNECTED))
- return UV_EDESTADDRREQ;
- if (addr != NULL) {
- if (addr->sa_family == AF_INET)
- addrlen = sizeof(struct sockaddr_in);
- else if (addr->sa_family == AF_INET6)
- addrlen = sizeof(struct sockaddr_in6);
- #if defined(AF_UNIX) && !defined(_WIN32)
- else if (addr->sa_family == AF_UNIX)
- addrlen = sizeof(struct sockaddr_un);
- #endif
- else
- return UV_EINVAL;
- } else {
- addrlen = 0;
- }
- return addrlen;
- }
- int uv_udp_send(uv_udp_send_t* req,
- uv_udp_t* handle,
- const uv_buf_t bufs[],
- unsigned int nbufs,
- const struct sockaddr* addr,
- uv_udp_send_cb send_cb) {
- int addrlen;
- addrlen = uv__udp_check_before_send(handle, addr);
- if (addrlen < 0)
- return addrlen;
- return uv__udp_send(req, handle, bufs, nbufs, addr, addrlen, send_cb);
- }
- int uv_udp_try_send(uv_udp_t* handle,
- const uv_buf_t bufs[],
- unsigned int nbufs,
- const struct sockaddr* addr) {
- int addrlen;
- addrlen = uv__udp_check_before_send(handle, addr);
- if (addrlen < 0)
- return addrlen;
- return uv__udp_try_send(handle, bufs, nbufs, addr, addrlen);
- }
- int uv_udp_recv_start(uv_udp_t* handle,
- uv_alloc_cb alloc_cb,
- uv_udp_recv_cb recv_cb) {
- if (handle->type != UV_UDP || alloc_cb == NULL || recv_cb == NULL)
- return UV_EINVAL;
- else
- return uv__udp_recv_start(handle, alloc_cb, recv_cb);
- }
- int uv_udp_recv_stop(uv_udp_t* handle) {
- if (handle->type != UV_UDP)
- return UV_EINVAL;
- else
- return uv__udp_recv_stop(handle);
- }
- #endif
- void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) {
- QUEUE queue;
- QUEUE* q;
- uv_handle_t* h;
- QUEUE_MOVE(&loop->handle_queue, &queue);
- while (!QUEUE_EMPTY(&queue)) {
- q = QUEUE_HEAD(&queue);
- h = QUEUE_DATA(q, uv_handle_t, handle_queue);
- QUEUE_REMOVE(q);
- QUEUE_INSERT_TAIL(&loop->handle_queue, q);
- if (h->flags & UV_HANDLE_INTERNAL) continue;
- walk_cb(h, arg);
- }
- }
- static void uv__print_handles(uv_loop_t* loop, int only_active, FILE* stream) {
- const char* type;
- QUEUE* q;
- uv_handle_t* h;
- if (loop == NULL)
- loop = uv_default_loop();
- QUEUE_FOREACH(q, &loop->handle_queue) {
- h = QUEUE_DATA(q, uv_handle_t, handle_queue);
- if (only_active && !uv__is_active(h))
- continue;
- switch (h->type) {
- #define X(uc, lc) case UV_##uc: type = #lc; break;
- UV_HANDLE_TYPE_MAP(X)
- #undef X
- default: type = "<unknown>";
- }
- fprintf(stream,
- "[%c%c%c] %-8s %p\n",
- "R-"[!(h->flags & UV_HANDLE_REF)],
- "A-"[!(h->flags & UV_HANDLE_ACTIVE)],
- "I-"[!(h->flags & UV_HANDLE_INTERNAL)],
- type,
- (void*)h);
- }
- }
- void uv_print_all_handles(uv_loop_t* loop, FILE* stream) {
- uv__print_handles(loop, 0, stream);
- }
- void uv_print_active_handles(uv_loop_t* loop, FILE* stream) {
- uv__print_handles(loop, 1, stream);
- }
- void uv_ref(uv_handle_t* handle) {
- uv__handle_ref(handle);
- }
- void uv_unref(uv_handle_t* handle) {
- uv__handle_unref(handle);
- }
- int uv_has_ref(const uv_handle_t* handle) {
- return uv__has_ref(handle);
- }
- void uv_stop(uv_loop_t* loop) {
- loop->stop_flag = 1;
- }
- uint64_t uv_now(const uv_loop_t* loop) {
- return loop->time;
- }
- size_t uv__count_bufs(const uv_buf_t bufs[], unsigned int nbufs) {
- unsigned int i;
- size_t bytes;
- bytes = 0;
- for (i = 0; i < nbufs; i++)
- bytes += (size_t) bufs[i].len;
- return bytes;
- }
- int uv_recv_buffer_size(uv_handle_t* handle, int* value) {
- return uv__socket_sockopt(handle, SO_RCVBUF, value);
- }
- int uv_send_buffer_size(uv_handle_t* handle, int *value) {
- return uv__socket_sockopt(handle, SO_SNDBUF, value);
- }
- int uv_fs_event_getpath(uv_fs_event_t* handle, char* buffer, size_t* size) {
- size_t required_len;
- if (!uv__is_active(handle)) {
- *size = 0;
- return UV_EINVAL;
- }
- required_len = strlen(handle->path);
- if (required_len >= *size) {
- *size = required_len + 1;
- return UV_ENOBUFS;
- }
- memcpy(buffer, handle->path, required_len);
- *size = required_len;
- buffer[required_len] = '\0';
- return 0;
- }
- /* The windows implementation does not have the same structure layout as
- * the unix implementation (nbufs is not directly inside req but is
- * contained in a nested union/struct) so this function locates it.
- */
- static unsigned int* uv__get_nbufs(uv_fs_t* req) {
- #ifdef _WIN32
- return &req->fs.info.nbufs;
- #else
- return &req->nbufs;
- #endif
- }
- /* uv_fs_scandir() uses the system allocator to allocate memory on non-Windows
- * systems. So, the memory should be released using free(). On Windows,
- * uv__malloc() is used, so use uv__free() to free memory.
- */
- #ifdef _WIN32
- # define uv__fs_scandir_free uv__free
- #else
- # define uv__fs_scandir_free free
- #endif
- void uv__fs_scandir_cleanup(uv_fs_t* req) {
- uv__dirent_t** dents;
- unsigned int* nbufs = uv__get_nbufs(req);
- dents = req->ptr;
- if (*nbufs > 0 && *nbufs != (unsigned int) req->result)
- (*nbufs)--;
- for (; *nbufs < (unsigned int) req->result; (*nbufs)++)
- uv__fs_scandir_free(dents[*nbufs]);
- uv__fs_scandir_free(req->ptr);
- req->ptr = NULL;
- }
- int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) {
- uv__dirent_t** dents;
- uv__dirent_t* dent;
- unsigned int* nbufs;
- /* Check to see if req passed */
- if (req->result < 0)
- return req->result;
- /* Ptr will be null if req was canceled or no files found */
- if (!req->ptr)
- return UV_EOF;
- nbufs = uv__get_nbufs(req);
- assert(nbufs);
- dents = req->ptr;
- /* Free previous entity */
- if (*nbufs > 0)
- uv__fs_scandir_free(dents[*nbufs - 1]);
- /* End was already reached */
- if (*nbufs == (unsigned int) req->result) {
- uv__fs_scandir_free(dents);
- req->ptr = NULL;
- return UV_EOF;
- }
- dent = dents[(*nbufs)++];
- ent->name = dent->d_name;
- ent->type = uv__fs_get_dirent_type(dent);
- return 0;
- }
- uv_dirent_type_t uv__fs_get_dirent_type(uv__dirent_t* dent) {
- uv_dirent_type_t type;
- #ifdef HAVE_DIRENT_TYPES
- switch (dent->d_type) {
- case UV__DT_DIR:
- type = UV_DIRENT_DIR;
- break;
- case UV__DT_FILE:
- type = UV_DIRENT_FILE;
- break;
- case UV__DT_LINK:
- type = UV_DIRENT_LINK;
- break;
- case UV__DT_FIFO:
- type = UV_DIRENT_FIFO;
- break;
- case UV__DT_SOCKET:
- type = UV_DIRENT_SOCKET;
- break;
- case UV__DT_CHAR:
- type = UV_DIRENT_CHAR;
- break;
- case UV__DT_BLOCK:
- type = UV_DIRENT_BLOCK;
- break;
- default:
- type = UV_DIRENT_UNKNOWN;
- }
- #else
- type = UV_DIRENT_UNKNOWN;
- #endif
- return type;
- }
- void uv__fs_readdir_cleanup(uv_fs_t* req) {
- uv_dir_t* dir;
- uv_dirent_t* dirents;
- int i;
- if (req->ptr == NULL)
- return;
- dir = req->ptr;
- dirents = dir->dirents;
- req->ptr = NULL;
- if (dirents == NULL)
- return;
- for (i = 0; i < req->result; ++i) {
- uv__free((char*) dirents[i].name);
- dirents[i].name = NULL;
- }
- }
- int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...) {
- va_list ap;
- int err;
- va_start(ap, option);
- /* Any platform-agnostic options should be handled here. */
- err = uv__loop_configure(loop, option, ap);
- va_end(ap);
- return err;
- }
- static uv_loop_t default_loop_struct;
- static uv_loop_t* default_loop_ptr;
- uv_loop_t* uv_default_loop(void) {
- if (default_loop_ptr != NULL)
- return default_loop_ptr;
- if (uv_loop_init(&default_loop_struct))
- return NULL;
- default_loop_ptr = &default_loop_struct;
- return default_loop_ptr;
- }
- uv_loop_t* uv_loop_new(void) {
- uv_loop_t* loop;
- loop = uv__malloc(sizeof(*loop));
- if (loop == NULL)
- return NULL;
- if (uv_loop_init(loop)) {
- uv__free(loop);
- return NULL;
- }
- return loop;
- }
- int uv_loop_close(uv_loop_t* loop) {
- QUEUE* q;
- uv_handle_t* h;
- #ifndef NDEBUG
- void* saved_data;
- #endif
- if (uv__has_active_reqs(loop))
- return UV_EBUSY;
- QUEUE_FOREACH(q, &loop->handle_queue) {
- h = QUEUE_DATA(q, uv_handle_t, handle_queue);
- if (!(h->flags & UV_HANDLE_INTERNAL))
- return UV_EBUSY;
- }
- uv__loop_close(loop);
- #ifndef NDEBUG
- saved_data = loop->data;
- memset(loop, -1, sizeof(*loop));
- loop->data = saved_data;
- #endif
- if (loop == default_loop_ptr)
- default_loop_ptr = NULL;
- return 0;
- }
- void uv_loop_delete(uv_loop_t* loop) {
- uv_loop_t* default_loop;
- int err;
- default_loop = default_loop_ptr;
- err = uv_loop_close(loop);
- (void) err; /* Squelch compiler warnings. */
- assert(err == 0);
- if (loop != default_loop)
- uv__free(loop);
- }
- void uv_os_free_environ(uv_env_item_t* envitems, int count) {
- int i;
- for (i = 0; i < count; i++) {
- uv__free(envitems[i].name);
- }
- uv__free(envitems);
- }
- void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
- int i;
- for (i = 0; i < count; i++)
- uv__free(cpu_infos[i].model);
- uv__free(cpu_infos);
- }
- #ifdef __GNUC__ /* Also covers __clang__ and __INTEL_COMPILER. */
- __attribute__((destructor))
- #endif
- void uv_library_shutdown(void) {
- static int was_shutdown;
- if (was_shutdown)
- return;
- uv__process_title_cleanup();
- uv__signal_cleanup();
- uv__threadpool_cleanup();
- was_shutdown = 1;
- }
|