aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authortilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b>2010-07-02 21:36:39 +0000
committertilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b>2010-07-02 21:36:39 +0000
commite08cb0ffa6dbd44c975ad5186f326ba2ee94b718 (patch)
tree1ff96db0aa1cf867ac85b9adfc65844e982bbde7 /include
parent4015a6816f3f78a0f4ef60529029d4a7dcbb1c9a (diff)
Have the DEADLOCK_AVOIDANCE macro warn when an unlock fails, to help catch potentially large software bugs.
(closes issue #17407) Reported by: pdf Patches: 20100527__issue17407.diff.txt uploaded by tilghman (license 14) Review: https://reviewboard.asterisk.org/r/751/ git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@273793 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'include')
-rw-r--r--include/asterisk/autoconfig.h.in55
-rw-r--r--include/asterisk/compiler.h6
-rw-r--r--include/asterisk/lock.h35
3 files changed, 66 insertions, 30 deletions
diff --git a/include/asterisk/autoconfig.h.in b/include/asterisk/autoconfig.h.in
index cf000a1f4..f76b66a41 100644
--- a/include/asterisk/autoconfig.h.in
+++ b/include/asterisk/autoconfig.h.in
@@ -66,6 +66,10 @@
/* Define to 1 if your GCC C compiler supports the 'unused' attribute. */
#undef HAVE_ATTRIBUTE_unused
+/* Define to 1 if your GCC C compiler supports the 'warn_unused_result'
+ attribute. */
+#undef HAVE_ATTRIBUTE_warn_unused_result
+
/* Define to 1 if you have the `bzero' function. */
#undef HAVE_BZERO
@@ -467,7 +471,7 @@
/* Define to 1 if you have the `strtoq' function. */
#undef HAVE_STRTOQ
-/* Define to 1 if `st_blksize' is a member of `struct stat'. */
+/* Define to 1 if `st_blksize' is member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_BLKSIZE
/* Define to 1 if you have the mISDN Supplemental Services library. */
@@ -656,12 +660,12 @@
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
-/* Define to the home page for this package. */
-#undef PACKAGE_URL
-
/* Define to the version of this package. */
#undef PACKAGE_VERSION
+/* Define to 1 if the C compiler supports function prototypes. */
+#undef PROTOTYPES
+
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */
#undef PTHREAD_CREATE_JOINABLE
@@ -681,6 +685,11 @@
/* Define to the type of arg 5 for `select'. */
#undef SELECT_TYPE_ARG5
+/* Define to 1 if the `setvbuf' function takes the buffering type as its
+ second argument and the buffer pointer as the third, as on System V before
+ release 3. */
+#undef SETVBUF_REVERSED
+
/* The size of `int', as computed by sizeof. */
#undef SIZEOF_INT
@@ -701,30 +710,20 @@
/* Define to 1 if your <sys/time.h> declares `struct tm'. */
#undef TM_IN_SYS_TIME
-/* Enable extensions on AIX 3, Interix. */
+/* Define to 1 if on AIX 3.
+ System headers sometimes define this.
+ We just want to avoid a redefinition error message. */
#ifndef _ALL_SOURCE
# undef _ALL_SOURCE
#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# undef _GNU_SOURCE
#endif
-/* Enable threading extensions on Solaris. */
-#ifndef _POSIX_PTHREAD_SEMANTICS
-# undef _POSIX_PTHREAD_SEMANTICS
-#endif
-/* Enable extensions on HP NonStop. */
-#ifndef _TANDEM_SOURCE
-# undef _TANDEM_SOURCE
-#endif
-/* Enable general extensions on Solaris. */
-#ifndef __EXTENSIONS__
-# undef __EXTENSIONS__
-#endif
-
-
-/* Number of bits in a file offset, on hosts where this is settable. */
-#undef _FILE_OFFSET_BITS
/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
#undef _LARGEFILE_SOURCE
@@ -742,6 +741,20 @@
/* Define to 1 if you need to in order for `stat' and other things to work. */
#undef _POSIX_SOURCE
+/* Enable extensions on Solaris. */
+#ifndef __EXTENSIONS__
+# undef __EXTENSIONS__
+#endif
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# undef _POSIX_PTHREAD_SEMANTICS
+#endif
+#ifndef _TANDEM_SOURCE
+# undef _TANDEM_SOURCE
+#endif
+
+/* Define like PROTOTYPES; this can be used by system headers. */
+#undef __PROTOTYPES
+
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
diff --git a/include/asterisk/compiler.h b/include/asterisk/compiler.h
index 618950017..eb06782a6 100644
--- a/include/asterisk/compiler.h
+++ b/include/asterisk/compiler.h
@@ -59,4 +59,10 @@
#define attribute_deprecated
#endif
+#ifdef HAVE_ATTRIBUTE_warn_unused_result
+#define attribute_warn_unused_result __attribute__((warn_unused_result))
+#else
+#define attribute_warn_unused_result
+#endif
+
#endif /* _ASTERISK_COMPILER_H */
diff --git a/include/asterisk/lock.h b/include/asterisk/lock.h
index d199f86db..1dbc18bbd 100644
--- a/include/asterisk/lock.h
+++ b/include/asterisk/lock.h
@@ -55,6 +55,7 @@
#include "asterisk/time.h"
#endif
#include "asterisk/logger.h"
+#include "asterisk/compiler.h"
/* internal macro to profile mutexes. Only computes the delay on
* non-blocking calls.
@@ -204,13 +205,21 @@ int ast_find_lock_info(void *lock_addr, char *filename, size_t filename_size, in
do { \
char __filename[80], __func[80], __mutex_name[80]; \
int __lineno; \
- int __res = ast_find_lock_info(lock, __filename, sizeof(__filename), &__lineno, __func, sizeof(__func), __mutex_name, sizeof(__mutex_name)); \
- ast_mutex_unlock(lock); \
+ int __res2, __res = ast_find_lock_info(lock, __filename, sizeof(__filename), &__lineno, __func, sizeof(__func), __mutex_name, sizeof(__mutex_name)); \
+ __res2 = ast_mutex_unlock(lock); \
usleep(1); \
if (__res < 0) { /* Shouldn't ever happen, but just in case... */ \
- ast_mutex_lock(lock); \
+ if (__res2 == 0) { \
+ ast_mutex_lock(lock); \
+ } else { \
+ ast_log(LOG_WARNING, "Could not unlock mutex '%s': %s and no lock info found! I will NOT try to relock.\n", #lock, strerror(__res2)); \
+ } \
} else { \
- __ast_pthread_mutex_lock(__filename, __lineno, __func, __mutex_name, lock); \
+ if (__res2 == 0) { \
+ __ast_pthread_mutex_lock(__filename, __lineno, __func, __mutex_name, lock); \
+ } else { \
+ ast_log(LOG_WARNING, "Could not unlock mutex '%s': %s. {{{Originally locked at %s line %d: (%s) '%s'}}} I will NOT try to relock.\n", #lock, strerror(__res2), __filename, __lineno, __func, __mutex_name); \
+ } \
} \
} while (0)
@@ -433,6 +442,8 @@ static inline int __ast_pthread_mutex_lock(const char *filename, int lineno, con
}
static inline int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func,
+ const char* mutex_name, ast_mutex_t *t) attribute_warn_unused_result;
+static inline int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func,
const char* mutex_name, ast_mutex_t *t)
{
int res;
@@ -712,9 +723,15 @@ static inline int __ast_cond_timedwait(const char *filename, int lineno, const c
#else /* !DEBUG_THREADS */
#define DEADLOCK_AVOIDANCE(lock) \
- ast_mutex_unlock(lock); \
- usleep(1); \
- ast_mutex_lock(lock);
+ do { \
+ int __res; \
+ if (!(__res = ast_mutex_unlock(lock))) { \
+ usleep(1); \
+ ast_mutex_lock(lock); \
+ } else { \
+ ast_log(LOG_WARNING, "Failed to unlock mutex '%s' (%s). I will NOT try to relock. {{{ THIS IS A BUG. }}}\n", #lock, strerror(__res)); \
+ } \
+ } while (0)
typedef pthread_mutex_t ast_mutex_t;
@@ -1367,7 +1384,7 @@ AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
#define ast_channel_lock(x) ast_mutex_lock(&x->lock)
/*! \brief Unlock a channel. If DEBUG_CHANNEL_LOCKS is defined
in the Makefile, print relevant output for debugging */
-#define ast_channel_unlock(x) ast_mutex_unlock(&x->lock)
+#define ast_channel_unlock(x) ast_mutex_unlock(&x->lock)
/*! \brief Try locking a channel. If DEBUG_CHANNEL_LOCKS is defined
in the Makefile, print relevant output for debugging */
#define ast_channel_trylock(x) ast_mutex_trylock(&x->lock)
@@ -1389,7 +1406,7 @@ int __ast_channel_unlock(struct ast_channel *chan, const char *file, int lineno,
#define ast_channel_trylock(a) __ast_channel_trylock(a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
/*! \brief Lock AST channel (and print debugging output)
\note You need to enable DEBUG_CHANNEL_LOCKS for this function */
-int __ast_channel_trylock(struct ast_channel *chan, const char *file, int lineno, const char *func);
+int __ast_channel_trylock(struct ast_channel *chan, const char *file, int lineno, const char *func) attribute_warn_unused_result;
#endif
#endif /* _ASTERISK_LOCK_H */