mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-04 13:30:12 -05:00
loop: handle remove while dispatching better
Keep the array of dispatched sources around in the loop. When a source is removed while dispatching, set the data to NULL so that we don't try to deref the source again or call its function. Fixes #2114
This commit is contained in:
parent
afc88a12e5
commit
45d911641b
1 changed files with 16 additions and 5 deletions
|
|
@ -48,6 +48,7 @@ static struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.loop");
|
||||||
#define MAX_ALIGN 8
|
#define MAX_ALIGN 8
|
||||||
#define ITEM_ALIGN 8
|
#define ITEM_ALIGN 8
|
||||||
#define DATAS_SIZE (4096*8)
|
#define DATAS_SIZE (4096*8)
|
||||||
|
#define MAX_EP 32
|
||||||
|
|
||||||
/** \cond */
|
/** \cond */
|
||||||
|
|
||||||
|
|
@ -80,6 +81,9 @@ struct impl {
|
||||||
int poll_fd;
|
int poll_fd;
|
||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
|
|
||||||
|
struct spa_poll_event dispatching[MAX_EP];
|
||||||
|
uint32_t n_dispatching;
|
||||||
|
|
||||||
struct spa_source *wakeup;
|
struct spa_source *wakeup;
|
||||||
int ack_fd;
|
int ack_fd;
|
||||||
|
|
||||||
|
|
@ -125,6 +129,11 @@ static int loop_update_source(void *object, struct spa_source *source)
|
||||||
static int loop_remove_source(void *object, struct spa_source *source)
|
static int loop_remove_source(void *object, struct spa_source *source)
|
||||||
{
|
{
|
||||||
struct impl *impl = object;
|
struct impl *impl = object;
|
||||||
|
uint32_t i;
|
||||||
|
for (i = 0; i < impl->n_dispatching; i++) {
|
||||||
|
if (impl->dispatching[i].data == source)
|
||||||
|
impl->dispatching[i].data = NULL;
|
||||||
|
}
|
||||||
source->loop = NULL;
|
source->loop = NULL;
|
||||||
return spa_system_pollfd_del(impl->system, impl->poll_fd, source->fd);
|
return spa_system_pollfd_del(impl->system, impl->poll_fd, source->fd);
|
||||||
}
|
}
|
||||||
|
|
@ -311,13 +320,12 @@ static inline void process_destroy(struct impl *impl)
|
||||||
static int loop_iterate(void *object, int timeout)
|
static int loop_iterate(void *object, int timeout)
|
||||||
{
|
{
|
||||||
struct impl *impl = object;
|
struct impl *impl = object;
|
||||||
struct spa_loop *loop = &impl->loop;
|
struct spa_poll_event *ep = impl->dispatching;
|
||||||
struct spa_poll_event ep[32];
|
|
||||||
int i, nfds;
|
int i, nfds;
|
||||||
|
|
||||||
spa_loop_control_hook_before(&impl->hooks_list);
|
spa_loop_control_hook_before(&impl->hooks_list);
|
||||||
|
|
||||||
nfds = spa_system_pollfd_wait(impl->system, impl->poll_fd, ep, SPA_N_ELEMENTS(ep), timeout);
|
nfds = spa_system_pollfd_wait(impl->system, impl->poll_fd, ep, MAX_EP, timeout);
|
||||||
|
|
||||||
spa_loop_control_hook_after(&impl->hooks_list);
|
spa_loop_control_hook_after(&impl->hooks_list);
|
||||||
|
|
||||||
|
|
@ -329,16 +337,19 @@ static int loop_iterate(void *object, int timeout)
|
||||||
* can then reset the rmask to suppress the callback */
|
* can then reset the rmask to suppress the callback */
|
||||||
for (i = 0; i < nfds; i++) {
|
for (i = 0; i < nfds; i++) {
|
||||||
struct spa_source *s = ep[i].data;
|
struct spa_source *s = ep[i].data;
|
||||||
|
if (SPA_LIKELY(s))
|
||||||
s->rmask = ep[i].events;
|
s->rmask = ep[i].events;
|
||||||
}
|
}
|
||||||
|
impl->n_dispatching = nfds;
|
||||||
for (i = 0; i < nfds; i++) {
|
for (i = 0; i < nfds; i++) {
|
||||||
struct spa_source *s = ep[i].data;
|
struct spa_source *s = ep[i].data;
|
||||||
if (SPA_LIKELY(s->rmask && s->fd != -1 && s->loop == loop))
|
if (SPA_LIKELY(s && s->rmask))
|
||||||
s->func(s);
|
s->func(s);
|
||||||
}
|
}
|
||||||
if (SPA_UNLIKELY(!spa_list_is_empty(&impl->destroy_list)))
|
if (SPA_UNLIKELY(!spa_list_is_empty(&impl->destroy_list)))
|
||||||
process_destroy(impl);
|
process_destroy(impl);
|
||||||
|
|
||||||
|
impl->n_dispatching = 0;
|
||||||
return nfds;
|
return nfds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue