diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c index 4940345791..9771bf2e42 100644 --- a/src/libsystemd/sd-event/sd-event.c +++ b/src/libsystemd/sd-event/sd-event.c @@ -115,6 +115,9 @@ struct sd_event { unsigned n_sources; + struct epoll_event *event_queue; + size_t event_queue_allocated; + LIST_HEAD(sd_event_source, sources); usec_t last_run, last_log; @@ -286,6 +289,8 @@ static sd_event *event_free(sd_event *e) { hashmap_free(e->child_sources); set_free(e->post_sources); + free(e->event_queue); + return mfree(e); } @@ -3477,8 +3482,7 @@ pending: } _public_ int sd_event_wait(sd_event *e, uint64_t timeout) { - struct epoll_event *ev_queue; - unsigned ev_queue_max; + size_t event_queue_max; int r, m, i; assert_return(e, -EINVAL); @@ -3492,14 +3496,15 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) { return 1; } - ev_queue_max = MAX(e->n_sources, 1u); - ev_queue = newa(struct epoll_event, ev_queue_max); + event_queue_max = MAX(e->n_sources, 1u); + if (!GREEDY_REALLOC(e->event_queue, e->event_queue_allocated, event_queue_max)) + return -ENOMEM; /* If we still have inotify data buffered, then query the other fds, but don't wait on it */ if (e->inotify_data_buffered) timeout = 0; - m = epoll_wait(e->epoll_fd, ev_queue, ev_queue_max, + m = epoll_wait(e->epoll_fd, e->event_queue, event_queue_max, timeout == (uint64_t) -1 ? -1 : (int) DIV_ROUND_UP(timeout, USEC_PER_MSEC)); if (m < 0) { if (errno == EINTR) { @@ -3515,26 +3520,26 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) { for (i = 0; i < m; i++) { - if (ev_queue[i].data.ptr == INT_TO_PTR(SOURCE_WATCHDOG)) - r = flush_timer(e, e->watchdog_fd, ev_queue[i].events, NULL); + if (e->event_queue[i].data.ptr == INT_TO_PTR(SOURCE_WATCHDOG)) + r = flush_timer(e, e->watchdog_fd, e->event_queue[i].events, NULL); else { - WakeupType *t = ev_queue[i].data.ptr; + WakeupType *t = e->event_queue[i].data.ptr; switch (*t) { case WAKEUP_EVENT_SOURCE: { - sd_event_source *s = ev_queue[i].data.ptr; + sd_event_source *s = e->event_queue[i].data.ptr; assert(s); switch (s->type) { case SOURCE_IO: - r = process_io(e, s, ev_queue[i].events); + r = process_io(e, s, e->event_queue[i].events); break; case SOURCE_CHILD: - r = process_pidfd(e, s, ev_queue[i].events); + r = process_pidfd(e, s, e->event_queue[i].events); break; default: @@ -3545,20 +3550,20 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) { } case WAKEUP_CLOCK_DATA: { - struct clock_data *d = ev_queue[i].data.ptr; + struct clock_data *d = e->event_queue[i].data.ptr; assert(d); - r = flush_timer(e, d->fd, ev_queue[i].events, &d->next); + r = flush_timer(e, d->fd, e->event_queue[i].events, &d->next); break; } case WAKEUP_SIGNAL_DATA: - r = process_signal(e, ev_queue[i].data.ptr, ev_queue[i].events); + r = process_signal(e, e->event_queue[i].data.ptr, e->event_queue[i].events); break; case WAKEUP_INOTIFY_DATA: - r = event_inotify_data_read(e, ev_queue[i].data.ptr, ev_queue[i].events); + r = event_inotify_data_read(e, e->event_queue[i].data.ptr, e->event_queue[i].events); break; default: