]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/mainloop.c
storage/dir: cleanup mount code
[mirror_lxc.git] / src / lxc / mainloop.c
CommitLineData
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 17struct 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 25int 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
62int 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
97int 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 104int 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 127int 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 137void 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}