]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/mainloop.c
utils: Add lxc_append_paths to join two paths.
[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 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <unistd.h>
29 #include <sys/epoll.h>
30
31 #include "mainloop.h"
32
33 struct mainloop_handler {
34 lxc_mainloop_callback_t callback;
35 int fd;
36 void *data;
37 };
38
39 #define MAX_EVENTS 10
40
41 int lxc_mainloop(struct lxc_epoll_descr *descr, int timeout_ms)
42 {
43 int i, nfds;
44 struct mainloop_handler *handler;
45 struct epoll_event events[MAX_EVENTS];
46
47 for (;;) {
48
49 nfds = epoll_wait(descr->epfd, events, MAX_EVENTS, timeout_ms);
50 if (nfds < 0) {
51 if (errno == EINTR)
52 continue;
53 return -1;
54 }
55
56 for (i = 0; i < nfds; i++) {
57 handler =
58 (struct mainloop_handler *) events[i].data.ptr;
59
60 /* If the handler returns a positive value, exit
61 the mainloop */
62 if (handler->callback(handler->fd, handler->data,
63 descr) > 0)
64 return 0;
65 }
66
67 if (nfds == 0 && timeout_ms != 0)
68 return 0;
69
70 if (lxc_list_empty(&descr->handlers))
71 return 0;
72 }
73 }
74
75 int lxc_mainloop_add_handler(struct lxc_epoll_descr *descr, int fd,
76 lxc_mainloop_callback_t callback, void *data)
77 {
78 struct epoll_event ev;
79 struct mainloop_handler *handler;
80 struct lxc_list *item;
81
82 handler = malloc(sizeof(*handler));
83 if (!handler)
84 return -1;
85
86 handler->callback = callback;
87 handler->fd = fd;
88 handler->data = data;
89
90 ev.events = EPOLLIN;
91 ev.data.ptr = handler;
92
93 if (epoll_ctl(descr->epfd, EPOLL_CTL_ADD, fd, &ev) < 0)
94 goto out_free_handler;
95
96 item = malloc(sizeof(*item));
97 if (!item)
98 goto out_free_handler;
99
100 item->elem = handler;
101 lxc_list_add(&descr->handlers, item);
102 return 0;
103
104 out_free_handler:
105 free(handler);
106 return -1;
107 }
108
109 int lxc_mainloop_del_handler(struct lxc_epoll_descr *descr, int fd)
110 {
111 struct mainloop_handler *handler;
112 struct lxc_list *iterator;
113
114 lxc_list_for_each(iterator, &descr->handlers) {
115 handler = iterator->elem;
116
117 if (handler->fd == fd) {
118 /* found */
119 if (epoll_ctl(descr->epfd, EPOLL_CTL_DEL, fd, NULL))
120 return -1;
121
122 lxc_list_del(iterator);
123 free(iterator->elem);
124 free(iterator);
125 return 0;
126 }
127 }
128
129 return -1;
130 }
131
132 int lxc_mainloop_open(struct lxc_epoll_descr *descr)
133 {
134 /* hint value passed to epoll create */
135 descr->epfd = epoll_create(2);
136 if (descr->epfd < 0)
137 return -1;
138
139 if (fcntl(descr->epfd, F_SETFD, FD_CLOEXEC)) {
140 close(descr->epfd);
141 return -1;
142 }
143
144 lxc_list_init(&descr->handlers);
145 return 0;
146 }
147
148 int lxc_mainloop_close(struct lxc_epoll_descr *descr)
149 {
150 struct lxc_list *iterator, *next;
151
152 iterator = descr->handlers.next;
153 while (iterator != &descr->handlers) {
154 next = iterator->next;
155
156 lxc_list_del(iterator);
157 free(iterator->elem);
158 free(iterator);
159 iterator = next;
160 }
161
162 return close(descr->epfd);
163 }
164