int lxc_poll(const char *name, struct lxc_handler *handler) { int sigfd = handler->sigfd; int pid = handler->pid; struct lxc_epoll_descr descr; if (lxc_mainloop_open(&descr)) { ERROR("Failed to create LXC mainloop."); goto out_sigfd; } if (lxc_mainloop_add_handler(&descr, sigfd, signal_handler, &pid)) { ERROR("Failed to add signal handler with file descriptor %d to LXC mainloop.", sigfd); goto out_mainloop_open; } if (lxc_console_mainloop_add(&descr, handler->conf)) { ERROR("Failed to add console handler to LXC mainloop."); goto out_mainloop_open; } if (lxc_cmd_mainloop_add(name, &descr, handler)) { ERROR("Failed to add command handler to LXC mainloop."); goto out_mainloop_open; } if (handler->conf->need_utmp_watch) { #if HAVE_SYS_CAPABILITY_H if (lxc_utmp_mainloop_add(&descr, handler)) { ERROR("Failed to add utmp handler to LXC mainloop."); goto out_mainloop_open; } #else DEBUG("Not starting utmp handler as CAP_SYS_BOOT cannot be dropped without capabilities support."); #endif } return lxc_mainloop(&descr, -1); out_mainloop_open: lxc_mainloop_close(&descr); out_sigfd: close(sigfd); return -1; }
int main(int argc, char *argv[]) { int ret,pipefd; char *lxcpath = argv[1]; char logpath[PATH_MAX]; sigset_t mask; 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); } ret = snprintf(logpath, sizeof(logpath), "%s/lxc-monitord.log", lxcpath); if (ret < 0 || ret >= sizeof(logpath)) return EXIT_FAILURE; ret = lxc_log_init(NULL, logpath, "NOTICE", "lxc-monitord", 0, lxcpath); if (ret) INFO("Failed to open log file %s, log will be lost", lxcpath); pipefd = atoi(argv[2]); if (sigfillset(&mask) || sigdelset(&mask, SIGILL) || sigdelset(&mask, SIGSEGV) || sigdelset(&mask, SIGBUS) || sigdelset(&mask, SIGTERM) || sigprocmask(SIG_BLOCK, &mask, NULL)) { SYSERROR("failed to set signal mask"); return -1; } signal(SIGILL, lxc_monitord_sig_handler); signal(SIGSEGV, lxc_monitord_sig_handler); signal(SIGBUS, lxc_monitord_sig_handler); signal(SIGTERM, lxc_monitord_sig_handler); ret = EXIT_FAILURE; memset(&mon, 0, sizeof(mon)); mon.lxcpath = lxcpath; if (lxc_mainloop_open(&mon.descr)) { ERROR("failed to create mainloop"); goto out; } if (lxc_monitord_create(&mon)) { goto out; } /* 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 (write(pipefd, "S", 1)) ; close(pipefd); if (lxc_monitord_mainloop_add(&mon)) { ERROR("failed to add mainloop handlers"); goto out; } NOTICE("monitoring lxcpath %s", mon.lxcpath); for(;;) { ret = lxc_mainloop(&mon.descr, 1000 * 30); if (mon.clientfds_cnt <= 0) { NOTICE("no clients for 30 seconds, exiting"); break; } } lxc_mainloop_close(&mon.descr); lxc_monitord_cleanup(); ret = EXIT_SUCCESS; NOTICE("monitor exiting"); out: return ret; }
int main(int argc, char *argv[]) { int ret, pipefd; char logpath[PATH_MAX]; sigset_t mask; char *lxcpath = argv[1]; bool mainloop_opened = false; bool monitord_created = false; struct lxc_log log; 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); } 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; 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 (lxc_safe_int(argv[2], &pipefd) < 0) exit(EXIT_FAILURE); if (sigfillset(&mask) || sigdelset(&mask, SIGILL) || sigdelset(&mask, SIGSEGV) || sigdelset(&mask, SIGBUS) || sigdelset(&mask, SIGTERM) || pthread_sigmask(SIG_BLOCK, &mask, NULL)) { SYSERROR("Failed to set signal mask"); exit(EXIT_FAILURE); } signal(SIGILL, lxc_monitord_sig_handler); signal(SIGSEGV, lxc_monitord_sig_handler); signal(SIGBUS, lxc_monitord_sig_handler); signal(SIGTERM, lxc_monitord_sig_handler); if (sigsetjmp(mark, 1) != 0) goto on_signal; ret = EXIT_FAILURE; memset(&mon, 0, sizeof(mon)); mon.lxcpath = lxcpath; if (lxc_mainloop_open(&mon.descr)) { ERROR("Failed to create mainloop"); goto on_error; } mainloop_opened = true; if (lxc_monitord_create(&mon)) 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 (lxc_monitord_mainloop_add(&mon)) { ERROR("Failed to add mainloop handlers"); goto on_error; } NOTICE("lxc-monitord with pid %d is now monitoring lxcpath %s", lxc_raw_getpid(), mon.lxcpath); for (;;) { ret = lxc_mainloop(&mon.descr, 1000 * 30); if (ret) { ERROR("mainloop returned an error"); break; } if (mon.clientfds_cnt <= 0) { NOTICE("No remaining clients. lxc-monitord is exiting"); break; } if (quit == LXC_MAINLOOP_CLOSE) { NOTICE("Got quit command. lxc-monitord is exitting"); break; } } on_signal: ret = EXIT_SUCCESS; on_error: if (monitord_created) lxc_monitord_cleanup(); if (mainloop_opened) lxc_mainloop_close(&mon.descr); exit(ret); }