}
if (siginfo.ssi_signo == SIGHUP) {
- if (hdlr->proc_pidfd >= 0)
+ if (hdlr->pidfd >= 0)
+ lxc_raw_pidfd_send_signal(hdlr->pidfd, SIGTERM, NULL, 0);
+ else if (hdlr->proc_pidfd >= 0)
lxc_raw_pidfd_send_signal(hdlr->proc_pidfd, SIGTERM, NULL, 0);
else
kill(hdlr->pid, SIGTERM);
}
if (siginfo.ssi_signo != SIGCHLD) {
- if (hdlr->proc_pidfd >= 0)
+ if (hdlr->pidfd >= 0)
+ lxc_raw_pidfd_send_signal(hdlr->pidfd,
+ siginfo.ssi_signo, NULL, 0);
+ else if (hdlr->proc_pidfd >= 0)
lxc_raw_pidfd_send_signal(hdlr->proc_pidfd,
siginfo.ssi_signo, NULL, 0);
else
handler->pinfd = -1;
+ handler->pidfd = -EBADF;
+
handler->proc_pidfd = -EBADF;
handler->sigfd = -1;
if (handler->pinfd >= 0)
close(handler->pinfd);
+ if (handler->pidfd >= 0)
+ close(handler->pidfd);
+
if (handler->proc_pidfd >= 0)
close(handler->proc_pidfd);
handler->conf = conf;
handler->lxcpath = lxcpath;
handler->pinfd = -1;
+ handler->pidfd = -EBADF;
handler->proc_pidfd = -EBADF;
handler->sigfd = -EBADF;
handler->init_died = false;
void lxc_abort(const char *name, struct lxc_handler *handler)
{
- int ret, status;
+ int ret = 0;
+ int status;
lxc_set_state(name, handler, ABORTING);
- if (handler->pid > 0) {
+ if (handler->pidfd > 0)
+ ret = lxc_raw_pidfd_send_signal(handler->pidfd, SIGKILL, NULL, 0);
+ else if (handler->proc_pidfd > 0)
ret = lxc_raw_pidfd_send_signal(handler->proc_pidfd, SIGKILL, NULL, 0);
- if (ret < 0)
- SYSERROR("Failed to send SIGKILL to %d", handler->pid);
- }
+ else if (handler->pid > 0)
+ ret = kill(handler->pid, SIGKILL);
+ if (ret < 0)
+ SYSERROR("Failed to send SIGKILL to %d", handler->pid);
- while ((ret = waitpid(-1, &status, 0)) > 0) {
- ;
- }
+ do {
+ ret = waitpid(-1, &status, 0);
+ } while (ret > 0);
}
static int do_start(void *data)
ATTR_UNUSED __do_close_prot_errno int data_sock0 = handler->data_sock[0],
data_sock1 = handler->data_sock[1];
int ret;
- char path[PATH_MAX];
uid_t new_uid;
gid_t new_gid;
struct lxc_list *iterator;
goto out_warn_father;
}
- ret = snprintf(path, sizeof(path), "%s/dev/null",
- handler->conf->rootfs.mount);
- if (ret < 0 || ret >= sizeof(path))
- goto out_warn_father;
-
/* In order to checkpoint restore, we need to have everything in the
* same mount namespace. However, some containers may not have a
* reasonable /dev (in particular, they may not have /dev/null), so we
* where it isn't wanted.
*/
if (handler->daemonize && !handler->conf->autodev) {
+ char path[PATH_MAX];
+
+ ret = snprintf(path, sizeof(path), "%s/dev/null",
+ handler->conf->rootfs.mount);
+ if (ret < 0 || ret >= sizeof(path))
+ goto out_warn_father;
+
ret = access(path, F_OK);
if (ret != 0) {
devnull_fd = open_devnull();
flags = handler->ns_on_clone_flags;
flags |= CLONE_PARENT;
- handler->pid = lxc_raw_clone_cb(do_start, handler, flags, NULL);
+ handler->pid = lxc_raw_clone_cb(do_start, handler, CLONE_PIDFD | flags,
+ &handler->pidfd);
if (handler->pid < 0)
return -1;
pid_t attacher_pid;
attacher_pid = lxc_clone(do_share_ns, handler,
- CLONE_VFORK | CLONE_VM | CLONE_FILES);
+ CLONE_VFORK | CLONE_VM | CLONE_FILES, NULL);
if (attacher_pid < 0) {
SYSERROR(LXC_CLONE_ERROR);
goto out_delete_net;
}
} else {
handler->pid = lxc_raw_clone_cb(do_start, handler,
- handler->ns_on_clone_flags, NULL);
+ CLONE_PIDFD | handler->ns_on_clone_flags,
+ &handler->pidfd);
}
if (handler->pid < 0) {
SYSERROR(LXC_CLONE_ERROR);
}
TRACE("Cloned child process %d", handler->pid);
- handler->proc_pidfd = proc_pidfd_open(handler->pid);
- if (handler->proc_pidfd < 0 && (errno != ENOSYS))
- goto out_delete_net;
+ if (handler->pidfd < 0) {
+ handler->proc_pidfd = proc_pidfd_open(handler->pid);
+ if (handler->proc_pidfd < 0 && (errno != ENOSYS))
+ goto out_delete_net;
+ }
for (i = 0; i < LXC_NS_MAX; i++)
if (handler->ns_on_clone_flags & ns_info[i].clone_flag)
if (!cgroup_ops->chown(cgroup_ops, handler->conf))
goto out_delete_net;
- /* Now we're ready to preserve the network namespace */
- ret = lxc_try_preserve_ns(handler->pid, "net");
- if (ret < 0) {
- if (ret != -EOPNOTSUPP) {
- SYSERROR("Failed to preserve net namespace");
- goto out_delete_net;
+ /* If not done yet, we're now ready to preserve the network namespace */
+ if (handler->nsfd[LXC_NS_NET] < 0) {
+ ret = lxc_try_preserve_ns(handler->pid, "net");
+ if (ret < 0) {
+ if (ret != -EOPNOTSUPP) {
+ SYSERROR("Failed to preserve net namespace");
+ goto out_delete_net;
+ }
+ } else {
+ handler->nsfd[LXC_NS_NET] = ret;
+ DEBUG("Preserved net namespace via fd %d", ret);
}
- } else {
- handler->nsfd[LXC_NS_NET] = ret;
- DEBUG("Preserved net namespace via fd %d", ret);
-
- ret = lxc_netns_set_nsid(handler->nsfd[LXC_NS_NET]);
- if (ret < 0)
- SYSWARN("Failed to allocate new network namespace id");
- else
- TRACE("Allocated new network namespace id");
}
+ ret = lxc_netns_set_nsid(handler->nsfd[LXC_NS_NET]);
+ if (ret < 0)
+ SYSWARN("Failed to allocate new network namespace id");
+ else
+ TRACE("Allocated new network namespace id");
/* Create the network configuration. */
if (handler->ns_clone_flags & CLONE_NEWNET) {
ret = lxc_init(name, handler);
if (ret < 0) {
ERROR("Failed to initialize container \"%s\"", name);
- return -1;
+ goto out_fini_nonet;
}
handler->ops = ops;
handler->data = data;