]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-event: don't allocate event queue array on stack
authorLennart Poettering <lennart@poettering.net>
Wed, 18 Dec 2019 09:59:27 +0000 (10:59 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 18 Dec 2019 09:59:27 +0000 (10:59 +0100)
We might have quite a number of event sources, hence allocate this in a
buffer we can reuse on the heap, rather than on the stack.

src/libsystemd/sd-event/sd-event.c

index 4940345791149d1226d885a5677a1d70b27ee928..9771bf2e42cec3c8d6d64e26bef3955f3467ae29 100644 (file)
@@ -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: