]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/mainloop.c
c102295ef3afdb4578da0b21222fcb0b0c33163a
[mirror_lxc.git] / src / lxc / mainloop.c
1 /*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
7 * Daniel Lezcano <daniel.lezcano at free.fr>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <sys/epoll.h>
31
32 #include "mainloop.h"
33
34 struct mainloop_handler {
35 lxc_mainloop_callback_t callback;
36 int fd;
37 void *data;
38 };
39
40 #define MAX_EVENTS 10
41
42 int lxc_mainloop(struct lxc_epoll_descr *descr, int timeout_ms)
43 {
44 int i, nfds, ret;
45 struct mainloop_handler *handler;
46 struct epoll_event events[MAX_EVENTS];
47
48 for (;;) {
49 nfds = epoll_wait(descr->epfd, events, MAX_EVENTS, timeout_ms);
50 if (nfds < 0) {
51 if (errno == EINTR)
52 continue;
53
54 return -1;
55 }
56
57 for (i = 0; i < nfds; i++) {
58 handler = events[i].data.ptr;
59
60 /* If the handler returns a positive value, exit the
61 * mainloop.
62 */
63 ret = handler->callback(handler->fd, events[i].events,
64 handler->data, descr);
65 if (ret == LXC_MAINLOOP_CLOSE)
66 return 0;
67 }
68
69 if (nfds == 0)
70 return 0;
71
72 if (lxc_list_empty(&descr->handlers))
73 return 0;
74 }
75 }
76
77 int lxc_mainloop_add_handler(struct lxc_epoll_descr *descr, int fd,
78 lxc_mainloop_callback_t callback, void *data)
79 {
80 struct epoll_event ev;
81 struct mainloop_handler *handler;
82 struct lxc_list *item;
83
84 handler = malloc(sizeof(*handler));
85 if (!handler)
86 return -1;
87
88 handler->callback = callback;
89 handler->fd = fd;
90 handler->data = data;
91
92 ev.events = EPOLLIN;
93 ev.data.ptr = handler;
94
95 if (epoll_ctl(descr->epfd, EPOLL_CTL_ADD, fd, &ev) < 0)
96 goto out_free_handler;
97
98 item = malloc(sizeof(*item));
99 if (!item)
100 goto out_free_handler;
101
102 item->elem = handler;
103 lxc_list_add(&descr->handlers, item);
104 return 0;
105
106 out_free_handler:
107 free(handler);
108 return -1;
109 }
110
111 int lxc_mainloop_del_handler(struct lxc_epoll_descr *descr, int fd)
112 {
113 struct mainloop_handler *handler;
114 struct lxc_list *iterator;
115
116 lxc_list_for_each(iterator, &descr->handlers) {
117 handler = iterator->elem;
118
119 if (handler->fd == fd) {
120 /* found */
121 if (epoll_ctl(descr->epfd, EPOLL_CTL_DEL, fd, NULL))
122 return -1;
123
124 lxc_list_del(iterator);
125 free(iterator->elem);
126 free(iterator);
127 return 0;
128 }
129 }
130
131 return -1;
132 }
133
134 int lxc_mainloop_open(struct lxc_epoll_descr *descr)
135 {
136 /* hint value passed to epoll create */
137 descr->epfd = epoll_create(2);
138 if (descr->epfd < 0)
139 return -1;
140
141 if (fcntl(descr->epfd, F_SETFD, FD_CLOEXEC)) {
142 close(descr->epfd);
143 return -1;
144 }
145
146 lxc_list_init(&descr->handlers);
147 return 0;
148 }
149
150 int lxc_mainloop_close(struct lxc_epoll_descr *descr)
151 {
152 struct lxc_list *iterator, *next;
153
154 iterator = descr->handlers.next;
155 while (iterator != &descr->handlers) {
156 next = iterator->next;
157
158 lxc_list_del(iterator);
159 free(iterator->elem);
160 free(iterator);
161 iterator = next;
162 }
163
164 return close(descr->epfd);
165 }