]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Enable tracking of pthreads mutexes
authorOndřej Surý <ondrej@isc.org>
Wed, 13 Jul 2022 11:19:32 +0000 (13:19 +0200)
committerMichał Kępień <michal@isc.org>
Wed, 13 Jul 2022 11:19:32 +0000 (13:19 +0200)
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.

Introduce a new ISC_TRACK_PTHREADS_OBJECTS preprocessor macro, which
causes isc_mutex_t structures to be allocated on the heap by
isc_mutex_init() and freed by isc_mutex_destroy().  Reuse existing mutex
macros (after renaming them appropriately) for other operations.

lib/isc/condition.c
lib/isc/include/isc/condition.h
lib/isc/include/isc/mutex.h
lib/isc/mutex.c

index 19c16be6b1c67fcb2879babc93631ffb260d3a42..de412ec5ab4c67f1e40bdb1a7145b437f60ad41b 100644 (file)
@@ -52,7 +52,15 @@ 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_mutex_t *mutex;
+
+#ifdef ISC_TRACK_PTHREADS_OBJECTS
+               mutex = *m;
+#else  /* ISC_TRACK_PTHREADS_OBJECTS */
+               mutex = m;
+#endif /* ISC_TRACK_PTHREADS_OBJECTS */
+
+               presult = pthread_cond_timedwait(c, mutex, &ts);
                if (presult == 0) {
                        return (ISC_R_SUCCESS);
                }
index 69622d32ced5ba2e4e22ce3c8f81807896d95433..36fc12873567480959df04061d4853d33f8cb0a9 100644 (file)
@@ -33,7 +33,13 @@ typedef pthread_cond_t isc_condition_t;
                ERRNO_CHECK(pthread_cond_init, _ret);     \
        }
 
-#define isc_condition_wait(cp, mp) \
+#ifdef ISC_TRACK_PTHREADS_OBJECTS
+#define isc_condition_wait(cp, mp) isc__condition_wait(cp, *mp)
+#else /* ISC_TRACK_PTHREADS_OBJECTS */
+#define isc_condition_wait(cp, mp) isc__condition_wait(cp, mp)
+#endif /* ISC_TRACK_PTHREADS_OBJECTS */
+
+#define isc__condition_wait(cp, mp) \
        RUNTIME_CHECK(pthread_cond_wait((cp), (mp)) == 0)
 
 #define isc_condition_signal(cp) RUNTIME_CHECK(pthread_cond_signal((cp)) == 0)
index 09d192f610bbfd1cf974a9dd6e0c40fa59fc6bcb..028db239dbd962c6036c3b39b7e0ed0361ac8bc5 100644 (file)
 
 #include <pthread.h>
 #include <stdio.h>
+#include <stdlib.h>
 
 #include <isc/lang.h>
 #include <isc/result.h> /* for ISC_R_ codes */
+#include <isc/util.h>
 
 ISC_LANG_BEGINDECLS
 
+#ifdef ISC_TRACK_PTHREADS_OBJECTS
+
+typedef pthread_mutex_t *isc_mutex_t;
+
+#define isc_mutex_init(mp)                  \
+       {                                   \
+               *mp = malloc(sizeof(**mp)); \
+               isc__mutex_init((*mp));     \
+       }
+#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)            \
+       {                                \
+               isc__mutex_destroy(*mp); \
+               free(*mp);               \
+       }
+
+#else /* ISC_TRACK_PTHREADS_OBJECTS */
+
 typedef pthread_mutex_t isc_mutex_t;
 
-void
-isc__mutex_init(isc_mutex_t *mp);
+#define isc_mutex_init(mp)    isc__mutex_init((mp))
+#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) isc__mutex_destroy(mp)
+
+#endif /* ISC_TRACK_PTHREADS_OBJECTS */
+
+extern pthread_mutexattr_t isc__mutex_init_attr;
 
-#define isc_mutex_init(mp) isc__mutex_init((mp))
+#define isc__mutex_init(mp)                                               \
+       {                                                                 \
+               int _ret = pthread_mutex_init(mp, &isc__mutex_init_attr); \
+               ERRNO_CHECK(pthread_mutex_init, _ret);                    \
+       }
 
-#define isc_mutex_lock(mp) RUNTIME_CHECK(pthread_mutex_lock((mp)) == 0)
+#define isc__mutex_lock(mp) RUNTIME_CHECK(pthread_mutex_lock((mp)) == 0)
 
-#define isc_mutex_unlock(mp) RUNTIME_CHECK(pthread_mutex_unlock((mp)) == 0)
+#define isc__mutex_unlock(mp) RUNTIME_CHECK(pthread_mutex_unlock((mp)) == 0)
 
-#define isc_mutex_trylock(mp) \
+#define isc__mutex_trylock(mp) \
        ((pthread_mutex_trylock((mp)) == 0) ? ISC_R_SUCCESS : ISC_R_LOCKBUSY)
 
-#define isc_mutex_destroy(mp) RUNTIME_CHECK(pthread_mutex_destroy((mp)) == 0)
+#define isc__mutex_destroy(mp) RUNTIME_CHECK(pthread_mutex_destroy((mp)) == 0)
 
 ISC_LANG_ENDDECLS
index 075fc37b32395f5a7e6d5244af15c8e7c4f372b6..9c067cbd9ece90995b062cb1ed6a5f730ec3241a 100644 (file)
@@ -47,14 +47,6 @@ isc__mutex_initialize(void) {
                      ISC_R_SUCCESS);
 }
 
-void
-isc__mutex_init(isc_mutex_t *mp) {
-       int err;
-
-       err = pthread_mutex_init(mp, &isc__mutex_init_attr);
-       ERRNO_CHECK(pthread_mutex_init, err);
-}
-
 void
 isc__mutex_shutdown(void) {
        /* noop */;