* commit 'fbd6c97f9ca858140df16dd07200ea0d4bdc1a83': lavu: fix memory leaks by using a mutex instead of atomics Conflicts: libavutil/buffer.c The atomics code is left in place as a fallback for synchronization in the absence of p/w32 threads. Our ABI did not requires applications to only use threads (and matching ones) to what libavutil was build with Our code also was not affected by the leak this change fixes, though no question the atomics based implementation is not pretty at all. First and foremost the code must work, being pretty comes after that. If this causes problems, for example when libavutil is used by multiple applications each using a different kind of threading system then the default possibly has to be changed to the uglier atomics.
Showing the changes to libavutil/buffer.c (1 of 2 files). Show all
Unified · Split
| @@ -23,6 +23,9 @@ · 22 unmodified lines | ||
| 23 | 23 | #include "buffer_internal.h" |
| 24 | 24 | #include "common.h" |
| 25 | 25 | #include "mem.h" |
| 26 | +#include "thread.h" | |
| 27 | + | |
| 28 | +#define USE_ATOMICS !(HAVE_PTHREADS || HAVE_W32THREADS) | |
| 26 | 29 | |
| 27 | 30 | AVBufferRef *av_buffer_create(uint8_t *data, int size, |
| 28 | 31 | void (*free)(void *opaque, uint8_t *data), |
| @@ -209,6 +212,8 @@ AVBufferPool *av_buffer_pool_init(int size, AVBufferRef* (*alloc)(int size)) · 180 unmodified lines | ||
| 209 | 212 | if (!pool) |
| 210 | 213 | return NULL; |
| 211 | 214 | |
| 215 | + ff_mutex_init(&pool->mutex, NULL); | |
| 216 | + | |
| 212 | 217 | pool->size = size; |
| 213 | 218 | pool->alloc = alloc ? alloc : av_buffer_alloc; |
| 214 | 219 | |
| @@ -230,6 +235,7 @@ static void buffer_pool_free(AVBufferPool *pool) · 15 unmodified lines | ||
| 230 | 235 | buf->free(buf->opaque, buf->data); |
| 231 | 236 | av_freep(&buf); |
| 232 | 237 | } |
| 238 | + ff_mutex_destroy(&pool->mutex); | |
| 233 | 239 | av_freep(&pool); |
| 234 | 240 | } |
| 235 | 241 | |
| @@ -290,7 +296,15 @@ static void pool_release_buffer(void *opaque, uint8_t *data) · 54 unmodified lines | ||
| 290 | 296 | if(CONFIG_MEMORY_POISONING) |
| 291 | 297 | memset(buf->data, FF_MEMORY_POISON, pool->size); |
| 292 | 298 | |
| 299 | +#if USE_ATOMICS | |
| 293 | 300 | add_to_pool(buf); |
| 301 | +#else | |
| 302 | + ff_mutex_lock(&pool->mutex); | |
| 303 | + buf->next = pool->pool; | |
| 304 | + pool->pool = buf; | |
| 305 | + ff_mutex_unlock(&pool->mutex); | |
| 306 | +#endif | |
| 307 | + | |
| 294 | 308 | if (!avpriv_atomic_int_add_and_fetch(&pool->refcount, -1)) |
| 295 | 309 | buffer_pool_free(pool); |
| 296 | 310 | } |
| @@ -320,8 +334,10 @@ static AVBufferRef *pool_alloc_buffer(AVBufferPool *pool) · 23 unmodified lines | ||
| 320 | 334 | ret->buffer->opaque = buf; |
| 321 | 335 | ret->buffer->free = pool_release_buffer; |
| 322 | 336 | |
| 337 | +#if USE_ATOMICS | |
| 323 | 338 | avpriv_atomic_int_add_and_fetch(&pool->refcount, 1); |
| 324 | 339 | avpriv_atomic_int_add_and_fetch(&pool->nb_allocated, 1); |
| 340 | +#endif | |
| 325 | 341 | |
| 326 | 342 | return ret; |
| 327 | 343 | } |
| @@ -331,6 +347,7 @@ AVBufferRef *av_buffer_pool_get(AVBufferPool *pool) · 3 unmodified lines | ||
| 331 | 347 | AVBufferRef *ret; |
| 332 | 348 | BufferPoolEntry *buf; |
| 333 | 349 | |
| 350 | +#if USE_ATOMICS | |
| 334 | 351 | /* check whether the pool is empty */ |
| 335 | 352 | buf = get_pool(pool); |
| 336 | 353 | if (!buf && pool->refcount <= pool->nb_allocated) { |
| @@ -352,7 +369,24 @@ AVBufferRef *av_buffer_pool_get(AVBufferPool *pool) · 15 unmodified lines | ||
| 352 | 369 | add_to_pool(buf); |
| 353 | 370 | return NULL; |
| 354 | 371 | } |
| 355 | − avpriv_atomic_int_add_and_fetch(&pool->refcount, 1); | |
| 372 | +#else | |
| 373 | + ff_mutex_lock(&pool->mutex); | |
| 374 | + buf = pool->pool; | |
| 375 | + if (buf) { | |
| 376 | + ret = av_buffer_create(buf->data, pool->size, pool_release_buffer, | |
| 377 | + buf, 0); | |
| 378 | + if (ret) { | |
| 379 | + pool->pool = buf->next; | |
| 380 | + buf->next = NULL; | |
| 381 | + } | |
| 382 | + } else { | |
| 383 | + ret = pool_alloc_buffer(pool); | |
| 384 | + } | |
| 385 | + ff_mutex_unlock(&pool->mutex); | |
| 386 | +#endif | |
| 387 | + | |
| 388 | + if (ret) | |
| 389 | + avpriv_atomic_int_add_and_fetch(&pool->refcount, 1); | |
| 356 | 390 | |
| 357 | 391 | return ret; |
| 358 | 392 | } |