Compare commits

...

17 Commits

Author SHA1 Message Date
Mark Andrews
d6851e95ae don't call isc_condition_init on same variable 2021-12-10 19:50:30 +11:00
Mark Andrews
893ad49799 cleanup listener_quota 2021-12-10 19:30:52 +11:00
Mark Andrews
df3f934e81 cleanup lasttime_mx 2021-12-10 19:30:46 +11:00
Mark Andrews
26769079fb cleanup reopen_lock 2021-12-10 19:27:36 +11:00
Mark Andrews
3e180d7b9f call isc_app_finish 2021-12-10 19:27:21 +11:00
Mark Andrews
5384028166 cleanup insecure_prefix_lock 2021-12-10 19:26:39 +11:00
Mark Andrews
19a16de33c cleanup wks_lock 2021-12-10 19:23:23 +11:00
Mark Andrews
e287a9dd60 enable pthread init destroy tracking in CI 2021-12-10 19:23:08 +11:00
Mark Andrews
abb1ec7b76 cleanup dlz_implock 2021-12-10 19:22:54 +11:00
Mark Andrews
29da36aaaa cleanup implock 2021-12-10 19:22:41 +11:00
Mark Andrews
dca6f818af use linked lists 2021-12-10 19:22:19 +11:00
Mark Andrews
03a5957ddb call isc_app_finish to cleanup 2021-12-10 19:16:22 +11:00
Mark Andrews
02de040db1 track isc_condition_init file and line 2021-12-10 19:16:04 +11:00
Mark Andrews
533f507bb0 Use linked list to track isc_condition_init/destroy 2021-12-10 19:15:54 +11:00
Michał Kępień
79c86d08ff Enable tracking of pthreads condition variables
Some POSIX threads implementations (e.g. FreeBSD's libthr) allocate
memory on the heap when pthread_cond_init() is called.  Every call to
that function must be accompanied by a corresponding call to
pthread_cond_destroy() or else the memory allocated for the condition
variable will leak.

jemalloc can be used for detecting memory allocations which are not
released by a process when it exits.  Unfortunately, since jemalloc is
also the system allocator on FreeBSD and a special (profiling-enabled)
build of jemalloc is required for memory leak detection, this method
cannot be used for detecting leaked memory allocated by libthr on a
stock FreeBSD installation.

However, libthr's behavior can be emulated on any platform by
implementing alternative versions of libisc functions for creating and
destroying condition variables that allocate memory using malloc() and
release it using free().  This enables using jemalloc for detecting
missing pthread_cond_destroy() calls on any platform on which it works
reliably.

Declare isc_condition_t as a structure containing a 'tracker' attribute
when the newly introduced ISC_TRACK_PTHREADS_OBJECTS preprocessor macro
is set.  Implement wrapper functions, isc_condition_init_track() and
isc_condition_destroy_track(), which take care of allocating and
releasing the "tracker pointer".  Reuse existing condition variable
macros (after renaming them appropriately) for other operations.
2021-12-10 19:14:52 +11:00
Michał Kępień
bcf48747e0 Enable tracking of pthreads mutexes
Some POSIX threads implementations (e.g. FreeBSD's libthr) allocate
memory on the heap when pthread_mutex_init() is called.  Every call to
that function must be accompanied by a corresponding call to
pthread_mutex_destroy() or else the memory allocated for the mutex will
leak.

jemalloc can be used for detecting memory allocations which are not
released by a process when it exits.  Unfortunately, since jemalloc is
also the system allocator on FreeBSD and a special (profiling-enabled)
build of jemalloc is required for memory leak detection, this method
cannot be used for detecting leaked memory allocated by libthr on a
stock FreeBSD installation.

However, libthr's behavior can be emulated on any platform by
implementing alternative versions of libisc functions for creating and
destroying mutexes that allocate memory using malloc() and release it
using free().  This enables using jemalloc for detecting missing
pthread_mutex_destroy() calls on any platform on which it works
reliably.

Declare isc_mutex_t as a structure containing a 'tracker' attribute when
the newly introduced ISC_TRACK_PTHREADS_OBJECTS preprocessor macro is
set.  Implement wrapper functions, isc_mutex_init_track() and
isc_mutex_destroy_track(), which take care of allocating and releasing
the "tracker pointer".  Reuse existing mutex macros (after renaming them
appropriately) for other operations.
2021-12-10 19:14:39 +11:00
Michał Kępień
31e9f6f0d3 Rename the isc__mutex_init() function
Rename isc__mutex_init() to isc_mutex_init_location() in order to better
convey the purpose of this function.
2021-12-10 19:14:24 +11:00
19 changed files with 399 additions and 33 deletions

View File

@@ -984,6 +984,32 @@ unit:clang:asan:
- job: clang:asan
artifacts: true
# Jobs to track pthread init/destroy Debian 10 "buster" (amd64)
gcc:pthread-track:
variables:
CC: gcc
CFLAGS: "${CFLAGS_COMMON} -DISC_TRACK_PTHREADS_OBJECTS"
EXTRA_CONFIGURE: "--with-libidn2 --enable-pthread-rwlock --without-jemalloc"
<<: *fedora_34_amd64_image
<<: *build_job
system:gcc:pthread-track:
variables:
<<: *fedora_34_amd64_image
<<: *system_test_job
needs:
- job: gcc:pthread-track
artifacts: true
unit:gcc:pthread-track:
variables:
<<: *fedora_34_amd64_image
<<: *unit_test_job
needs:
- job: gcc:pthread-track
artifacts: true
# Jobs for TSAN builds on Debian 10 "buster" (amd64)
gcc:tsan:

View File

@@ -1082,6 +1082,7 @@ main(int argc, char **argv) {
fatal("isc_app_run() failed: %s", isc_result_totext(result));
}
isc_app_finish();
isc_task_detach(&rndc_task);
isc_managers_destroy(&netmgr, &taskmgr, NULL);

View File

@@ -253,7 +253,7 @@ sub pid_file_exists {
if (send_signal(0, $pid) == 0) {
# XXX: on windows this is likely to result in a
# false positive, so don't bother reporting the error.
if (!defined($ENV{'CYGWIN'})) {
if (!defined($ENV{'CYGWIN'}) || $ENV{'CYGWIN'} eq "") {
print "I:$test:$server crashed on shutdown\n";
$errors = 1;
}

View File

@@ -563,6 +563,16 @@ initialize_action(void) {
isc_mutex_init(&insecure_prefix_lock);
}
static void
cleanup_insecure_prefix_lock(void) ISC_DESTRUCTOR;
static void
cleanup_insecure_prefix_lock(void) {
RUNTIME_CHECK(isc_once_do(&insecure_prefix_once, initialize_action) ==
ISC_R_SUCCESS);
isc_mutex_destroy(&insecure_prefix_lock);
}
/*
* Called via isc_radix_process() to find IP table nodes that are
* insecure.

View File

@@ -1104,3 +1104,12 @@ dns_db_setgluecachestats(dns_db_t *db, isc_stats_t *stats) {
return (ISC_R_NOTIMPLEMENTED);
}
static void
dns_db_destroyimplock(void) ISC_DESTRUCTOR;
static void
dns_db_destroyimplock(void) {
RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
isc_rwlock_destroy(&implock);
}

View File

@@ -532,3 +532,12 @@ dns_dlz_ssumatch(dns_dlzdb_t *dlzdatabase, const dns_name_t *signer,
impl->driverarg, dlzdatabase->dbdata);
return (r);
}
static void
dns_dlz_destroyimplock(void) ISC_DESTRUCTOR;
static void
dns_dlz_destroyimplock(void) {
RUNTIME_CHECK(isc_once_do(&once, dlz_initialize) == ISC_R_SUCCESS);
isc_rwlock_destroy(&dlz_implock);
}

View File

@@ -504,6 +504,8 @@ destroy(dns_dtenv_t *env) {
isc_stats_detach(&env->stats);
}
isc_mutex_destroy(&env->reopen_lock);
isc_mem_putanddetach(&env->mctx, env, sizeof(*env));
}

View File

@@ -34,12 +34,22 @@
#define RRTYPE_WKS_ATTRIBUTES (0)
static isc_mutex_t wks_lock;
static isc_once_t wks_once = ISC_ONCE_INIT;
static void
init_lock(void) {
isc_mutex_init(&wks_lock);
}
static void
cleanup_wks_lock(void) ISC_DESTRUCTOR;
static void
cleanup_wks_lock(void) {
RUNTIME_CHECK(isc_once_do(&wks_once, init_lock) == ISC_R_SUCCESS);
isc_mutex_destroy(&wks_lock);
}
static bool
mygetprotobyname(const char *name, long *proto) {
struct protoent *pe;
@@ -68,7 +78,6 @@ mygetservbyname(const char *name, const char *proto, long *port) {
static inline isc_result_t
fromtext_in_wks(ARGS_FROMTEXT) {
static isc_once_t once = ISC_ONCE_INIT;
isc_token_t token;
isc_region_t region;
struct in_addr addr;
@@ -92,7 +101,7 @@ fromtext_in_wks(ARGS_FROMTEXT) {
UNUSED(rdclass);
UNUSED(callbacks);
RUNTIME_CHECK(isc_once_do(&once, init_lock) == ISC_R_SUCCESS);
RUNTIME_CHECK(isc_once_do(&wks_once, init_lock) == ISC_R_SUCCESS);
/*
* IPv4 dotted quad.

View File

@@ -102,6 +102,7 @@ cleanup_managers(void) {
if (app_running) {
isc_app_finish();
app_running = false;
}
}
@@ -128,6 +129,7 @@ dns_test_begin(FILE *logfile, bool start_managers) {
if (start_managers) {
CHECK(isc_app_start());
app_running = true;
}
if (debug_mem_record) {
isc_mem_debugging |= ISC_MEM_DEBUGRECORD;

View File

@@ -12,6 +12,7 @@
/*! \file */
#include <errno.h>
#include <unistd.h>
#include <isc/condition.h>
#include <isc/strerr.h>
@@ -19,6 +20,66 @@
#include <isc/time.h>
#include <isc/util.h>
#ifdef ISC_TRACK_PTHREADS_OBJECTS
#include <stdlib.h>
struct isc_condition_tracker {
ISC_LINK(isc_condition_tracker_t) link;
const char *file;
int line;
};
static pthread_mutex_t conditionslock = PTHREAD_MUTEX_INITIALIZER;
static ISC_LIST(isc_condition_tracker_t) conditions = { NULL, NULL };
void
isc_condition_init_track(isc_condition_t *c, const char *file, int line) {
isc__condition_init(&c->cond);
c->tracker = malloc(sizeof(*c->tracker));
INSIST(c->tracker != NULL);
c->tracker->file = file;
c->tracker->line = line;
pthread_mutex_lock(&conditionslock);
ISC_LIST_INITANDAPPEND(conditions, c->tracker, link);
pthread_mutex_unlock(&conditionslock);
}
isc_result_t
isc_condition_destroy_track(isc_condition_t *c) {
INSIST(c->tracker != NULL);
pthread_mutex_lock(&conditionslock);
ISC_LIST_UNLINK(conditions, c->tracker, link);
pthread_mutex_unlock(&conditionslock);
free(c->tracker);
c->tracker = NULL;
return (isc__condition_destroy(&c->cond));
}
void
isc_condition_check_track(void) {
pthread_mutex_lock(&conditionslock);
if (!ISC_LIST_EMPTY(conditions)) {
isc_condition_tracker_t *t;
fprintf(stderr,
"isc_condition_init/isc_condition_destroy mismatch\n");
for (t = ISC_LIST_HEAD(conditions); t != NULL;
t = ISC_LIST_NEXT(t, link)) {
fprintf(stderr, "condition %s:%d\n", t->file, t->line);
}
abort();
}
pthread_mutex_unlock(&conditionslock);
}
#endif
isc_result_t
isc_condition_waituntil(isc_condition_t *c, isc_mutex_t *m, isc_time_t *t) {
int presult;
@@ -50,7 +111,22 @@ isc_condition_waituntil(isc_condition_t *c, isc_mutex_t *m, isc_time_t *t) {
ts.tv_nsec = (long)isc_time_nanoseconds(t);
do {
presult = pthread_cond_timedwait(c, m, &ts);
pthread_cond_t *cond;
pthread_mutex_t *mutex;
#ifdef ISC_TRACK_PTHREADS_OBJECTS
cond = &c->cond;
#else /* ISC_TRACK_PTHREADS_OBJECTS */
cond = c;
#endif /* ISC_TRACK_PTHREADS_OBJECTS */
#ifdef ISC_TRACK_PTHREADS_OBJECTS
mutex = &m->mutex;
#else /* ISC_TRACK_PTHREADS_OBJECTS */
mutex = m;
#endif /* ISC_TRACK_PTHREADS_OBJECTS */
presult = pthread_cond_timedwait(cond, mutex, &ts);
if (presult == 0) {
return (ISC_R_SUCCESS);
}

View File

@@ -23,9 +23,45 @@
#include <isc/string.h>
#include <isc/types.h>
#ifdef ISC_TRACK_PTHREADS_OBJECTS
typedef struct isc_condition_tracker isc_condition_tracker_t;
typedef struct {
pthread_cond_t cond;
isc_condition_tracker_t *tracker;
} isc_condition_t;
void
isc_condition_init_track(isc_condition_t *c, const char *file, int line);
isc_result_t
isc_condition_destroy_track(isc_condition_t *);
void
isc_condition_check_track(void);
#define isc_condition_init(cond) \
isc_condition_init_track(cond, __FILE__, __LINE__)
#define isc_condition_wait(cp, mp) \
isc__condition_wait(&(cp)->cond, &(mp)->mutex)
#define isc_condition_signal(cp) isc__condition_signal(&(cp)->cond)
#define isc_condition_broadcast(cp) isc__condition_broadcast(&(cp)->cond)
#define isc_condition_destroy(cp) isc_condition_destroy_track(cp)
#else /* ISC_TRACK_PTHREADS_OBJECTS */
typedef pthread_cond_t isc_condition_t;
#define isc_condition_init(cond) \
#define isc_condition_init(cond) isc__condition_init(cond)
#define isc_condition_wait(cp, mp) isc__condition_wait(cp, mp)
#define isc_condition_signal(cp) isc__condition_signal(cp)
#define isc_condition_broadcast(cp) isc__condition_broadcast(cp)
#define isc_condition_destroy(cp) isc__condition_destroy(cp)
#endif /* ISC_TRACK_PTHREADS_OBJECTS */
#define isc__condition_init(cond) \
if (pthread_cond_init(cond, NULL) != 0) { \
char isc_condition_strbuf[ISC_STRERRORSIZE]; \
strerror_r(errno, isc_condition_strbuf, \
@@ -35,17 +71,17 @@ typedef pthread_cond_t isc_condition_t;
isc_condition_strbuf); \
}
#define isc_condition_wait(cp, mp) \
#define isc__condition_wait(cp, mp) \
((pthread_cond_wait((cp), (mp)) == 0) ? ISC_R_SUCCESS \
: ISC_R_UNEXPECTED)
#define isc_condition_signal(cp) \
#define isc__condition_signal(cp) \
((pthread_cond_signal((cp)) == 0) ? ISC_R_SUCCESS : ISC_R_UNEXPECTED)
#define isc_condition_broadcast(cp) \
#define isc__condition_broadcast(cp) \
((pthread_cond_broadcast((cp)) == 0) ? ISC_R_SUCCESS : ISC_R_UNEXPECTED)
#define isc_condition_destroy(cp) \
#define isc__condition_destroy(cp) \
((pthread_cond_destroy((cp)) == 0) ? ISC_R_SUCCESS : ISC_R_UNEXPECTED)
ISC_LANG_BEGINDECLS

View File

@@ -21,22 +21,52 @@
ISC_LANG_BEGINDECLS
#ifdef ISC_TRACK_PTHREADS_OBJECTS
typedef struct isc_mutex_tracker isc_mutex_tracker_t;
typedef struct {
pthread_mutex_t mutex;
isc_mutex_tracker_t *tracker;
} isc_mutex_t;
void
isc_mutex_init_track(isc_mutex_t *m, const char *file, int line);
void
isc_mutex_destroy_track(isc_mutex_t *m);
void
isc_mutex_check_track(void);
#define isc_mutex_init(mp) isc_mutex_init_track(mp, __FILE__, __LINE__)
#define isc_mutex_lock(mp) isc__mutex_lock(&(mp)->mutex)
#define isc_mutex_unlock(mp) isc__mutex_unlock(&(mp)->mutex)
#define isc_mutex_trylock(mp) isc__mutex_trylock(&(mp)->mutex)
#define isc_mutex_destroy(mp) isc_mutex_destroy_track(mp)
#else /* ISC_TRACK_PTHREADS_OBJECTS */
typedef pthread_mutex_t isc_mutex_t;
void
isc__mutex_init(isc_mutex_t *mp, const char *file, unsigned int line);
#define isc_mutex_init(mp) isc__mutex_init((mp), __FILE__, __LINE__)
#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)
isc_mutex_init_location(isc_mutex_t *mp, const char *file, unsigned int line);
#define isc_mutex_init(mp) isc_mutex_init_location((mp), __FILE__, __LINE__)
#define isc_mutex_lock(mp) isc__mutex_lock(mp)
#define isc_mutex_unlock(mp) isc__mutex_unlock(mp)
#define isc_mutex_trylock(mp) isc__mutex_trylock(mp)
#define isc_mutex_destroy(mp) RUNTIME_CHECK(pthread_mutex_destroy((mp)) == 0)
#endif /* ISC_TRACK_PTHREADS_OBJECTS */
#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)
ISC_LANG_ENDDECLS

View File

@@ -28,12 +28,22 @@ typedef enum {
isc_rwlocktype_write
} isc_rwlocktype_t;
#ifdef ISC_TRACK_PTHREADS_OBJECTS
typedef struct isc_rwlock_tracker isc_rwlock_tracker_t;
void
isc_rwlock_check_track(void);
#endif
#if USE_PTHREAD_RWLOCK
#include <pthread.h>
struct isc_rwlock {
pthread_rwlock_t rwlock;
atomic_bool downgrade;
#ifdef ISC_TRACK_PTHREADS_OBJECTS
isc_rwlock_tracker_t *tracker;
#endif /* ISC_TRACK_PTHREADS_OBJECTS */
};
#else /* USE_PTHREAD_RWLOCK */
@@ -71,14 +81,19 @@ struct isc_rwlock {
atomic_uint_fast32_t write_granted;
/* Unlocked. */
unsigned int write_quota;
unsigned int write_quota;
#ifdef ISC_TRACK_PTHREADS_OBJECTS
isc_rwlock_tracker_t *tracker;
#endif /* ISC_TRACK_PTHREADS_OBJECTS */
};
#endif /* USE_PTHREAD_RWLOCK */
#define isc_rwlock_init(rwl, read_quota, write_quota) \
isc__rwlock_init(rwl, read_quota, write_quota, __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 *file, int line);
isc_result_t
isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type);

View File

@@ -12,8 +12,10 @@
/*! \file */
#include <isc/bind9.h>
#include <isc/condition.h>
#include <isc/mem.h>
#include <isc/os.h>
#include <isc/rwlock.h>
#include <isc/tls.h>
#include <isc/util.h>
@@ -48,4 +50,9 @@ isc__shutdown(void) {
isc__trampoline_shutdown();
isc__tls_shutdown();
isc__mem_shutdown();
#ifdef ISC_TRACK_PTHREADS_OBJECTS
isc_mutex_check_track();
isc_rwlock_check_track();
isc_condition_check_track();
#endif
}

View File

@@ -24,6 +24,62 @@
#include <isc/string.h>
#include <isc/util.h>
#ifdef ISC_TRACK_PTHREADS_OBJECTS
#include <stdlib.h>
struct isc_mutex_tracker {
ISC_LINK(isc_mutex_tracker_t) link;
const char *file;
int line;
};
static pthread_mutex_t mutexeslock = PTHREAD_MUTEX_INITIALIZER;
static ISC_LIST(isc_mutex_tracker_t) mutexes = { NULL, NULL };
void
isc_mutex_init_track(isc_mutex_t *m, const char *file, int line) {
RUNTIME_CHECK(pthread_mutex_init(&m->mutex, NULL) == 0);
m->tracker = malloc(sizeof(*m->tracker));
INSIST(m->tracker != NULL);
m->tracker->file = file;
m->tracker->line = line;
pthread_mutex_lock(&mutexeslock);
ISC_LIST_INITANDAPPEND(mutexes, m->tracker, link);
pthread_mutex_unlock(&mutexeslock);
}
void
isc_mutex_destroy_track(isc_mutex_t *m) {
INSIST(m->tracker != NULL);
pthread_mutex_lock(&mutexeslock);
ISC_LIST_UNLINK(mutexes, m->tracker, link);
pthread_mutex_unlock(&mutexeslock);
free(m->tracker);
m->tracker = NULL;
RUNTIME_CHECK(pthread_mutex_destroy(&m->mutex) == 0);
}
void
isc_mutex_check_track(void) {
pthread_mutex_lock(&mutexeslock);
if (!ISC_LIST_EMPTY(mutexes)) {
isc_mutex_tracker_t *t;
fprintf(stderr, "isc_mutex_init/isc_mutext_destroy mismatch\n");
for (t = ISC_LIST_HEAD(mutexes); t != NULL;
t = ISC_LIST_NEXT(t, link)) {
fprintf(stderr, "mutex %s:%d\n", t->file, t->line);
}
abort();
}
pthread_mutex_unlock(&mutexeslock);
}
#else /* ISC_TRACK_PTHREADS_OBJECTS */
#ifdef HAVE_PTHREAD_MUTEX_ADAPTIVE_NP
static bool attr_initialized = false;
static pthread_mutexattr_t attr;
@@ -39,7 +95,7 @@ initialize_attr(void) {
#endif /* HAVE_PTHREAD_MUTEX_ADAPTIVE_NP */
void
isc__mutex_init(isc_mutex_t *mp, const char *file, unsigned int line) {
isc_mutex_init_location(isc_mutex_t *mp, const char *file, unsigned int line) {
int err;
#ifdef HAVE_PTHREAD_MUTEX_ADAPTIVE_NP
@@ -58,3 +114,5 @@ isc__mutex_init(isc_mutex_t *mp, const char *file, unsigned int line) {
strbuf);
}
}
#endif /* ISC_TRACK_PTHREADS_OBJECTS */

View File

@@ -25,18 +25,62 @@
#include <isc/rwlock.h>
#include <isc/util.h>
#ifdef ISC_TRACK_PTHREADS_OBJECTS
#include <stdlib.h>
struct isc_rwlock_tracker {
ISC_LINK(isc_rwlock_tracker_t) link;
const char *file;
int line;
};
static pthread_mutex_t rwlockslock = PTHREAD_MUTEX_INITIALIZER;
static ISC_LIST(isc_rwlock_tracker_t) rwlocks = { NULL, NULL };
void
isc_rwlock_check_track(void) {
pthread_mutex_lock(&rwlockslock);
if (!ISC_LIST_EMPTY(rwlocks)) {
isc_rwlock_tracker_t *t;
fprintf(stderr,
"isc_rwlock_init/isc_rwlock_destroy mismatch\n");
for (t = ISC_LIST_HEAD(rwlocks); t != NULL;
t = ISC_LIST_NEXT(t, link)) {
fprintf(stderr, "rwlock %s:%d\n", t->file, t->line);
}
abort();
}
pthread_mutex_unlock(&rwlockslock);
}
#endif /* ISC_TRACK_PTHREADS_OBJECTS */
#if USE_PTHREAD_RWLOCK
#include <errno.h>
#include <pthread.h>
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 *file, int line) {
UNUSED(read_quota);
UNUSED(write_quota);
REQUIRE(pthread_rwlock_init(&rwl->rwlock, NULL) == 0);
atomic_init(&rwl->downgrade, false);
#ifdef ISC_TRACK_PTHREADS_OBJECTS
rwl->tracker = malloc(sizeof(*rwl->tracker));
INSIST(rwl->tracker != NULL);
rwl->tracker->file = file;
rwl->tracker->line = line;
pthread_mutex_lock(&rwlockslock);
ISC_LIST_INITANDAPPEND(rwlocks, rwl->tracker, link);
pthread_mutex_unlock(&rwlockslock);
#else
UNUSED(file);
UNUSED(line);
#endif /* ISC_TRACK_PTHREADS_OBJECTS */
}
isc_result_t
@@ -123,6 +167,15 @@ isc_rwlock_downgrade(isc_rwlock_t *rwl) {
void
isc_rwlock_destroy(isc_rwlock_t *rwl) {
#ifdef ISC_TRACK_PTHREADS_OBJECTS
INSIST(rwl->tracker != NULL);
pthread_mutex_lock(&rwlockslock);
ISC_LIST_UNLINK(rwlocks, rwl->tracker, link);
pthread_mutex_unlock(&rwlockslock);
free(rwl->tracker);
rwl->tracker = NULL;
#endif /* ISC_TRACK_PTHREADS_OBJECTS */
pthread_rwlock_destroy(&rwl->rwlock);
}
@@ -191,8 +244,8 @@ 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 *file, int line) {
REQUIRE(rwl != NULL);
/*
@@ -221,6 +274,19 @@ isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
isc_condition_init(&rwl->readable);
isc_condition_init(&rwl->writeable);
#ifdef ISC_TRACK_PTHREADS_OBJECTS
rwl->tracker = malloc(sizeof(*rwl->tracker));
INSIST(rwl->tracker != NULL);
rwl->tracker->file = file;
rwl->tracker->line = line;
pthread_mutex_lock(&rwlockslock);
ISC_LIST_INITANDAPPEND(rwlocks, rwl->tracker, link);
pthread_mutex_unlock(&rwlockslock);
#else
UNUSED(file);
UNUSED(line);
#endif /* ISC_TRACK_PTHREADS_OBJECTS */
rwl->magic = RWLOCK_MAGIC;
}
@@ -233,6 +299,15 @@ isc_rwlock_destroy(isc_rwlock_t *rwl) {
atomic_load_acquire(&rwl->cnt_and_flag) == 0 &&
rwl->readers_waiting == 0);
#ifdef ISC_TRACK_PTHREADS_OBJECTS
INSIST(rwl->tracker != NULL);
pthread_mutex_lock(&rwlockslock);
ISC_LIST_UNLINK(rwlocks, rwl->tracker, link);
pthread_mutex_unlock(&rwlockslock);
free(rwl->tracker);
rwl->tracker = NULL;
#endif /* ISC_TRACK_PTHREADS_OBJECTS */
rwl->magic = 0;
(void)isc_condition_destroy(&rwl->readable);
(void)isc_condition_destroy(&rwl->writeable);

View File

@@ -379,6 +379,8 @@ nm_teardown(void **state __attribute__((unused))) {
isc_refcount_destroy(&active_ssends);
isc_refcount_destroy(&active_sreads);
isc_quota_destroy(&listener_quota);
return (0);
}

View File

@@ -104,6 +104,7 @@ _teardown(void **state) {
UNUSED(state);
isc_test_end();
isc_mutex_destroy(&lock);
isc_condition_destroy(&cv);
return (0);
@@ -919,8 +920,6 @@ post_shutdown(void **state) {
atomic_init(&done, false);
event_type = 4;
isc_condition_init(&cv);
LOCK(&lock);
task = NULL;
@@ -1059,6 +1058,7 @@ test_purge(int sender, int type, int tag, int exp_purged) {
atomic_init(&done, false);
eventcnt = 0;
isc_condition_destroy(&cv);
isc_condition_init(&cv);
result = isc_task_create(taskmgr, 0, &task);
@@ -1354,8 +1354,6 @@ try_purgeevent(bool purgeable) {
atomic_init(&done, false);
eventcnt = 0;
isc_condition_init(&cv);
result = isc_task_create(taskmgr, 0, &task);
assert_int_equal(result, ISC_R_SUCCESS);

View File

@@ -146,6 +146,7 @@ setup_test(isc_timertype_t timertype, isc_time_t *expires,
isc_task_detach(&task);
isc_mutex_destroy(&mx);
isc_mutex_destroy(&lasttime_mx);
(void)isc_condition_destroy(&cv);
}