1 /* $NetBSD: uv.c,v 1.3 2026/01/29 18:37:55 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 #include <unistd.h> 17 18 #include <isc/mem.h> 19 #include <isc/util.h> 20 #include <isc/uv.h> 21 22 /*% 23 * Convert a libuv error value into an isc_result_t. The 24 * list of supported error values is not complete; new users 25 * of this function should add any expected errors that are 26 * not already there. 27 */ 28 isc_result_t 29 isc__uverr2result(int uverr, bool dolog, const char *file, unsigned int line, 30 const char *func) { 31 switch (uverr) { 32 case 0: 33 return ISC_R_SUCCESS; 34 case UV_ENOTDIR: 35 case UV_ELOOP: 36 case UV_EINVAL: /* XXX sometimes this is not for files */ 37 case UV_ENAMETOOLONG: 38 case UV_EBADF: 39 return ISC_R_INVALIDFILE; 40 case UV_ENOENT: 41 return ISC_R_FILENOTFOUND; 42 case UV_EAGAIN: 43 return ISC_R_NOCONN; 44 case UV_EACCES: 45 case UV_EPERM: 46 return ISC_R_NOPERM; 47 case UV_EEXIST: 48 return ISC_R_FILEEXISTS; 49 case UV_EIO: 50 return ISC_R_IOERROR; 51 case UV_ENOMEM: 52 return ISC_R_NOMEMORY; 53 case UV_ENFILE: 54 case UV_EMFILE: 55 return ISC_R_TOOMANYOPENFILES; 56 case UV_ENOSPC: 57 return ISC_R_DISCFULL; 58 case UV_EPIPE: 59 case UV_ECONNRESET: 60 case UV_ECONNABORTED: 61 return ISC_R_CONNECTIONRESET; 62 case UV_ENOTCONN: 63 return ISC_R_NOTCONNECTED; 64 case UV_ETIMEDOUT: 65 return ISC_R_TIMEDOUT; 66 case UV_ENOBUFS: 67 return ISC_R_NORESOURCES; 68 case UV_EAFNOSUPPORT: 69 return ISC_R_FAMILYNOSUPPORT; 70 case UV_ENETDOWN: 71 return ISC_R_NETDOWN; 72 case UV_EHOSTDOWN: 73 return ISC_R_HOSTDOWN; 74 case UV_ENETUNREACH: 75 return ISC_R_NETUNREACH; 76 case UV_EHOSTUNREACH: 77 return ISC_R_HOSTUNREACH; 78 case UV_EADDRINUSE: 79 return ISC_R_ADDRINUSE; 80 case UV_EADDRNOTAVAIL: 81 return ISC_R_ADDRNOTAVAIL; 82 case UV_ECONNREFUSED: 83 return ISC_R_CONNREFUSED; 84 case UV_ECANCELED: 85 return ISC_R_CANCELED; 86 case UV_EOF: 87 return ISC_R_EOF; 88 case UV_EMSGSIZE: 89 return ISC_R_MAXSIZE; 90 case UV_ENOTSUP: 91 return ISC_R_FAMILYNOSUPPORT; 92 case UV_ENOPROTOOPT: 93 case UV_EPROTONOSUPPORT: 94 return ISC_R_INVALIDPROTO; 95 default: 96 if (dolog) { 97 UNEXPECTED_ERROR("unable to convert libuv error code " 98 "in %s (%s:%d) to isc_result: %d: %s", 99 func, file, line, uverr, 100 uv_strerror(uverr)); 101 } 102 return ISC_R_UNEXPECTED; 103 } 104 } 105 106 #if UV_VERSION_HEX >= UV_VERSION(1, 38, 0) 107 static isc_mem_t *isc__uv_mctx = NULL; 108 109 static void * 110 isc__uv_malloc(size_t size) { 111 return isc_mem_allocate(isc__uv_mctx, size); 112 } 113 114 static void * 115 isc__uv_realloc(void *ptr, size_t size) { 116 return isc_mem_reallocate(isc__uv_mctx, ptr, size); 117 } 118 119 static void * 120 isc__uv_calloc(size_t count, size_t size) { 121 return isc_mem_callocate(isc__uv_mctx, count, size); 122 } 123 124 static void 125 isc__uv_free(void *ptr) { 126 if (ptr == NULL) { 127 return; 128 } 129 isc_mem_free(isc__uv_mctx, ptr); 130 } 131 #endif /* UV_VERSION_HEX >= UV_VERSION(1, 38, 0) */ 132 133 void 134 isc__uv_initialize(void) { 135 /* 136 * Ensure the first 3 file descriptors are open 137 * otherwise, libuv may use one and trigger abort 138 * when closing it. 139 * 140 * See https://github.com/libuv/libuv/pull/4559 141 */ 142 do { 143 int fd = open("/dev/null", O_RDWR, 0); 144 RUNTIME_CHECK(fd >= 0); 145 if (fd > STDERR_FILENO) { 146 close(fd); 147 break; 148 } 149 } while (true); 150 #if UV_VERSION_HEX >= UV_VERSION(1, 38, 0) 151 int r; 152 isc_mem_create(&isc__uv_mctx); 153 isc_mem_setname(isc__uv_mctx, "uv"); 154 isc_mem_setdestroycheck(isc__uv_mctx, false); 155 156 r = uv_replace_allocator(isc__uv_malloc, isc__uv_realloc, 157 isc__uv_calloc, isc__uv_free); 158 UV_RUNTIME_CHECK(uv_replace_allocator, r); 159 #endif /* UV_VERSION_HEX >= UV_VERSION(1, 38, 0) */ 160 } 161 162 void 163 isc__uv_shutdown(void) { 164 #if UV_VERSION_HEX >= UV_VERSION(1, 38, 0) 165 uv_library_shutdown(); 166 isc_mem_destroy(&isc__uv_mctx); 167 #endif /* UV_VERSION_HEX < UV_VERSION(1, 38, 0) */ 168 } 169 170 void 171 isc__uv_setdestroycheck(bool check) { 172 #if UV_VERSION_HEX >= UV_VERSION(1, 38, 0) 173 isc_mem_setdestroycheck(isc__uv_mctx, check); 174 #else 175 UNUSED(check); 176 #endif /* UV_VERSION_HEX >= UV_VERSION(1, 6, 0) */ 177 } 178