diff options
author | tilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b> | 2010-07-02 21:36:39 +0000 |
---|---|---|
committer | tilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b> | 2010-07-02 21:36:39 +0000 |
commit | e08cb0ffa6dbd44c975ad5186f326ba2ee94b718 (patch) | |
tree | 1ff96db0aa1cf867ac85b9adfc65844e982bbde7 /include | |
parent | 4015a6816f3f78a0f4ef60529029d4a7dcbb1c9a (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.in | 55 | ||||
-rw-r--r-- | include/asterisk/compiler.h | 6 | ||||
-rw-r--r-- | include/asterisk/lock.h | 35 |
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 */ |