void (*destroy_backend)();
pthread_rwlock_t log_limiter_lock = PTHREAD_RWLOCK_INITIALIZER;
-static pthread_rwlock_t log_destruction_lock = PTHREAD_RWLOCK_INITIALIZER;
static pthread_mutex_t log_construction_lock = PTHREAD_MUTEX_INITIALIZER;
static bool is_initialized = false;
* pointer could be made to point at a null handler instead of a true NULL)
* but giving this guarantee makes everything a lot simpler as it removes
* the risk of something suddenly becoming NULL during processing. */
- if (!pthread_rwlock_rdlock(&log_destruction_lock)) {
- ret = !initialize() || !write_to_log
- ? DLOG_ERROR_NOT_PERMITTED
- : __write_to_log_critical_section(log_id, prio, tag, fmt, ap, check_should_log)
+ ret = !initialize() || !write_to_log
+ ? DLOG_ERROR_NOT_PERMITTED
+ : __write_to_log_critical_section(log_id, prio, tag, fmt, ap, check_should_log)
;
- pthread_rwlock_unlock(&log_destruction_lock);
- } else
- ret = DLOG_ERROR_NOT_PERMITTED;
pthread_setcancelstate(old_cancel_state, NULL);
* @details Finalizes and deallocates the library
* @notes Used directly in tests; brings back the pre-init state
*/
-#ifndef UNIT_TEST
-static
-#endif
void __dlog_fini(void)
{
if (destroy_backend) {
__log_limiter_destroy();
__dynamic_config_destroy();
}
-
-#ifdef UNIT_TEST
-void
-#else
-static void __attribute__((destructor))
-#endif
-__dlog_destroy(void)
-{
- if (!pthread_rwlock_wrlock(&log_destruction_lock))
- __dlog_fini();
-
- /* IMPORTANT! The lock is NEVER RELEASED. This is done ON PURPOSE.
- * The critical section can still be reached in some ways, NONE LEGAL.
- *
- * The first is that the program links the library dynamically and keeps
- * pointers to API functions past dlclose(). This is UNDEFINED BEHAVIOUR
- * and the implementation is NOT REQUIRED to keep the functions in memory
- * AT ALL and doing this COULD HAVE ALREADY CRASHED the program under a
- * different implementation.
- *
- * The second is when linking statically and FAILING TO JOIN threads before
- * exit(). These threads then typically keep running and can access the
- * library interface. However, they WILL DIE ANY MOMENT NOW ANYWAY so
- * getting deadlocked is of no consequence.
- *
- * In theory it would be possible to detect that destruction has already
- * taken place and reinitialize the library to salvage a logging attempt.
- * This is a HORRIBLE IDEA since without a destructor to rely on, either
- * those RESOURCES WOULD LEAK or we would have to MASSIVELY CONVOLUTE our
- * logic for manual destruction in such cases. */
-}
-