mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	mem: Clean up stray mappings
Warn when some mappings were not freed when freeing all the blocks and memmaps. Clean them anyway to avoid leaks.
This commit is contained in:
		
							parent
							
								
									4796673581
								
							
						
					
					
						commit
						6aeaebe2b0
					
				
					 2 changed files with 43 additions and 15 deletions
				
			
		| 
						 | 
				
			
			@ -98,22 +98,23 @@ static struct spa_list _mempools = SPA_LIST_INIT(&_mempools);
 | 
			
		|||
struct mempool {
 | 
			
		||||
	struct pw_mempool this;
 | 
			
		||||
 | 
			
		||||
	struct spa_list link;
 | 
			
		||||
	struct spa_list link;		/* link in global _mempools */
 | 
			
		||||
 | 
			
		||||
	struct spa_hook_list listener_list;
 | 
			
		||||
 | 
			
		||||
	struct pw_map map;
 | 
			
		||||
	struct spa_list blocks;
 | 
			
		||||
	struct pw_map map;		/* map memblock to id */
 | 
			
		||||
	struct spa_list blocks;		/* list of memblock */
 | 
			
		||||
	uint32_t pagesize;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct memblock {
 | 
			
		||||
	struct pw_memblock this;
 | 
			
		||||
	struct spa_list link;
 | 
			
		||||
	struct spa_list mappings;
 | 
			
		||||
	struct spa_list maps;
 | 
			
		||||
	struct spa_list link;		/* link in mempool */
 | 
			
		||||
	struct spa_list mappings;	/* list of struct mapping */
 | 
			
		||||
	struct spa_list memmaps;	/* list of struct memmap */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* a mapped region of a block */
 | 
			
		||||
struct mapping {
 | 
			
		||||
	struct memblock *block;
 | 
			
		||||
	int ref;
 | 
			
		||||
| 
						 | 
				
			
			@ -124,6 +125,7 @@ struct mapping {
 | 
			
		|||
	void *ptr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* a reference to a (part of a) mapped region */
 | 
			
		||||
struct memmap {
 | 
			
		||||
	struct pw_memmap this;
 | 
			
		||||
	struct mapping *mapping;
 | 
			
		||||
| 
						 | 
				
			
			@ -260,6 +262,9 @@ static struct mapping * memblock_find_mapping(struct memblock *b,
 | 
			
		|||
	struct pw_mempool *pool = b->this.pool;
 | 
			
		||||
 | 
			
		||||
	spa_list_for_each(m, &b->mappings, link) {
 | 
			
		||||
		pw_log_debug(NAME" %p: check %p offset:(%d <= %d) end:(%d >= %d)",
 | 
			
		||||
				pool, m, m->offset, offset, m->offset + m->size,
 | 
			
		||||
				offset + size);
 | 
			
		||||
		if (m->offset <= offset && (m->offset + m->size) >= (offset + size)) {
 | 
			
		||||
			pw_log_debug(NAME" %p: found %p id:%d fd:%d offs:%d size:%d ref:%d",
 | 
			
		||||
					pool, &b->this, b->this.id, b->this.fd,
 | 
			
		||||
| 
						 | 
				
			
			@ -321,7 +326,7 @@ static struct mapping * memblock_map(struct memblock *b,
 | 
			
		|||
	return m;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void mapping_unmap(struct mapping *m)
 | 
			
		||||
static void mapping_free(struct mapping *m)
 | 
			
		||||
{
 | 
			
		||||
	struct memblock *b = m->block;
 | 
			
		||||
	struct mempool *p = SPA_CONTAINER_OF(b->this.pool, struct mempool, this);
 | 
			
		||||
| 
						 | 
				
			
			@ -333,7 +338,15 @@ static void mapping_unmap(struct mapping *m)
 | 
			
		|||
		munmap(m->ptr, m->size);
 | 
			
		||||
	spa_list_remove(&m->link);
 | 
			
		||||
	free(m);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void mapping_unmap(struct mapping *m)
 | 
			
		||||
{
 | 
			
		||||
	struct memblock *b = m->block;
 | 
			
		||||
	struct mempool *p = SPA_CONTAINER_OF(b->this.pool, struct mempool, this);
 | 
			
		||||
        pw_log_debug(NAME" %p: mapping:%p block:%p fd:%d ptr:%p size:%d block-ref:%d",
 | 
			
		||||
			p, m, b, b->this.fd, m->ptr, m->size, b->this.ref);
 | 
			
		||||
	mapping_free(m);
 | 
			
		||||
	pw_memblock_unref(&b->this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -372,7 +385,7 @@ struct pw_memmap * pw_memblock_map(struct pw_memblock *block,
 | 
			
		|||
	if (tag)
 | 
			
		||||
		memcpy(mm->this.tag, tag, sizeof(mm->this.tag));
 | 
			
		||||
 | 
			
		||||
	spa_list_append(&b->maps, &mm->link);
 | 
			
		||||
	spa_list_append(&b->memmaps, &mm->link);
 | 
			
		||||
 | 
			
		||||
        pw_log_debug(NAME" %p: map:%p block:%p fd:%d ptr:%p (%d %d) mapping:%p ref:%d", p,
 | 
			
		||||
			&mm->this, b, b->this.fd, mm->this.ptr, offset, size, m, m->ref);
 | 
			
		||||
| 
						 | 
				
			
			@ -454,7 +467,7 @@ struct pw_memblock * pw_mempool_alloc(struct pw_mempool *pool, enum pw_memblock_
 | 
			
		|||
	b->this.type = type;
 | 
			
		||||
	b->this.size = size;
 | 
			
		||||
	spa_list_init(&b->mappings);
 | 
			
		||||
	spa_list_init(&b->maps);
 | 
			
		||||
	spa_list_init(&b->memmaps);
 | 
			
		||||
 | 
			
		||||
#ifdef USE_MEMFD
 | 
			
		||||
	b->this.fd = memfd_create("pipewire-memfd", MFD_CLOEXEC | MFD_ALLOW_SEALING);
 | 
			
		||||
| 
						 | 
				
			
			@ -500,7 +513,7 @@ struct pw_memblock * pw_mempool_alloc(struct pw_mempool *pool, enum pw_memblock_
 | 
			
		|||
 | 
			
		||||
	b->this.id = pw_map_insert_new(&impl->map, b);
 | 
			
		||||
	spa_list_append(&impl->blocks, &b->link);
 | 
			
		||||
	pw_log_debug(NAME" %p: block:%p id:%d type:%u", pool, &b->this, b->this.id, type);
 | 
			
		||||
	pw_log_debug(NAME" %p: block:%p id:%d type:%u size:%zd", pool, &b->this, b->this.id, type, size);
 | 
			
		||||
 | 
			
		||||
	pw_mempool_emit_added(impl, &b->this);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -546,7 +559,7 @@ struct pw_memblock * pw_mempool_import(struct pw_mempool *pool,
 | 
			
		|||
	if (b == NULL)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	spa_list_init(&b->maps);
 | 
			
		||||
	spa_list_init(&b->memmaps);
 | 
			
		||||
	spa_list_init(&b->mappings);
 | 
			
		||||
 | 
			
		||||
	b->this.ref = 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -569,6 +582,8 @@ SPA_EXPORT
 | 
			
		|||
struct pw_memblock * pw_mempool_import_block(struct pw_mempool *pool,
 | 
			
		||||
		struct pw_memblock *mem)
 | 
			
		||||
{
 | 
			
		||||
	pw_log_debug(NAME" %p: import block:%p type:%d fd:%d", pool,
 | 
			
		||||
			mem, mem->type, mem->fd);
 | 
			
		||||
	return pw_mempool_import(pool,
 | 
			
		||||
			mem->flags | PW_MEMBLOCK_FLAG_DONT_CLOSE,
 | 
			
		||||
			mem->type, mem->fd);
 | 
			
		||||
| 
						 | 
				
			
			@ -581,7 +596,6 @@ struct pw_memmap * pw_mempool_import_map(struct pw_mempool *pool,
 | 
			
		|||
	struct pw_memblock *old, *block;
 | 
			
		||||
	struct memblock *b;
 | 
			
		||||
	struct pw_memmap *map;
 | 
			
		||||
	struct mapping *m;
 | 
			
		||||
	uint32_t offset;
 | 
			
		||||
 | 
			
		||||
	old = pw_mempool_find_ptr(other, data);
 | 
			
		||||
| 
						 | 
				
			
			@ -595,6 +609,8 @@ struct pw_memmap * pw_mempool_import_map(struct pw_mempool *pool,
 | 
			
		|||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	if (block->ref == 1) {
 | 
			
		||||
		struct mapping *m;
 | 
			
		||||
 | 
			
		||||
		b = SPA_CONTAINER_OF(block, struct memblock, this);
 | 
			
		||||
 | 
			
		||||
		m = calloc(1, sizeof(struct mapping));
 | 
			
		||||
| 
						 | 
				
			
			@ -607,6 +623,8 @@ struct pw_memmap * pw_mempool_import_map(struct pw_mempool *pool,
 | 
			
		|||
		m->offset = old->map->offset;
 | 
			
		||||
		m->size = old->map->size;
 | 
			
		||||
		spa_list_append(&b->mappings, &m->link);
 | 
			
		||||
		pw_log_debug(NAME" %p: mapping:%p block:%p offset:%u size:%u ref:%u",
 | 
			
		||||
				pool, m, block, m->offset, m->size, block->ref);
 | 
			
		||||
	} else {
 | 
			
		||||
		block->ref--;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -618,7 +636,8 @@ struct pw_memmap * pw_mempool_import_map(struct pw_mempool *pool,
 | 
			
		|||
	if (map == NULL)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	pw_log_debug(NAME" %p: block:%p id:%u", pool, block, block->id);
 | 
			
		||||
	pw_log_debug(NAME" %p: from pool:%p block:%p id:%u data:%p size:%u ref:%d",
 | 
			
		||||
			pool, other, block, block->id, data, size, block->ref);
 | 
			
		||||
 | 
			
		||||
	return map;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -653,6 +672,7 @@ void pw_memblock_free(struct pw_memblock *block)
 | 
			
		|||
	struct pw_mempool *pool = block->pool;
 | 
			
		||||
	struct mempool *impl = SPA_CONTAINER_OF(pool, struct mempool, this);
 | 
			
		||||
	struct memmap *mm;
 | 
			
		||||
	struct mapping *m;
 | 
			
		||||
 | 
			
		||||
	spa_return_if_fail(block != NULL);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -669,9 +689,14 @@ void pw_memblock_free(struct pw_memblock *block)
 | 
			
		|||
 | 
			
		||||
	pw_mempool_emit_removed(impl, block);
 | 
			
		||||
 | 
			
		||||
	spa_list_consume(mm, &b->maps, link)
 | 
			
		||||
	spa_list_consume(mm, &b->memmaps, link)
 | 
			
		||||
		pw_memmap_free(&mm->this);
 | 
			
		||||
 | 
			
		||||
	spa_list_consume(m, &b->mappings, link) {
 | 
			
		||||
		pw_log_warn(NAME" %p: stray mapping:%p", pool, m);
 | 
			
		||||
		mapping_free(m);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (block->fd != -1 && !(block->flags & PW_MEMBLOCK_FLAG_DONT_CLOSE)) {
 | 
			
		||||
		pw_log_debug(NAME" %p: close fd:%d", pool, block->fd);
 | 
			
		||||
		close(block->fd);
 | 
			
		||||
| 
						 | 
				
			
			@ -734,7 +759,7 @@ struct pw_memmap * pw_mempool_find_tag(struct pw_mempool *pool, uint32_t tag[5],
 | 
			
		|||
	pw_log_debug(NAME" %p: find tag %zd", pool, size);
 | 
			
		||||
 | 
			
		||||
	spa_list_for_each(b, &impl->blocks, link) {
 | 
			
		||||
		spa_list_for_each(mm, &b->maps, link) {
 | 
			
		||||
		spa_list_for_each(mm, &b->memmaps, link) {
 | 
			
		||||
			if (memcmp(tag, mm->this.tag, size) == 0) {
 | 
			
		||||
				pw_log_debug(NAME" %p: found %p", pool, mm);
 | 
			
		||||
				return &mm->this;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,6 +55,9 @@ enum pw_memmap_flags {
 | 
			
		|||
 | 
			
		||||
struct pw_memchunk;
 | 
			
		||||
 | 
			
		||||
/** \class pw_memblock
 | 
			
		||||
 *
 | 
			
		||||
 * A memory pool is a collection of pw_memblocks */
 | 
			
		||||
struct pw_mempool {
 | 
			
		||||
	struct pw_properties *props;
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue