From add7342a14f398fea2416d1b86ce7393cfa29e7c Mon Sep 17 00:00:00 2001 From: Karl Heyes Date: Thu, 8 Jan 2009 03:35:54 +0000 Subject: [PATCH] Don't free up the second, third... header pages, as those are only referenced once, only the first page is refcounted multiple times by the queue. Put some checks in to help capture odd cases if they arise. svn path=/icecast/trunk/icecast/; revision=15613 --- src/format_ogg.c | 1 + src/refbuf.c | 39 ++++++++++++++++++++++++++------------- src/source.c | 2 ++ 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/format_ogg.c b/src/format_ogg.c index 64cd0801..b7c8b658 100644 --- a/src/format_ogg.c +++ b/src/format_ogg.c @@ -120,6 +120,7 @@ void format_ogg_free_headers (ogg_state_t *ogg_info) { refbuf_t *to_release = header; header = header->next; + to_release->next = NULL; refbuf_release (to_release); } ogg_info->header_pages = NULL; diff --git a/src/refbuf.c b/src/refbuf.c index 11478fcc..bdc1978d 100644 --- a/src/refbuf.c +++ b/src/refbuf.c @@ -25,6 +25,11 @@ #include "refbuf.h" +#define CATMODULE "refbuf" + +#include "logging.h" + + void refbuf_initialize(void) { } @@ -33,22 +38,19 @@ void refbuf_shutdown(void) { } -refbuf_t *refbuf_new(unsigned int size) +refbuf_t *refbuf_new (unsigned int size) { refbuf_t *refbuf; refbuf = (refbuf_t *)malloc(sizeof(refbuf_t)); if (refbuf == NULL) - return NULL; + abort(); refbuf->data = NULL; if (size) { refbuf->data = malloc (size); if (refbuf->data == NULL) - { - free (refbuf); - return NULL; - } + abort(); } refbuf->len = size; refbuf->sync_point = 0; @@ -64,18 +66,29 @@ void refbuf_addref(refbuf_t *self) self->_count++; } +static void refbuf_release_associated (refbuf_t *ref) +{ + if (ref == NULL) + return; + while (ref && ref->_count == 1) + { + refbuf_t *to_go = ref; + ref = to_go->next; + to_go->next = NULL; + refbuf_release (to_go); + } +} + void refbuf_release(refbuf_t *self) { if (self == NULL) return; self->_count--; - if (self->_count == 0) { - while (self->associated) - { - refbuf_t *ref = self->associated; - self->associated = ref->next; - refbuf_release (ref); - } + if (self->_count == 0) + { + refbuf_release_associated (self->associated); + if (self->next) + DEBUG0 ("next not null"); free(self->data); free(self); } diff --git a/src/source.c b/src/source.c index c4245dd5..26b228cd 100644 --- a/src/source.c +++ b/src/source.c @@ -239,6 +239,7 @@ void source_clear_source (source_t *source) { refbuf_t *p = source->stream_data; source->stream_data = p->next; + p->next = NULL; /* can be referenced by burst handler as well */ while (p->_count > 1) refbuf_release (p); @@ -806,6 +807,7 @@ void source_main (source_t *source) } source->stream_data = to_go->next; source->queue_size -= to_go->len; + to_go->next = NULL; refbuf_release (to_go); } }