#include "log.h"
#include "mainloop.h"
#include "monitor.h"
-#include "raw_syscalls.h"
+#include "process_utils.h"
#include "utils.h"
#define CLIENTFDS_CHUNK 64
sigjmp_buf mark;
-static void lxc_monitord_cleanup(void);
-
/*
* Defines the structure to store the monitor information
* @lxcpath : the path being monitored
int *clientfds;
int clientfds_size;
int clientfds_cnt;
- struct lxc_epoll_descr descr;
+ struct lxc_async_descr descr;
};
static struct lxc_monitor monitor;
return 0;
}
-static void lxc_monitord_sockfd_remove(struct lxc_monitor *mon, int fd)
+static int lxc_monitord_sockfd_remove(struct lxc_monitor *mon, int fd)
{
int i;
- if (lxc_mainloop_del_handler(&mon->descr, fd))
- CRIT("File descriptor %d not found in mainloop", fd);
- close(fd);
-
for (i = 0; i < mon->clientfds_cnt; i++)
if (mon->clientfds[i] == fd)
break;
if (i >= mon->clientfds_cnt) {
CRIT("File descriptor %d not found in clients array", fd);
- lxc_monitord_cleanup();
- exit(EXIT_FAILURE);
+ return LXC_MAINLOOP_ERROR;
}
memmove(&mon->clientfds[i], &mon->clientfds[i+1],
(mon->clientfds_cnt - i - 1) * sizeof(mon->clientfds[0]));
mon->clientfds_cnt--;
+ return LXC_MAINLOOP_DISARM;
}
static int lxc_monitord_sock_handler(int fd, uint32_t events, void *data,
- struct lxc_epoll_descr *descr)
+ struct lxc_async_descr *descr)
{
struct lxc_monitor *mon = data;
char buf[4];
rc = lxc_read_nointr(fd, buf, sizeof(buf));
- if (rc > 0 && !strncmp(buf, "quit", 4))
+ if (rc > 0 && !strncmp(buf, "quit", 4)) {
quit = LXC_MAINLOOP_CLOSE;
+ return LXC_MAINLOOP_CLOSE;
+ }
}
if (events & EPOLLHUP)
- lxc_monitord_sockfd_remove(mon, fd);
+ return lxc_monitord_sockfd_remove(mon, fd);
return quit;
}
static int lxc_monitord_sock_accept(int fd, uint32_t events, void *data,
- struct lxc_epoll_descr *descr)
+ struct lxc_async_descr *descr)
{
int ret, clientfd;
struct lxc_monitor *mon = data;
}
ret = lxc_mainloop_add_handler(&mon->descr, clientfd,
- lxc_monitord_sock_handler, mon);
+ lxc_monitord_sock_handler,
+ default_cleanup_handler,
+ mon, "lxc_monitord_sock_handler");
if (ret < 0) {
ERROR("Failed to add socket handler");
goto err1;
static void lxc_monitord_delete(struct lxc_monitor *mon)
{
- int i;
-
- lxc_mainloop_del_handler(&mon->descr, mon->listenfd);
lxc_abstract_unix_close(mon->listenfd);
lxc_monitord_sock_delete(mon);
- lxc_mainloop_del_handler(&mon->descr, mon->fifofd);
lxc_monitord_fifo_delete(mon);
close(mon->fifofd);
- for (i = 0; i < mon->clientfds_cnt; i++) {
- lxc_mainloop_del_handler(&mon->descr, mon->clientfds[i]);
+ for (int i = 0; i < mon->clientfds_cnt; i++)
close(mon->clientfds[i]);
- }
mon->clientfds_cnt = 0;
}
static int lxc_monitord_fifo_handler(int fd, uint32_t events, void *data,
- struct lxc_epoll_descr *descr)
+ struct lxc_async_descr *descr)
{
int ret, i;
struct lxc_msg msglxc;
int ret;
ret = lxc_mainloop_add_handler(&mon->descr, mon->fifofd,
- lxc_monitord_fifo_handler, mon);
+ lxc_monitord_fifo_handler,
+ default_cleanup_handler,
+ mon, "lxc_monitord_fifo_handler");
if (ret < 0) {
ERROR("Failed to add to mainloop monitor handler for fifo");
return -1;
}
ret = lxc_mainloop_add_handler(&mon->descr, mon->listenfd,
- lxc_monitord_sock_accept, mon);
+ lxc_monitord_sock_accept,
+ default_cleanup_handler,
+ mon, "lxc_monitord_sock_accept");
if (ret < 0) {
ERROR("Failed to add to mainloop monitor handler for listen socket");
return -1;
return 0;
}
-static void lxc_monitord_cleanup(void)
-{
- lxc_monitord_delete(&monitor);
-}
-
static void lxc_monitord_sig_handler(int sig)
{
siglongjmp(mark, 1);
int main(int argc, char *argv[])
{
- int ret, pipefd;
- char logpath[PATH_MAX];
+ int ret, pipefd = -1;
sigset_t mask;
- char *lxcpath = argv[1];
+ const char *lxcpath = NULL;
bool mainloop_opened = false;
bool monitord_created = false;
- struct lxc_log log;
+ bool persistent = false;
- if (argc != 3) {
- fprintf(stderr,
- "Usage: lxc-monitord lxcpath sync-pipe-fd\n\n"
- "NOTE: lxc-monitord is intended for use by lxc internally\n"
- " and does not need to be run by hand\n\n");
- exit(EXIT_FAILURE);
+ if (argc > 1 && !strcmp(argv[1], "--daemon")) {
+ persistent = true;
+ --argc;
+ ++argv;
}
- ret = snprintf(logpath, sizeof(logpath), "%s/lxc-monitord.log",
- (strcmp(LXCPATH, lxcpath) ? lxcpath : LOGPATH));
- if (ret < 0 || ret >= sizeof(logpath))
- exit(EXIT_FAILURE);
-
- log.name = NULL;
- log.file = logpath;
- log.level = "DEBUG";
- log.prefix = "lxc-monitord";
- log.quiet = 0;
- log.lxcpath = lxcpath;
+ if (argc > 1) {
+ lxcpath = argv[1];
+ --argc;
+ ++argv;
+ } else {
+ lxcpath = lxc_global_config_value("lxc.lxcpath");
+ if (!lxcpath) {
+ ERROR("Failed to get default lxcpath");
+ exit(EXIT_FAILURE);
+ }
+ }
- ret = lxc_log_init(&log);
- if (ret)
- INFO("Failed to open log file %s, log will be lost", lxcpath);
- lxc_log_options_no_override();
+ if (argc > 1) {
+ if (lxc_safe_int(argv[1], &pipefd) < 0)
+ exit(EXIT_FAILURE);
+ --argc;
+ ++argv;
+ }
- if (lxc_safe_int(argv[2], &pipefd) < 0)
+ if (argc != 1 || (persistent != (pipefd == -1))) {
+ fprintf(stderr,
+ "Usage: lxc-monitord lxcpath sync-pipe-fd\n"
+ " lxc-monitord --daemon lxcpath\n\n"
+ "NOTE: lxc-monitord is intended for use by lxc internally\n"
+ " and does not need to be run by hand\n\n");
exit(EXIT_FAILURE);
+ }
if (sigfillset(&mask) ||
sigdelset(&mask, SIGILL) ||
goto on_error;
monitord_created = true;
- /* sync with parent, we're ignoring the return from write
- * because regardless if it works or not, the following
- * close will sync us with the parent process. the
- * if-empty-statement construct is to quiet the
- * warn-unused-result warning.
- */
- if (lxc_write_nointr(pipefd, "S", 1))
- ;
- close(pipefd);
+ if (pipefd != -1) {
+ /* sync with parent, we're ignoring the return from write
+ * because regardless if it works or not, the following
+ * close will sync us with the parent process. the
+ * if-empty-statement construct is to quiet the
+ * warn-unused-result warning.
+ */
+ if (lxc_write_nointr(pipefd, "S", 1))
+ ;
+ close(pipefd);
+ }
if (lxc_monitord_mainloop_add(&monitor)) {
ERROR("Failed to add mainloop handlers");
lxc_raw_getpid(), monitor.lxcpath);
for (;;) {
- ret = lxc_mainloop(&monitor.descr, 1000 * 30);
+ ret = lxc_mainloop(&monitor.descr, persistent ? -1 : 1000 * 30);
if (ret) {
ERROR("mainloop returned an error");
break;
ret = EXIT_SUCCESS;
on_error:
- if (monitord_created)
- lxc_monitord_cleanup();
-
if (mainloop_opened)
lxc_mainloop_close(&monitor.descr);
+ if (monitord_created)
+ lxc_monitord_delete(&monitor);
+
exit(ret);
}