]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/mainloop.c
Merge pull request #3204 from brauner/switch_to_spdx
[mirror_lxc.git] / src / lxc / mainloop.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #ifndef _GNU_SOURCE
4 #define _GNU_SOURCE 1
5 #endif
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/epoll.h>
12 #include <unistd.h>
13
14 #include "config.h"
15 #include "mainloop.h"
16
17 struct mainloop_handler {
18 lxc_mainloop_callback_t callback;
19 int fd;
20 void *data;
21 };
22
23 #define MAX_EVENTS 10
24
25 int lxc_mainloop(struct lxc_epoll_descr *descr, int timeout_ms)
26 {
27 int i, nfds, ret;
28 struct mainloop_handler *handler;
29 struct epoll_event events[MAX_EVENTS];
30
31 for (;;) {
32 nfds = epoll_wait(descr->epfd, events, MAX_EVENTS, timeout_ms);
33 if (nfds < 0) {
34 if (errno == EINTR)
35 continue;
36
37 return -1;
38 }
39
40 for (i = 0; i < nfds; i++) {
41 handler = events[i].data.ptr;
42
43 /* If the handler returns a positive value, exit the
44 * mainloop.
45 */
46 ret = handler->callback(handler->fd, events[i].events,
47 handler->data, descr);
48 if (ret == LXC_MAINLOOP_ERROR)
49 return -1;
50 if (ret == LXC_MAINLOOP_CLOSE)
51 return 0;
52 }
53
54 if (nfds == 0)
55 return 0;
56
57 if (lxc_list_empty(&descr->handlers))
58 return 0;
59 }
60 }
61
62 int lxc_mainloop_add_handler(struct lxc_epoll_descr *descr, int fd,
63 lxc_mainloop_callback_t callback, void *data)
64 {
65 struct epoll_event ev;
66 struct mainloop_handler *handler;
67 struct lxc_list *item;
68
69 handler = malloc(sizeof(*handler));
70 if (!handler)
71 return -1;
72
73 handler->callback = callback;
74 handler->fd = fd;
75 handler->data = data;
76
77 ev.events = EPOLLIN;
78 ev.data.ptr = handler;
79
80 if (epoll_ctl(descr->epfd, EPOLL_CTL_ADD, fd, &ev) < 0)
81 goto out_free_handler;
82
83 item = malloc(sizeof(*item));
84 if (!item)
85 goto out_free_handler;
86
87 item->elem = handler;
88 lxc_list_add(&descr->handlers, item);
89 return 0;
90
91 out_free_handler:
92 free(handler);
93 return -1;
94 }
95
96 int lxc_mainloop_del_handler(struct lxc_epoll_descr *descr, int fd)
97 {
98 struct mainloop_handler *handler;
99 struct lxc_list *iterator;
100
101 lxc_list_for_each(iterator, &descr->handlers) {
102 handler = iterator->elem;
103
104 if (handler->fd == fd) {
105 /* found */
106 if (epoll_ctl(descr->epfd, EPOLL_CTL_DEL, fd, NULL))
107 return -1;
108
109 lxc_list_del(iterator);
110 free(iterator->elem);
111 free(iterator);
112 return 0;
113 }
114 }
115
116 return -1;
117 }
118
119 int lxc_mainloop_open(struct lxc_epoll_descr *descr)
120 {
121 /* hint value passed to epoll create */
122 descr->epfd = epoll_create1(EPOLL_CLOEXEC);
123 if (descr->epfd < 0)
124 return -1;
125
126 lxc_list_init(&descr->handlers);
127 return 0;
128 }
129
130 int lxc_mainloop_close(struct lxc_epoll_descr *descr)
131 {
132 struct lxc_list *iterator, *next;
133
134 iterator = descr->handlers.next;
135 while (iterator != &descr->handlers) {
136 next = iterator->next;
137
138 lxc_list_del(iterator);
139 free(iterator->elem);
140 free(iterator);
141 iterator = next;
142 }
143
144 if (descr->epfd >= 0)
145 return close(descr->epfd);
146
147 return 0;
148 }