/* Should be called locked */ static void segment_detach(pa_memimport_segment *seg) { pa_assert(seg); pa_hashmap_remove(seg->import->segments, PA_UINT32_TO_PTR(seg->memory.id)); pa_shm_free(&seg->memory); pa_xfree(seg); }
void pa_mempool_free(pa_mempool *p) { pa_assert(p); pa_mutex_lock(p->mutex); while (p->imports) pa_memimport_free(p->imports); while (p->exports) pa_memexport_free(p->exports); pa_mutex_unlock(p->mutex); 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)); } pa_shm_free(&p->memory); pa_mutex_free(p->mutex); pa_semaphore_free(p->semaphore); pa_xfree(p); }
int pa_shm_cleanup(void) { #ifdef HAVE_SHM_OPEN #ifdef SHM_PATH DIR *d; struct dirent *de; if (!(d = opendir(SHM_PATH))) { pa_log_warn("Failed to read "SHM_PATH": %s", pa_cstrerror(errno)); return -1; } while ((de = readdir(d))) { pa_shm seg; unsigned id; pid_t pid; char fn[128]; struct shm_marker *m; #if defined(__sun) if (strncmp(de->d_name, ".SHMDpulse-shm-", SHM_ID_LEN)) #else if (strncmp(de->d_name, "pulse-shm-", SHM_ID_LEN)) #endif continue; if (pa_atou(de->d_name + SHM_ID_LEN, &id) < 0) continue; if (pa_shm_attach(&seg, id, false) < 0) continue; if (seg.size < SHM_MARKER_SIZE) { pa_shm_free(&seg); continue; } m = (struct shm_marker*) ((uint8_t*) seg.ptr + seg.size - SHM_MARKER_SIZE); if (pa_atomic_load(&m->marker) != SHM_MARKER) { pa_shm_free(&seg); continue; } if (!(pid = (pid_t) pa_atomic_load(&m->pid))) { pa_shm_free(&seg); continue; } if (kill(pid, 0) == 0 || errno != ESRCH) { pa_shm_free(&seg); continue; } pa_shm_free(&seg); /* Ok, the owner of this shms segment is dead, so, let's remove the segment */ segment_name(fn, sizeof(fn), id); if (shm_unlink(fn) < 0 && errno != EACCES && errno != ENOENT) pa_log_warn("Failed to remove SHM segment %s: %s\n", fn, pa_cstrerror(errno)); } closedir(d); #endif /* SHM_PATH */ #endif /* HAVE_SHM_OPEN */ return 0; }
void pa_mempool_free(pa_mempool *p) { pa_assert(p); pa_mutex_lock(p->mutex); while (p->imports) pa_memimport_free(p->imports); while (p->exports) pa_memexport_free(p->exports); pa_mutex_unlock(p->mutex); pa_flist_free(p->free_slots, NULL); if (pa_atomic_load(&p->stat.n_allocated) > 0) { /* 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); pa_mutex_free(p->mutex); pa_semaphore_free(p->semaphore); pa_xfree(p); }