From da81d62483992548213bc62784e90e1efa081c58 Mon Sep 17 00:00:00 2001 From: Rick van Rein Date: Thu, 2 Dec 2021 13:56:14 +0000 Subject: [PATCH] Additional arpa2comerr_init() function - Not needed when linking a COM-ERR library to a program - May be needed when linking it to a loadable module - In such cases, call arpa2comerr_init() as documented - Be careful about threads and module loading order --- include/arpa2/com_err.h | 21 ++++++++++++++++++++ src/util/CMakeLists.txt | 1 + src/util/comerrinit.c | 43 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 src/util/comerrinit.c diff --git a/include/arpa2/com_err.h b/include/arpa2/com_err.h index 57ffd91..72ea331 100644 --- a/include/arpa2/com_err.h +++ b/include/arpa2/com_err.h @@ -91,6 +91,27 @@ #ifndef ARPA2_COM_ERR_H #define ARPA2_COM_ERR_H + +/** @brief Initialise the COM-ERR list of error codes. + * + * This call is not usually needed, but a COM-ERR library may count on + * the list being set to NULL before getting started and this can fail + * if a program loads a module as a shared object that in turn loads + * the COM-ERR library. In such cases, you may need to explicitly + * initialise. + * + * If you program uses threads, then use pthread_once() or similar to + * avoid calling it concurrently, using + * + * static pthread_once_t a2ce_ctl = PTHREAD_ONCE_INIT; + * pthread_once (*a2ce_ctl, arpa2comerr_init); + * + * It is not a problem if multiple modules call this function in + * sequence, as long as these code fragments are not concurrently + * called, which is not usually what modular programs do. + */ +void arpa2comerr_init (void); + #ifdef __FreeBSD__ #include #else diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index 0adc513..13035f9 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -11,6 +11,7 @@ library_pair( socket.c snoprintf.c cmdparse.c + comerrinit.c EXPORT ARPA2Common ) # TODO: remove when ARPA2CM 0.8.7 is in use diff --git a/src/util/comerrinit.c b/src/util/comerrinit.c new file mode 100644 index 0000000..7d44b9b --- /dev/null +++ b/src/util/comerrinit.c @@ -0,0 +1,43 @@ +/* Initialise the COM-ERR library. + * + * We like to use the more advanced com_err codes, and pass them in errno, + * but there are a few libraries. Some may need to be initialised _if_ + * they are loaded by dlopen() by another program than the binary loader. + * This may happen in a shared library loaded into a modularised server, + * if it does not call linker-setup initialisation code of such modules. + * + * SPDX-License-Identifier: BSD-2-Clause + * SPDX-FileCopyrightText: Copyright 2021 Rick van Rein + */ + + +#include + +#include + + +/* TODO: CMake may flag distinct between COM-ERR variants. */ + +#ifdef __FreeBSD__ + +/* + * arpa2comerr_init() for FreeBSD + */ +#warning "No port for arpa2comerr_init() yet for FreeBSD com_err" + +#else + +/* + * arpa2comerr_init() for Linux and others + */ +void arpa2comerr_init (void) { + extern struct et_list *_et_list; + static bool a2ce_init = false; + if (!a2ce_init) { + a2ce_init = true; + _et_list = NULL; + } +} + +#endif + -- GitLab