diff options
| -rw-r--r-- | src/pulsecore/memblock.c | 43 | ||||
| -rw-r--r-- | src/pulsecore/refcnt.h | 44 | 
2 files changed, 81 insertions, 6 deletions
diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c index fbf0a470..6cc0ff3f 100644 --- a/src/pulsecore/memblock.c +++ b/src/pulsecore/memblock.c @@ -745,8 +745,47 @@ void pa_mempool_free(pa_mempool *p) {      pa_flist_free(p->free_slots, NULL);      if (pa_atomic_load(&p->stat.n_allocated) > 0) { -/*         raise(SIGTRAP);  */ -        pa_log_warn("Memory pool destroyed but not all memory blocks freed! %u remain.", pa_atomic_load(&p->stat.n_allocated)); + +        /* Ouch, somebody is retaining a memory block reference! */ + +#ifdef DEBUG_REF +        unsigned i; +        pa_flist *list; + +        /* Let's try to find at least one of those leaked memory blocks */ + +        list = pa_flist_new(p->n_blocks); + +        for (i = 0; i < (unsigned) pa_atomic_load(&p->n_init); i++) { +            struct mempool_slot *slot; +            pa_memblock *b, *k; + +            slot = (struct mempool_slot*) ((uint8_t*) p->memory.ptr + (p->block_size * (size_t) i)); +            b = mempool_slot_data(slot); + +            while ((k = pa_flist_pop(p->free_slots))) { +                while (pa_flist_push(list, k) < 0) +                    ; + +                if (b == k) +                    break; +            } + +            if (!k) +                pa_log("REF: Leaked memory block %p", b); + +            while ((k = pa_flist_pop(list))) +                while (pa_flist_push(p->free_slots, k) < 0) +                    ; +        } + +        pa_flist_free(list, NULL); + +#endif + +        pa_log_error("Memory pool destroyed but not all memory blocks freed! %u remain.", pa_atomic_load(&p->stat.n_allocated)); + +/*         PA_DEBUG_TRAP; */      }      pa_shm_free(&p->memory); diff --git a/src/pulsecore/refcnt.h b/src/pulsecore/refcnt.h index 1e988326..782436b5 100644 --- a/src/pulsecore/refcnt.h +++ b/src/pulsecore/refcnt.h @@ -23,23 +23,59 @@  ***/  #include <pulsecore/atomic.h> +#include <pulsecore/macro.h> +#include <pulsecore/log.h> + +/* #define DEBUG_REF */  #define PA_REFCNT_DECLARE \      pa_atomic_t _ref -#define PA_REFCNT_INIT(p) \ -    pa_atomic_store(&(p)->_ref, 1) +#define PA_REFCNT_VALUE(p) \ +    pa_atomic_load(&(p)->_ref)  #define PA_REFCNT_INIT_ZERO(p) \      pa_atomic_store(&(p)->_ref, 0) +#ifndef DEBUG_REF + +#define PA_REFCNT_INIT(p) \ +    pa_atomic_store(&(p)->_ref, 1) +  #define PA_REFCNT_INC(p) \      pa_atomic_inc(&(p)->_ref)  #define PA_REFCNT_DEC(p) \      (pa_atomic_dec(&(p)->_ref)-1) -#define PA_REFCNT_VALUE(p) \ -    pa_atomic_load(&(p)->_ref) +#else + +/* If you need to debug ref counting problems define DEBUG_REF and + * set $PULSE_LOG_BACKTRACE=5 or suchlike in the shell when running + * PA */ + +#define PA_REFCNT_INIT(p)                       \ +    do {                                        \ +        pa_atomic_store(&(p)->_ref, 1);         \ +        pa_log("REF: Init %p", p);              \ +    } while (FALSE) + +#define PA_REFCNT_INC(p)                        \ +    do {                                        \ +        pa_atomic_inc(&(p)->_ref);              \ +        pa_log("REF: Inc %p", p);               \ +    } while (FALSE)                             \ + +#define PA_REFCNT_DEC(p)                        \ +    ({                                          \ +        int _j = (pa_atomic_dec(&(p)->_ref)-1); \ +        if (_j <= 0)                            \ +            pa_log("REF: Done %p", p);          \ +        else                                    \ +            pa_log("REF: Dec %p", p);           \ +        _j;                                     \ +     }) + +#endif  #endif  | 
