--- apps/buffering.c.0 2011-01-11 00:01:50.000000000 +0000 +++ apps/buffering.c 2011-01-25 18:47:35.000000000 +0000 @@ -25,6 +25,8 @@ #include #include #include +#define assert(a) + #include "buffering.h" #include "storage.h" @@ -613,6 +615,16 @@ return data_counters.useful < (conf_watermark / 2); } +static uintptr_t beyond_handle(struct memory_handle *h) +{ + /* + * the last handle on the chain must leave at least one byte + * between itself and the first handle, to avoid overflowing the + * ring by advancing buf_widx up to buf_ridx + */ + return h->next != 0 ? ringbuf_offset(h->next) : ringbuf_sub(buf_ridx, 1); +} + /* Buffer data for the given handle. Return whether or not the buffering should continue explicitly. */ static bool buffer_handle(int handle_id) @@ -671,10 +683,10 @@ buffer_len - h->widx); ssize_t overlap; - uintptr_t next_handle = ringbuf_offset(h->next); + uintptr_t next_handle = beyond_handle(h); /* stop copying if it would overwrite the reading position */ - if (ringbuf_add_cross(h->widx, copy_n, buf_ridx) >= 0) + if (h->widx == next_handle || ringbuf_add_cross(h->widx, copy_n, buf_ridx) >= 0) return false; /* FIXME: This would overwrite the next handle @@ -791,8 +803,7 @@ LOGFQUEUE("buffering >| Q_RESET_HANDLE %d", handle_id); queue_send(&buffering_queue, Q_RESET_HANDLE, handle_id); - uintptr_t next = ringbuf_offset(h->next); - if (ringbuf_sub(next, h->data) < h->filesize - newpos) + if (ringbuf_sub(beyond_handle(h), h->data) < h->filesize - newpos) { /* There isn't enough space to rebuffer all of the track from its new offset, so we ask the user to free some */