]>
Commit | Line | Data |
---|---|---|
cc73685d | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
3c319edb | 2 | |
d38dd64a CB |
3 | #ifndef _GNU_SOURCE |
4 | #define _GNU_SOURCE 1 | |
5 | #endif | |
b0a33c1e | 6 | #include <errno.h> |
91480a0f | 7 | #include <fcntl.h> |
3c319edb CB |
8 | #include <stdio.h> |
9 | #include <stdlib.h> | |
10 | #include <string.h> | |
b0a33c1e | 11 | #include <sys/epoll.h> |
d38dd64a | 12 | #include <unistd.h> |
b0a33c1e | 13 | |
d38dd64a | 14 | #include "config.h" |
b0a33c1e | 15 | #include "mainloop.h" |
16 | ||
9227a12a | 17 | struct mainloop_handler { |
b0a33c1e | 18 | lxc_mainloop_callback_t callback; |
19 | int fd; | |
20 | void *data; | |
21 | }; | |
22 | ||
5df6b18f CC |
23 | #define MAX_EVENTS 10 |
24 | ||
e51d4895 | 25 | int lxc_mainloop(struct lxc_epoll_descr *descr, int timeout_ms) |
b0a33c1e | 26 | { |
a529bc25 | 27 | int i, nfds, ret; |
9227a12a | 28 | struct mainloop_handler *handler; |
5df6b18f | 29 | struct epoll_event events[MAX_EVENTS]; |
b0a33c1e | 30 | |
31 | for (;;) { | |
e51d4895 | 32 | nfds = epoll_wait(descr->epfd, events, MAX_EVENTS, timeout_ms); |
b0a33c1e | 33 | if (nfds < 0) { |
34 | if (errno == EINTR) | |
35 | continue; | |
3c319edb | 36 | |
eafc1bb6 | 37 | return -errno; |
b0a33c1e | 38 | } |
39 | ||
5df6b18f | 40 | for (i = 0; i < nfds; i++) { |
a529bc25 | 41 | handler = events[i].data.ptr; |
b0a33c1e | 42 | |
a529bc25 | 43 | /* If the handler returns a positive value, exit the |
3c319edb CB |
44 | * mainloop. |
45 | */ | |
a529bc25 CB |
46 | ret = handler->callback(handler->fd, events[i].events, |
47 | handler->data, descr); | |
018051e3 CB |
48 | if (ret == LXC_MAINLOOP_ERROR) |
49 | return -1; | |
a529bc25 | 50 | if (ret == LXC_MAINLOOP_CLOSE) |
b0a33c1e | 51 | return 0; |
b0a33c1e | 52 | } |
53 | ||
3c319edb | 54 | if (nfds == 0) |
e51d4895 DE |
55 | return 0; |
56 | ||
d066f3b8 | 57 | if (lxc_list_empty(&descr->handlers)) |
b0a33c1e | 58 | return 0; |
59 | } | |
60 | } | |
61 | ||
9d1c51d1 WB |
62 | int lxc_mainloop_add_handler_events(struct lxc_epoll_descr *descr, int fd, |
63 | int events, | |
64 | lxc_mainloop_callback_t callback, | |
65 | void *data) | |
b0a33c1e | 66 | { |
eafc1bb6 CB |
67 | __do_free struct mainloop_handler *handler = NULL; |
68 | __do_free struct lxc_list *item = NULL; | |
d066f3b8 | 69 | struct epoll_event ev; |
1126d148 | 70 | |
4879faff | 71 | if (fd < 0) |
72 | return -1; | |
b0a33c1e | 73 | |
74 | handler = malloc(sizeof(*handler)); | |
75 | if (!handler) | |
76 | return -1; | |
77 | ||
78 | handler->callback = callback; | |
79 | handler->fd = fd; | |
80 | handler->data = data; | |
81 | ||
9d1c51d1 | 82 | ev.events = events; |
d066f3b8 | 83 | ev.data.ptr = handler; |
b0a33c1e | 84 | |
d066f3b8 | 85 | if (epoll_ctl(descr->epfd, EPOLL_CTL_ADD, fd, &ev) < 0) |
eafc1bb6 | 86 | return -errno; |
b0a33c1e | 87 | |
d066f3b8 CC |
88 | item = malloc(sizeof(*item)); |
89 | if (!item) | |
eafc1bb6 | 90 | return ret_errno(ENOMEM); |
b0a33c1e | 91 | |
eafc1bb6 CB |
92 | item->elem = move_ptr(handler); |
93 | lxc_list_add(&descr->handlers, move_ptr(item)); | |
3ce45e64 | 94 | return 0; |
b0a33c1e | 95 | } |
96 | ||
9d1c51d1 WB |
97 | int lxc_mainloop_add_handler(struct lxc_epoll_descr *descr, int fd, |
98 | lxc_mainloop_callback_t callback, void *data) | |
99 | { | |
100 | return lxc_mainloop_add_handler_events(descr, fd, EPOLLIN, callback, | |
101 | data); | |
102 | } | |
103 | ||
b0a33c1e | 104 | int lxc_mainloop_del_handler(struct lxc_epoll_descr *descr, int fd) |
105 | { | |
9227a12a | 106 | struct mainloop_handler *handler; |
d066f3b8 | 107 | struct lxc_list *iterator; |
b0a33c1e | 108 | |
d066f3b8 CC |
109 | lxc_list_for_each(iterator, &descr->handlers) { |
110 | handler = iterator->elem; | |
b0a33c1e | 111 | |
d066f3b8 CC |
112 | if (handler->fd == fd) { |
113 | /* found */ | |
114 | if (epoll_ctl(descr->epfd, EPOLL_CTL_DEL, fd, NULL)) | |
eafc1bb6 | 115 | return -errno; |
b0a33c1e | 116 | |
d066f3b8 CC |
117 | lxc_list_del(iterator); |
118 | free(iterator->elem); | |
119 | free(iterator); | |
120 | return 0; | |
b0a33c1e | 121 | } |
b0a33c1e | 122 | } |
123 | ||
eafc1bb6 | 124 | return ret_errno(EINVAL); |
b0a33c1e | 125 | } |
126 | ||
a9e61274 | 127 | int lxc_mainloop_open(struct lxc_epoll_descr *descr) |
b0a33c1e | 128 | { |
12c2798e | 129 | descr->epfd = epoll_create1(EPOLL_CLOEXEC); |
b0a33c1e | 130 | if (descr->epfd < 0) |
eafc1bb6 | 131 | return -errno; |
b0a33c1e | 132 | |
d066f3b8 | 133 | lxc_list_init(&descr->handlers); |
b0a33c1e | 134 | return 0; |
135 | } | |
136 | ||
eafc1bb6 | 137 | void lxc_mainloop_close(struct lxc_epoll_descr *descr) |
b0a33c1e | 138 | { |
d066f3b8 CC |
139 | struct lxc_list *iterator, *next; |
140 | ||
141 | iterator = descr->handlers.next; | |
142 | while (iterator != &descr->handlers) { | |
143 | next = iterator->next; | |
b0a33c1e | 144 | |
d066f3b8 CC |
145 | lxc_list_del(iterator); |
146 | free(iterator->elem); | |
147 | free(iterator); | |
148 | iterator = next; | |
149 | } | |
b0a33c1e | 150 | |
eafc1bb6 | 151 | close_prot_errno_disarm(descr->epfd); |
b0a33c1e | 152 | } |