]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/mainloop.c
Merge branch 'master' into japanese
[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 if (fd < 0)
70 return -1;
71
72 handler = malloc(sizeof(*handler));
73 if (!handler)
74 return -1;
75
76 handler->callback = callback;
77 handler->fd = fd;
78 handler->data = data;
79
80 ev.events = EPOLLIN;
81 ev.data.ptr = handler;
82
83 if (epoll_ctl(descr->epfd, EPOLL_CTL_ADD, fd, &ev) < 0)
84 goto out_free_handler;
85
86 item = malloc(sizeof(*item));
87 if (!item)
88 goto out_free_handler;
89
90 item->elem = handler;
91 lxc_list_add(&descr->handlers, item);
92 return 0;
93
94 out_free_handler:
95 free(handler);
96 return -1;
97 }
98
99 int lxc_mainloop_del_handler(struct lxc_epoll_descr *descr, int fd)
100 {
101 struct mainloop_handler *handler;
102 struct lxc_list *iterator;
103
104 lxc_list_for_each(iterator, &descr->handlers) {
105 handler = iterator->elem;
106
107 if (handler->fd == fd) {
108 /* found */
109 if (epoll_ctl(descr->epfd, EPOLL_CTL_DEL, fd, NULL))
110 return -1;
111
112 lxc_list_del(iterator);
113 free(iterator->elem);
114 free(iterator);
115 return 0;
116 }
117 }
118
119 return -1;
120 }
121
122 int lxc_mainloop_open(struct lxc_epoll_descr *descr)
123 {
124 /* hint value passed to epoll create */
125 descr->epfd = epoll_create1(EPOLL_CLOEXEC);
126 if (descr->epfd < 0)
127 return -1;
128
129 lxc_list_init(&descr->handlers);
130 return 0;
131 }
132
133 int lxc_mainloop_close(struct lxc_epoll_descr *descr)
134 {
135 struct lxc_list *iterator, *next;
136
137 iterator = descr->handlers.next;
138 while (iterator != &descr->handlers) {
139 next = iterator->next;
140
141 lxc_list_del(iterator);
142 free(iterator->elem);
143 free(iterator);
144 iterator = next;
145 }
146
147 if (descr->epfd >= 0)
148 return close(descr->epfd);
149
150 return 0;
151 }