loop: only flush pending items

Mostly useful for when invoking from the thread itself so that the new
invoke item is executed before new items are added.

Imagine this case with module-loopback:
     - data-loop goes into the capture process function
          - mainloop invokes node remove of capture and waits
     - data-loop invokes trigger -> node remove is first executed, mainloop
                                    is woken up
          - mainloop continues
    	  - mainloop invokes remove of playback and waits
     - data-loop continues flushing the ringbuffer -> playback remove is
                                 executed, mainloop wakes up
    	  - mainloop continues destroying items, frees playback
    	    and capture streams
     - data-loop finaly gets to flush the trigger and crashes because
            streams are gone.
This commit is contained in:
Wim Taymans 2022-12-07 17:10:21 +01:00
parent 7b61bf8c8a
commit 97f95f51c5

View file

@ -167,10 +167,12 @@ static int loop_remove_source(void *object, struct spa_source *source)
static void flush_items(struct impl *impl)
{
uint32_t index;
int32_t avail;
int res;
impl->flushing = true;
while (spa_ringbuffer_get_read_index(&impl->buffer, &index) > 0) {
avail = spa_ringbuffer_get_read_index(&impl->buffer, &index);
while (avail > 0) {
struct invoke_item *item;
bool block;
@ -182,7 +184,9 @@ static void flush_items(struct impl *impl)
true, item->seq, item->data, item->size,
item->user_data) : 0;
spa_ringbuffer_read_update(&impl->buffer, index + item->item_size);
index += item->item_size;
avail -= item->item_size;
spa_ringbuffer_read_update(&impl->buffer, index);
if (block) {
if ((res = spa_system_eventfd_write(impl->system, impl->ack_fd, 1)) < 0)