Compare commits

...

7 Commits

Author SHA1 Message Date
Ondřej Surý
4eae3fb9cd Add libuv and openssl memory debugging 2021-12-06 11:59:29 +01:00
Ondřej Surý
3e12d19329 Add simple leak check scripts for mutex and rwlock 2021-12-06 11:23:56 +01:00
Ondřej Surý
67bbfd3ec8 FIXME: Add simple accounting to rwlock.c 2021-12-06 11:23:38 +01:00
Ondřej Surý
d3b1a73325 WIP: Fix PTHREAD_MUTEX_ERRORCHECK use in mutex.c 2021-12-06 11:23:09 +01:00
Ondřej Surý
606e19c286 WIP: Fix rwlock leak in db.c and dlz.c 2021-12-06 11:22:43 +01:00
Ondřej Surý
eeed92e0b9 WIP: Stop leaking mutex in nm workers 2021-12-06 11:10:17 +01:00
Ondřej Surý
6ffcd13bf1 AWIP: dd isc_mutex accounting mode via ISC_MUTEX_DEBUG 2021-12-06 10:58:04 +01:00
11 changed files with 366 additions and 191 deletions

View File

@@ -62,24 +62,9 @@ unsigned int dns_pps = 0U;
static ISC_LIST(dns_dbimplementation_t) implementations;
static isc_rwlock_t implock;
static isc_once_t once = ISC_ONCE_INIT;
static dns_dbimplementation_t rbtimp;
static void
initialize(void) {
isc_rwlock_init(&implock, 0, 0);
rbtimp.name = "rbt";
rbtimp.create = dns_rbtdb_create;
rbtimp.mctx = NULL;
rbtimp.driverarg = NULL;
ISC_LINK_INIT(&rbtimp, link);
ISC_LIST_INIT(implementations);
ISC_LIST_APPEND(implementations, &rbtimp, link);
}
static inline dns_dbimplementation_t *
impfind(const char *name) {
dns_dbimplementation_t *imp;
@@ -104,8 +89,6 @@ dns_db_create(isc_mem_t *mctx, const char *db_type, const dns_name_t *origin,
char *argv[], dns_db_t **dbp) {
dns_dbimplementation_t *impinfo;
RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
/*
* Create a new database using implementation 'db_type'.
*/
@@ -839,8 +822,6 @@ dns_db_register(const char *name, dns_dbcreatefunc_t create, void *driverarg,
REQUIRE(name != NULL);
REQUIRE(dbimp != NULL && *dbimp == NULL);
RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
RWLOCK(&implock, isc_rwlocktype_write);
imp = impfind(name);
if (imp != NULL) {
@@ -869,8 +850,6 @@ dns_db_unregister(dns_dbimplementation_t **dbimp) {
REQUIRE(dbimp != NULL && *dbimp != NULL);
RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
imp = *dbimp;
*dbimp = NULL;
RWLOCK(&implock, isc_rwlocktype_write);
@@ -1104,3 +1083,28 @@ dns_db_setgluecachestats(dns_db_t *db, isc_stats_t *stats) {
return (ISC_R_NOTIMPLEMENTED);
}
void
initialize(void) ISC_CONSTRUCTOR;
void
initialize(void) {
isc_rwlock_init(&implock, 0, 0);
rbtimp.name = "rbt";
rbtimp.create = dns_rbtdb_create;
rbtimp.mctx = NULL;
rbtimp.driverarg = NULL;
ISC_LINK_INIT(&rbtimp, link);
ISC_LIST_INIT(implementations);
ISC_LIST_APPEND(implementations, &rbtimp, link);
}
void
dns__db_shutdown(void) ISC_DESTRUCTOR;
void
dns__db_shutdown(void) {
isc_rwlock_destroy(&implock);
}

View File

@@ -75,13 +75,6 @@
static ISC_LIST(dns_dlzimplementation_t) dlz_implementations;
static isc_rwlock_t dlz_implock;
static isc_once_t once = ISC_ONCE_INIT;
static void
dlz_initialize(void) {
isc_rwlock_init(&dlz_implock, 0, 0);
ISC_LIST_INIT(dlz_implementations);
}
/*%
* Searches the dlz_implementations list for a driver matching name.
@@ -158,12 +151,6 @@ dns_dlzcreate(isc_mem_t *mctx, const char *dlzname, const char *drivername,
isc_result_t result;
dns_dlzdb_t *db = NULL;
/*
* initialize the dlz_implementations list, this is guaranteed
* to only really happen once.
*/
RUNTIME_CHECK(isc_once_do(&once, dlz_initialize) == ISC_R_SUCCESS);
/*
* Performs checks to make sure data is as we expect it to be.
*/
@@ -289,12 +276,6 @@ dns_dlzregister(const char *drivername, const dns_dlzmethods_t *methods,
REQUIRE(mctx != NULL);
REQUIRE(dlzimp != NULL && *dlzimp == NULL);
/*
* initialize the dlz_implementations list, this is guaranteed
* to only really happen once.
*/
RUNTIME_CHECK(isc_once_do(&once, dlz_initialize) == ISC_R_SUCCESS);
/* lock the dlz_implementations list so we can modify it. */
RWLOCK(&dlz_implock, isc_rwlocktype_write);
@@ -374,12 +355,6 @@ dns_dlzunregister(dns_dlzimplementation_t **dlzimp) {
*/
REQUIRE(dlzimp != NULL && *dlzimp != NULL);
/*
* initialize the dlz_implementations list, this is guaranteed
* to only really happen once.
*/
RUNTIME_CHECK(isc_once_do(&once, dlz_initialize) == ISC_R_SUCCESS);
dlz_imp = *dlzimp;
/* lock the dlz_implementations list so we can modify it. */
@@ -532,3 +507,20 @@ dns_dlz_ssumatch(dns_dlzdb_t *dlzdatabase, const dns_name_t *signer,
impl->driverarg, dlzdatabase->dbdata);
return (r);
}
void
dns__dlz_initialize(void) ISC_CONSTRUCTOR;
void
dns__dlz_initialize(void) {
isc_rwlock_init(&dlz_implock, 0, 0);
ISC_LIST_INIT(dlz_implementations);
}
void
dns__dlz_destroy(void) ISC_DESTRUCTOR;
void
dns__dlz_destroy(void) {
isc_rwlock_destroy(&dlz_implock);
}

View File

@@ -21,21 +21,8 @@
ISC_LANG_BEGINDECLS
/*!
* Supply mutex attributes that enable deadlock detection
* (helpful when debugging). This is system dependent and
* currently only supported on NetBSD.
*/
#if ISC_MUTEX_DEBUG && defined(__NetBSD__) && defined(PTHREAD_MUTEX_ERRORCHECK)
extern pthread_mutexattr_t isc__mutex_attrs;
#define ISC__MUTEX_ATTRS &isc__mutex_attrs
#else /* if ISC_MUTEX_DEBUG && defined(__NetBSD__) && \
* defined(PTHREAD_MUTEX_ERRORCHECK) */
#define ISC__MUTEX_ATTRS NULL
#endif /* if ISC_MUTEX_DEBUG && defined(__NetBSD__) && \
* defined(PTHREAD_MUTEX_ERRORCHECK) */
/* XXX We could do fancier error handling... */
/* DROPME */
#define ISC_MUTEX_DEBUG 1
/*!
* Define ISC_MUTEX_PROFILE to turn on profiling of mutexes by line. When
@@ -47,79 +34,79 @@ extern pthread_mutexattr_t isc__mutex_attrs;
#define ISC_MUTEX_PROFILE 0
#endif /* ifndef ISC_MUTEX_PROFILE */
#if ISC_MUTEX_PROFILE
#if defined(ISC_MUTEX_DEBUG)
typedef pthread_mutex_t isc_mutex_t;
#define isc_mutex_init(mp) \
isc_mutex_init_debug((mp), __func__, __FILE__, __LINE__)
#define isc_mutex_destroy(mp) \
isc_mutex_destroy_debug((mp), __func__, __FILE__, __LINE__)
void
isc_mutex_init_debug(isc_mutex_t *mp, const char *func, const char *file,
unsigned int line);
void
isc_mutex_destroy_debug(isc_mutex_t *mp, const char *func, const char *file,
unsigned int line);
#elif ISC_MUTEX_PROFILE
typedef struct isc_mutexstats isc_mutexstats_t;
typedef struct {
pthread_mutex_t mutex; /*%< The actual mutex. */
isc_mutexstats_t *stats; /*%< Mutex statistics. */
} isc_mutex_t;
#else /* if ISC_MUTEX_PROFILE */
typedef pthread_mutex_t isc_mutex_t;
#endif /* if ISC_MUTEX_PROFILE */
#if ISC_MUTEX_PROFILE
#define isc_mutex_init(mp) isc_mutex_init_profile((mp), __FILE__, __LINE__)
#else /* if ISC_MUTEX_PROFILE */
#if ISC_MUTEX_DEBUG && defined(PTHREAD_MUTEX_ERRORCHECK)
#define isc_mutex_init(mp) isc_mutex_init_errcheck((mp))
#else /* if ISC_MUTEX_DEBUG && defined(PTHREAD_MUTEX_ERRORCHECK) */
#define isc_mutex_init(mp) isc__mutex_init((mp), __FILE__, __LINE__)
void
isc__mutex_init(isc_mutex_t *mp, const char *file, unsigned int line);
#endif /* if ISC_MUTEX_DEBUG && defined(PTHREAD_MUTEX_ERRORCHECK) */
#endif /* if ISC_MUTEX_PROFILE */
#if ISC_MUTEX_PROFILE
#define isc_mutex_lock(mp) isc_mutex_lock_profile((mp), __FILE__, __LINE__)
#else /* if ISC_MUTEX_PROFILE */
#define isc_mutex_lock(mp) \
((pthread_mutex_lock((mp)) == 0) ? ISC_R_SUCCESS : ISC_R_UNEXPECTED)
#endif /* if ISC_MUTEX_PROFILE */
#if ISC_MUTEX_PROFILE
#define isc_mutex_unlock(mp) isc_mutex_unlock_profile((mp), __FILE__, __LINE__)
#else /* if ISC_MUTEX_PROFILE */
#define isc_mutex_unlock(mp) \
((pthread_mutex_unlock((mp)) == 0) ? ISC_R_SUCCESS : ISC_R_UNEXPECTED)
#endif /* if ISC_MUTEX_PROFILE */
#if ISC_MUTEX_PROFILE
#define isc_mutex_trylock(mp) \
((pthread_mutex_trylock((&(mp)->mutex)) == 0) ? ISC_R_SUCCESS \
: ISC_R_LOCKBUSY)
#else /* if ISC_MUTEX_PROFILE */
#define isc_mutex_trylock(mp) \
((pthread_mutex_trylock((mp)) == 0) ? ISC_R_SUCCESS : ISC_R_LOCKBUSY)
#endif /* if ISC_MUTEX_PROFILE */
#if ISC_MUTEX_PROFILE
#define isc_mutex_destroy(mp) \
RUNTIME_CHECK(pthread_mutex_destroy((&(mp)->mutex)) == 0)
#else /* if ISC_MUTEX_PROFILE */
#define isc_mutex_destroy(mp) RUNTIME_CHECK(pthread_mutex_destroy((mp)) == 0)
#endif /* if ISC_MUTEX_PROFILE */
#if ISC_MUTEX_PROFILE
#define isc_mutex_stats(fp) isc_mutex_statsprofile(fp);
#else /* if ISC_MUTEX_PROFILE */
#define isc_mutex_stats(fp)
#endif /* if ISC_MUTEX_PROFILE */
#if ISC_MUTEX_PROFILE
void
isc_mutex_init_profile(isc_mutex_t *mp, const char *_file, int _line);
#else
typedef pthread_mutex_t isc_mutex_t;
#define isc_mutex_init(mp) isc__mutex_init((mp), __FILE__, __LINE__)
void
isc__mutex_init(isc_mutex_t *mp, const char *file, unsigned int line);
#define isc_mutex_destroy(mp) RUNTIME_CHECK(pthread_mutex_destroy((mp)) == 0)
#endif
#if ISC_MUTEX_PROFILE
#define isc_mutex_lock(mp) isc_mutex_lock_profile((mp), __FILE__, __LINE__)
isc_result_t
isc_mutex_lock_profile(isc_mutex_t *mp, const char *_file, int _line);
#define isc_mutex_unlock(mp) isc_mutex_unlock_profile((mp), __FILE__, __LINE__)
isc_result_t
isc_mutex_unlock_profile(isc_mutex_t *mp, const char *_file, int _line);
#define isc_mutex_trylock(mp) \
((pthread_mutex_trylock((&(mp)->mutex)) == 0) ? ISC_R_SUCCESS \
: ISC_R_LOCKBUSY)
#define isc_mutex_stats(fp) isc_mutex_statsprofile(fp);
void
isc_mutex_statsprofile(FILE *fp);
#endif /* ISC_MUTEX_PROFILE */
void
isc_mutex_init_errcheck(isc_mutex_t *mp);
#else
#define isc_mutex_lock(mp) \
((pthread_mutex_lock((mp)) == 0) ? ISC_R_SUCCESS : ISC_R_UNEXPECTED)
#define isc_mutex_unlock(mp) \
((pthread_mutex_unlock((mp)) == 0) ? ISC_R_SUCCESS : ISC_R_UNEXPECTED)
#define isc_mutex_trylock(mp) \
((pthread_mutex_trylock((mp)) == 0) ? ISC_R_SUCCESS : ISC_R_LOCKBUSY)
#define isc_mutex_stats(fp)
#endif
ISC_LANG_ENDDECLS

View File

@@ -76,9 +76,14 @@ struct isc_rwlock {
#endif /* USE_PTHREAD_RWLOCK */
#define isc_rwlock_init(rwl, read_quota, write_quota) \
isc__rwlock_init(rwl, read_quota, write_quota, __func__, __FILE__, \
__LINE__)
void
isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
unsigned int write_quota);
isc__rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
unsigned int write_quota, const char *func, const char *file,
unsigned int line);
isc_result_t
isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type);
@@ -95,7 +100,10 @@ isc_rwlock_tryupgrade(isc_rwlock_t *rwl);
void
isc_rwlock_downgrade(isc_rwlock_t *rwl);
#define isc_rwlock_destroy(rwl) \
isc__rwlock_destroy(rwl, __func__, __FILE__, __LINE__)
void
isc_rwlock_destroy(isc_rwlock_t *rwl);
isc__rwlock_destroy(isc_rwlock_t *rwl, const char *func, const char *file,
unsigned int line);
ISC_LANG_ENDDECLS

View File

@@ -11,6 +11,11 @@
/*! \file */
#include <string.h>
#include <uv.h>
#include <openssl/crypto.h>
#include <isc/bind9.h>
#include <isc/mem.h>
#include <isc/os.h>
@@ -19,6 +24,7 @@
#include "config.h"
#include "mem_p.h"
#include "mutex_p.h"
#include "tls_p.h"
#include "trampoline_p.h"
@@ -30,6 +36,100 @@
*** Functions
***/
static isc_mem_t *uv_mem = NULL;
static isc_mem_t *openssl_mem = NULL;
static void *
uv_malloc(size_t size) {
return (isc_mem_allocate(uv_mem, size));
}
static void *
uv_realloc(void *ptr, size_t size) {
return (isc_mem_reallocate(uv_mem, ptr, size));
}
static void *
uv_calloc(size_t count, size_t size) {
/* FIXME: Check for overflow */
void *ptr = isc_mem_allocate(uv_mem, count * size);
memset(ptr, 0, count * size);
return (ptr);
}
static void
uv_free(void *ptr) {
if (ptr == 0) {
return;
}
isc_mem_free(uv_mem, ptr);
}
static void
isc__uv_initialize(void) {
isc_mem_create(&uv_mem);
RUNTIME_CHECK(uv_replace_allocator(uv_malloc, uv_realloc, uv_calloc,
uv_free) == 0);
}
static void
isc__uv_shutdown(void) {
uv_library_shutdown();
isc_mem_destroy(&uv_mem);
}
static void *
openssl_malloc(size_t size, const char *file, int line) {
#if ISC_MEM_TRACKLINES
return (isc__mem_allocate(openssl_mem, size, file, line));
#else
UNUSED(file);
UNUSED(line);
return (isc_mem_allocate(openssl_mem, size));
#endif
}
static void *
openssl_realloc(void *ptr, size_t size, const char *file, int line) {
#if ISC_MEM_TRACKLINES
return (isc__mem_reallocate(openssl_mem, ptr, size, file, line));
#else
UNUSED(file);
UNUSED(line);
return (isc_mem_reallocate(openssl_mem, ptr, size));
#endif
}
static void
openssl_free(void *ptr, const char *file, int line) {
if (ptr == 0) {
return;
}
#if ISC_MEM_TRACKLINES
isc__mem_free(openssl_mem, ptr, file, line);
#else
UNUSED(file);
UNUSED(line);
isc_mem_free(openssl_mem, ptr);
#endif
}
static void
isc__openssl_initialize(void) {
isc_mem_create(&openssl_mem);
RUNTIME_CHECK(CRYPTO_set_mem_functions(openssl_malloc, openssl_realloc,
openssl_free) == 1);
}
static void
isc__openssl_shutdown(void) {
isc_mem_destroy(&openssl_mem);
}
void
isc__initialize(void) ISC_CONSTRUCTOR;
void
@@ -37,7 +137,10 @@ isc__shutdown(void) ISC_DESTRUCTOR;
void
isc__initialize(void) {
isc__mutex_initialize();
isc__mem_initialize();
isc__uv_initialize();
isc__openssl_initialize();
isc__tls_initialize();
isc__trampoline_initialize();
(void)isc_os_ncpus();
@@ -47,5 +150,8 @@ void
isc__shutdown(void) {
isc__trampoline_shutdown();
isc__tls_shutdown();
isc__openssl_shutdown();
isc__uv_shutdown();
isc__mem_shutdown();
isc__mutex_shutdown();
}

View File

@@ -17,6 +17,7 @@
#include <sys/time.h>
#include <time.h>
#include <isc/atomic.h>
#include <isc/mutex.h>
#include <isc/once.h>
#include <isc/print.h>
@@ -24,7 +25,75 @@
#include <isc/string.h>
#include <isc/util.h>
#if ISC_MUTEX_PROFILE
#include "mutex_p.h"
static pthread_mutexattr_t attr;
static isc_once_t init_once = ISC_ONCE_INIT;
static isc_once_t shut_once = ISC_ONCE_INIT;
static atomic_uint_fast32_t mutex_active = ATOMIC_VAR_INIT(0);
static void
mutex_initialize(void) {
RUNTIME_CHECK(pthread_mutexattr_init(&attr) == 0);
#if defined(ISC_MUTEX_DEBUG) && defined(PTHREAD_MUTEX_ERRORCHECK)
RUNTIME_CHECK(pthread_mutexattr_settype(&attr,
PTHREAD_MUTEX_ERRORCHECK) == 0);
#elif defined(HAVE_PTHREAD_MUTEX_ADAPTIVE_NP)
RUNTIME_CHECK(pthread_mutexattr_settype(
&attr, PTHREAD_MUTEX_ADAPTIVE_NP) == 0);
#endif /* HAVE_PTHREAD_MUTEX_ADAPTIVE_NP */
}
void
isc__mutex_initialize(void) {
RUNTIME_CHECK(isc_once_do(&init_once, mutex_initialize) ==
ISC_R_SUCCESS);
}
static void
mutex_shutdown(void) {
REQUIRE(atomic_load_acquire(&mutex_active) == 0);
}
void
isc__mutex_shutdown(void) {
RUNTIME_CHECK(isc_once_do(&shut_once, mutex_shutdown) == ISC_R_SUCCESS);
}
#if ISC_MUTEX_DEBUG
void
isc_mutex_init_debug(isc_mutex_t *mp, const char *func, const char *file,
unsigned int line) {
int err;
err = pthread_mutex_init(mp, &attr);
if (err != 0) {
char strbuf[ISC_STRERRORSIZE];
strerror_r(err, strbuf, sizeof(strbuf));
isc_error_fatal(file, line, "pthread_mutex_init failed: %s",
strbuf);
}
fprintf(stderr, "mutex:init %p func %s file %s line %u\n", mp, func,
file, line);
atomic_fetch_add_relaxed(&mutex_active, 1);
}
void
isc_mutex_destroy_debug(isc_mutex_t *mp, const char *func, const char *file,
unsigned int line) {
atomic_fetch_sub_release(&mutex_active, 1);
fprintf(stderr, "mutex:destroy %p func %s file %s line %u\n", mp, func,
file, line);
pthread_mutex_destroy(mp);
}
#elif ISC_MUTEX_PROFILE
/*@{*/
/*% Operations on timevals; adapted from FreeBSD's sys/time.h */
@@ -83,7 +152,7 @@ void
isc_mutex_init_profile(isc_mutex_t *mp, const char *file, int line) {
int i, err;
err = pthread_mutex_init(&mp->mutex, NULL);
err = pthread_mutex_init(&mp->mutex, &attr);
if (err != 0) {
strerror_r(err, strbuf, sizeof(strbuf));
isc_error_fatal(file, line, "pthread_mutex_init failed: %s",
@@ -216,79 +285,13 @@ isc_mutex_statsprofile(FILE *fp) {
}
}
#endif /* ISC_MUTEX_PROFILE */
#if ISC_MUTEX_DEBUG && defined(PTHREAD_MUTEX_ERRORCHECK)
static bool errcheck_initialized = false;
static pthread_mutexattr_t errcheck;
static isc_once_t once_errcheck = ISC_ONCE_INIT;
static void
initialize_errcheck(void) {
RUNTIME_CHECK(pthread_mutexattr_init(&errcheck) == 0);
RUNTIME_CHECK(pthread_mutexattr_settype(&errcheck,
PTHREAD_MUTEX_ERRORCHECK) == 0);
errcheck_initialized = true;
}
void
isc_mutex_init_errcheck(isc_mutex_t *mp) {
isc_result_t result;
int err;
result = isc_once_do(&once_errcheck, initialize_errcheck);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
err = pthread_mutex_init(mp, &errcheck);
if (err != 0) {
strerror_r(err, strbuf, sizeof(strbuf));
isc_error_fatal(file, line, "pthread_mutex_init failed: %s",
strbuf);
}
}
#endif /* if ISC_MUTEX_DEBUG && defined(PTHREAD_MUTEX_ERRORCHECK) */
#if ISC_MUTEX_DEBUG && defined(__NetBSD__) && defined(PTHREAD_MUTEX_ERRORCHECK)
pthread_mutexattr_t isc__mutex_attrs = {
PTHREAD_MUTEX_ERRORCHECK, /* m_type */
0 /* m_flags, which appears to be unused. */
};
#endif /* if ISC_MUTEX_DEBUG && defined(__NetBSD__) && \
* defined(PTHREAD_MUTEX_ERRORCHECK) */
#if !(ISC_MUTEX_DEBUG && defined(PTHREAD_MUTEX_ERRORCHECK)) && \
!ISC_MUTEX_PROFILE
#ifdef HAVE_PTHREAD_MUTEX_ADAPTIVE_NP
static bool attr_initialized = false;
static pthread_mutexattr_t attr;
static isc_once_t once_attr = ISC_ONCE_INIT;
#endif /* HAVE_PTHREAD_MUTEX_ADAPTIVE_NP */
#ifdef HAVE_PTHREAD_MUTEX_ADAPTIVE_NP
static void
initialize_attr(void) {
RUNTIME_CHECK(pthread_mutexattr_init(&attr) == 0);
RUNTIME_CHECK(pthread_mutexattr_settype(
&attr, PTHREAD_MUTEX_ADAPTIVE_NP) == 0);
attr_initialized = true;
}
#endif /* HAVE_PTHREAD_MUTEX_ADAPTIVE_NP */
#else
void
isc__mutex_init(isc_mutex_t *mp, const char *file, unsigned int line) {
int err;
#ifdef HAVE_PTHREAD_MUTEX_ADAPTIVE_NP
isc_result_t result = ISC_R_SUCCESS;
result = isc_once_do(&once_attr, initialize_attr);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
err = pthread_mutex_init(mp, &attr);
#else /* HAVE_PTHREAD_MUTEX_ADAPTIVE_NP */
err = pthread_mutex_init(mp, ISC__MUTEX_ATTRS);
#endif /* HAVE_PTHREAD_MUTEX_ADAPTIVE_NP */
if (err != 0) {
char strbuf[ISC_STRERRORSIZE];
strerror_r(err, strbuf, sizeof(strbuf));
@@ -296,5 +299,5 @@ isc__mutex_init(isc_mutex_t *mp, const char *file, unsigned int line) {
strbuf);
}
}
#endif /* if !(ISC_MUTEX_DEBUG && defined(PTHREAD_MUTEX_ERRORCHECK)) && \
* !ISC_MUTEX_PROFILE */
#endif

24
lib/isc/mutex_p.h Normal file
View File

@@ -0,0 +1,24 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#pragma once
#include <stdio.h>
#include <isc/mem.h>
/*! \file */
void
isc__mutex_initialize(void);
void
isc__mutex_shutdown(void);

View File

@@ -379,6 +379,7 @@ nm_destroy(isc_nm_t **mgr0) {
isc_mem_put(mgr->mctx, ievent, sizeof(*ievent));
}
isc_condition_destroy(&worker->cond_prio);
isc_mutex_destroy(&worker->lock);
r = uv_loop_close(&worker->loop);
INSIST(r == 0);

View File

@@ -191,8 +191,9 @@ print_lock(const char *operation, isc_rwlock_t *rwl, isc_rwlocktype_t type) {
#endif /* ISC_RWLOCK_TRACE */
void
isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
unsigned int write_quota) {
isc__rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
unsigned int write_quota, const char *func, const char *file,
unsigned int line) {
REQUIRE(rwl != NULL);
/*
@@ -221,13 +222,20 @@ isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
isc_condition_init(&rwl->readable);
isc_condition_init(&rwl->writeable);
fprintf(stderr, "rwlock:init %p func %s file %s line %u\n", rwl, func,
file, line);
rwl->magic = RWLOCK_MAGIC;
}
void
isc_rwlock_destroy(isc_rwlock_t *rwl) {
isc__rwlock_destroy(isc_rwlock_t *rwl, const char *func, const char *file,
unsigned int line) {
REQUIRE(VALID_RWLOCK(rwl));
fprintf(stderr, "rwlock:destroy %p func %s file %s line %u\n", rwl,
func, file, line);
REQUIRE(atomic_load_acquire(&rwl->write_requests) ==
atomic_load_acquire(&rwl->write_completions) &&
atomic_load_acquire(&rwl->cnt_and_flag) == 0 &&

21
util/mutexleak.pl Normal file
View File

@@ -0,0 +1,21 @@
#!/usr/bin/perl
#
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
# Massage the output from ISC_MEM_DEBUG to extract mem_get() calls
# with no corresponding mem_put().
while (<>) {
$gets{$1} = $_ if (/mutex:init (?:0x)?([0-9a-f]+) func/);
delete $gets{$1} if /mutex:destroy (?:0x)?([0-9a-f]+) func/;
}
print join('', values %gets);
exit(0);

21
util/rwlockleak.pl Normal file
View File

@@ -0,0 +1,21 @@
#!/usr/bin/perl
#
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
# Massage the output from ISC_MEM_DEBUG to extract mem_get() calls
# with no corresponding mem_put().
while (<>) {
$gets{$1} = $_ if (/rwlock:init (?:0x)?([0-9a-f]+) func/);
delete $gets{$1} if /rwlock:destroy (?:0x)?([0-9a-f]+) func/;
}
print join('', values %gets);
exit(0);