Home | History | Annotate | Line # | Download | only in isc
      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