void lxc_fini(const char *name, struct lxc_handler *handler) { /* The STOPPING state is there for future cleanup code * which can take awhile */ lxc_set_state(name, handler, STOPPING); lxc_set_state(name, handler, STOPPED); if (run_lxc_hooks(name, "post-stop", handler->conf, handler->lxcpath, NULL)) ERROR("failed to run post-stop hooks for container '%s'.", name); /* reset mask set by setup_signal_fd */ if (sigprocmask(SIG_SETMASK, &handler->oldmask, NULL)) WARN("failed to restore sigprocmask"); lxc_console_delete(&handler->conf->console); lxc_delete_tty(&handler->conf->tty_info); close(handler->conf->maincmd_fd); handler->conf->maincmd_fd = -1; free(handler->name); if (handler->ttysock[0] != -1) { close(handler->ttysock[0]); close(handler->ttysock[1]); } cgroup_destroy(handler); free(handler); }
void lxc_fini(const char *name, struct lxc_handler *handler) { int i, rc; pid_t self = getpid(); char *namespaces[LXC_NS_MAX+1]; size_t namespace_count = 0; /* The STOPPING state is there for future cleanup code * which can take awhile */ lxc_set_state(name, handler, STOPPING); for (i = 0; i < LXC_NS_MAX; i++) { if (handler->nsfd[i] != -1) { rc = asprintf(&namespaces[namespace_count], "%s:/proc/%d/fd/%d", ns_info[i].proc_name, self, handler->nsfd[i]); if (rc == -1) { SYSERROR("failed to allocate memory"); break; } ++namespace_count; } } namespaces[namespace_count] = NULL; if (run_lxc_hooks(name, "stop", handler->conf, handler->lxcpath, namespaces)) ERROR("failed to run stop hooks for container '%s'.", name); while (namespace_count--) free(namespaces[namespace_count]); for (i = 0; i < LXC_NS_MAX; i++) { if (handler->nsfd[i] != -1) { close(handler->nsfd[i]); handler->nsfd[i] = -1; } } lxc_set_state(name, handler, STOPPED); if (run_lxc_hooks(name, "post-stop", handler->conf, handler->lxcpath, NULL)) ERROR("failed to run post-stop hooks for container '%s'.", name); /* reset mask set by setup_signal_fd */ if (sigprocmask(SIG_SETMASK, &handler->oldmask, NULL)) WARN("failed to restore sigprocmask"); lxc_console_delete(&handler->conf->console); lxc_delete_tty(&handler->conf->tty_info); close(handler->conf->maincmd_fd); handler->conf->maincmd_fd = -1; free(handler->name); if (handler->ttysock[0] != -1) { close(handler->ttysock[0]); close(handler->ttysock[1]); } if (handler->conf->ephemeral == 1 && handler->conf->reboot != 1) { lxc_destroy_container_on_signal(handler, name); } cgroup_destroy(handler); free(handler); }
void lxc_abort(const char *name, struct lxc_handler *handler) { int ret, status; lxc_set_state(name, handler, ABORTING); if (handler->pid > 0) kill(handler->pid, SIGKILL); while ((ret = waitpid(-1, &status, 0)) > 0) ; }
struct lxc_handler *lxc_init(const char *name, struct lxc_conf *conf, const char *lxcpath) { struct lxc_handler *handler; handler = malloc(sizeof(*handler)); if (!handler) return NULL; memset(handler, 0, sizeof(*handler)); handler->ttysock[0] = handler->ttysock[1] = -1; handler->conf = conf; handler->lxcpath = lxcpath; handler->pinfd = -1; lsm_init(); handler->name = strdup(name); if (!handler->name) { ERROR("failed to allocate memory"); goto out_free; } if (lxc_cmd_init(name, handler, lxcpath)) goto out_free_name; if (lxc_read_seccomp_config(conf) != 0) { ERROR("failed loading seccomp policy"); goto out_close_maincmd_fd; } /* Begin by setting the state to STARTING */ if (lxc_set_state(name, handler, STARTING)) { ERROR("failed to set state '%s'", lxc_state2str(STARTING)); goto out_close_maincmd_fd; } /* Start of environment variable setup for hooks */ if (name && setenv("LXC_NAME", name, 1)) { SYSERROR("failed to set environment variable for container name"); } if (conf->rcfile && setenv("LXC_CONFIG_FILE", conf->rcfile, 1)) { SYSERROR("failed to set environment variable for config path"); } if (conf->rootfs.mount && setenv("LXC_ROOTFS_MOUNT", conf->rootfs.mount, 1)) { SYSERROR("failed to set environment variable for rootfs mount"); } if (conf->rootfs.path && setenv("LXC_ROOTFS_PATH", conf->rootfs.path, 1)) { SYSERROR("failed to set environment variable for rootfs mount"); } if (conf->console.path && setenv("LXC_CONSOLE", conf->console.path, 1)) { SYSERROR("failed to set environment variable for console path"); } if (conf->console.log_path && setenv("LXC_CONSOLE_LOGPATH", conf->console.log_path, 1)) { SYSERROR("failed to set environment variable for console log"); } /* End of environment variable setup for hooks */ if (run_lxc_hooks(name, "pre-start", conf, handler->lxcpath, NULL)) { ERROR("failed to run pre-start hooks for container '%s'.", name); goto out_aborting; } /* the signal fd has to be created before forking otherwise * if the child process exits before we setup the signal fd, * the event will be lost and the command will be stuck */ handler->sigfd = setup_signal_fd(&handler->oldmask); if (handler->sigfd < 0) { ERROR("failed to set sigchild fd handler"); goto out_delete_tty; } /* do this after setting up signals since it might unblock SIGWINCH */ if (lxc_console_create(conf)) { ERROR("failed to create console"); goto out_restore_sigmask; } if (ttys_shift_ids(conf) < 0) { ERROR("Failed to shift tty into container"); goto out_restore_sigmask; } INFO("'%s' is initialized", name); return handler; out_restore_sigmask: sigprocmask(SIG_SETMASK, &handler->oldmask, NULL); out_delete_tty: lxc_delete_tty(&conf->tty_info); out_aborting: lxc_set_state(name, handler, ABORTING); out_close_maincmd_fd: close(conf->maincmd_fd); conf->maincmd_fd = -1; out_free_name: free(handler->name); handler->name = NULL; out_free: free(handler); return NULL; }
void lxc_fini(const char *name, struct lxc_handler *handler) { int i, rc; pid_t self = getpid(); char *namespaces[LXC_NS_MAX+1]; size_t namespace_count = 0; /* The STOPPING state is there for future cleanup code which can take * awhile. */ lxc_set_state(name, handler, STOPPING); for (i = 0; i < LXC_NS_MAX; i++) { if (handler->nsfd[i] != -1) { rc = asprintf(&namespaces[namespace_count], "%s:/proc/%d/fd/%d", ns_info[i].proc_name, self, handler->nsfd[i]); if (rc == -1) { SYSERROR("Failed to allocate memory."); break; } ++namespace_count; } } namespaces[namespace_count] = NULL; if (handler->conf->reboot && setenv("LXC_TARGET", "reboot", 1)) SYSERROR("Failed to set environment variable: LXC_TARGET=reboot."); if (!handler->conf->reboot && setenv("LXC_TARGET", "stop", 1)) SYSERROR("Failed to set environment variable: LXC_TARGET=stop."); if (run_lxc_hooks(name, "stop", handler->conf, handler->lxcpath, namespaces)) ERROR("Failed to run lxc.hook.stop for container \"%s\".", name); while (namespace_count--) free(namespaces[namespace_count]); for (i = 0; i < LXC_NS_MAX; i++) { if (handler->nsfd[i] != -1) { close(handler->nsfd[i]); handler->nsfd[i] = -1; } } if (handler->netnsfd >= 0) { close(handler->netnsfd); handler->netnsfd = -1; } lxc_set_state(name, handler, STOPPED); if (run_lxc_hooks(name, "post-stop", handler->conf, handler->lxcpath, NULL)) { ERROR("Failed to run lxc.hook.post-stop for container \"%s\".", name); if (handler->conf->reboot) { WARN("Container will be stopped instead of rebooted."); handler->conf->reboot = 0; if (setenv("LXC_TARGET", "stop", 1)) WARN("Failed to set environment variable: LXC_TARGET=stop."); } } /* Reset mask set by setup_signal_fd. */ if (sigprocmask(SIG_SETMASK, &handler->oldmask, NULL)) WARN("Failed to restore signal mask."); lxc_console_delete(&handler->conf->console); lxc_delete_tty(&handler->conf->tty_info); close(handler->conf->maincmd_fd); handler->conf->maincmd_fd = -1; free(handler->name); if (handler->ttysock[0] != -1) { close(handler->ttysock[0]); close(handler->ttysock[1]); } if (handler->conf->ephemeral == 1 && handler->conf->reboot != 1) lxc_destroy_container_on_signal(handler, name); cgroup_destroy(handler); free(handler); }
struct lxc_handler *lxc_init(const char *name, struct lxc_conf *conf, const char *lxcpath) { int i; struct lxc_handler *handler; handler = malloc(sizeof(*handler)); if (!handler) return NULL; memset(handler, 0, sizeof(*handler)); handler->ttysock[0] = handler->ttysock[1] = -1; handler->conf = conf; handler->lxcpath = lxcpath; handler->pinfd = -1; for (i = 0; i < LXC_NS_MAX; i++) handler->nsfd[i] = -1; lsm_init(); handler->name = strdup(name); if (!handler->name) { ERROR("Failed to allocate memory."); goto out_free; } if (lxc_cmd_init(name, handler, lxcpath)) goto out_free_name; if (lxc_read_seccomp_config(conf) != 0) { ERROR("Failed loading seccomp policy."); goto out_close_maincmd_fd; } /* Begin by setting the state to STARTING. */ if (lxc_set_state(name, handler, STARTING)) { ERROR("Failed to set state for container \"%s\" to \"%s\".", name, lxc_state2str(STARTING)); goto out_close_maincmd_fd; } /* Start of environment variable setup for hooks. */ if (name && setenv("LXC_NAME", name, 1)) SYSERROR("Failed to set environment variable: LXC_NAME=%s.", name); if (conf->rcfile && setenv("LXC_CONFIG_FILE", conf->rcfile, 1)) SYSERROR("Failed to set environment variable: LXC_CONFIG_FILE=%s.", conf->rcfile); if (conf->rootfs.mount && setenv("LXC_ROOTFS_MOUNT", conf->rootfs.mount, 1)) SYSERROR("Failed to set environment variable: LXC_ROOTFS_MOUNT=%s.", conf->rootfs.mount); if (conf->rootfs.path && setenv("LXC_ROOTFS_PATH", conf->rootfs.path, 1)) SYSERROR("Failed to set environment variable: LXC_ROOTFS_PATH=%s.", conf->rootfs.path); if (conf->console.path && setenv("LXC_CONSOLE", conf->console.path, 1)) SYSERROR("Failed to set environment variable: LXC_CONSOLE=%s.", conf->console.path); if (conf->console.log_path && setenv("LXC_CONSOLE_LOGPATH", conf->console.log_path, 1)) SYSERROR("Failed to set environment variable: LXC_CONSOLE_LOGPATH=%s.", conf->console.log_path); if (setenv("LXC_CGNS_AWARE", "1", 1)) SYSERROR("Failed to set environment variable LXC_CGNS_AWARE=1."); /* End of environment variable setup for hooks. */ if (run_lxc_hooks(name, "pre-start", conf, handler->lxcpath, NULL)) { ERROR("Failed to run lxc.hook.pre-start for container \"%s\".", name); goto out_aborting; } /* The signal fd has to be created before forking otherwise if the child * process exits before we setup the signal fd, the event will be lost * and the command will be stuck. */ handler->sigfd = setup_signal_fd(&handler->oldmask); if (handler->sigfd < 0) { ERROR("Failed to setup SIGCHLD fd handler."); goto out_delete_tty; } /* Do this after setting up signals since it might unblock SIGWINCH. */ if (lxc_console_create(conf)) { ERROR("Failed to create console for container \"%s\".", name); goto out_restore_sigmask; } if (ttys_shift_ids(conf) < 0) { ERROR("Failed to shift tty into container."); goto out_restore_sigmask; } INFO("Container \"%s\" is initialized.", name); return handler; out_restore_sigmask: sigprocmask(SIG_SETMASK, &handler->oldmask, NULL); out_delete_tty: lxc_delete_tty(&conf->tty_info); out_aborting: lxc_set_state(name, handler, ABORTING); out_close_maincmd_fd: close(conf->maincmd_fd); conf->maincmd_fd = -1; out_free_name: free(handler->name); handler->name = NULL; out_free: free(handler); return NULL; }