mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-08-14 15:29:56 +00:00
Merge pull request #2986 from brauner/2019-05-09/clone_pidfd
start: use CLONE_PIDFD
This commit is contained in:
commit
3e860bdac0
@ -4419,7 +4419,7 @@ int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), void *data,
|
|||||||
d.p[1] = p[1];
|
d.p[1] = p[1];
|
||||||
|
|
||||||
/* Clone child in new user namespace. */
|
/* Clone child in new user namespace. */
|
||||||
pid = lxc_clone(run_userns_fn, &d, CLONE_NEWUSER);
|
pid = lxc_clone(run_userns_fn, &d, CLONE_NEWUSER, NULL);
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
ERROR("Failed to clone process in new user namespace");
|
ERROR("Failed to clone process in new user namespace");
|
||||||
goto on_error;
|
goto on_error;
|
||||||
|
@ -54,7 +54,7 @@ static int do_clone(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define __LXC_STACK_SIZE 4096
|
#define __LXC_STACK_SIZE 4096
|
||||||
pid_t lxc_clone(int (*fn)(void *), void *arg, int flags)
|
pid_t lxc_clone(int (*fn)(void *), void *arg, int flags, int *pidfd)
|
||||||
{
|
{
|
||||||
size_t stack_size;
|
size_t stack_size;
|
||||||
pid_t ret;
|
pid_t ret;
|
||||||
@ -66,9 +66,9 @@ pid_t lxc_clone(int (*fn)(void *), void *arg, int flags)
|
|||||||
stack_size = __LXC_STACK_SIZE;
|
stack_size = __LXC_STACK_SIZE;
|
||||||
|
|
||||||
#ifdef __ia64__
|
#ifdef __ia64__
|
||||||
ret = __clone2(do_clone, stack, stack_size, flags | SIGCHLD, &clone_arg);
|
ret = __clone2(do_clone, stack, stack_size, flags | SIGCHLD, &clone_arg, pidfd);
|
||||||
#else
|
#else
|
||||||
ret = clone(do_clone, stack + stack_size, flags | SIGCHLD, &clone_arg);
|
ret = clone(do_clone, stack + stack_size, flags | SIGCHLD, &clone_arg, pidfd);
|
||||||
#endif
|
#endif
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
SYSERROR("Failed to clone (%#x)", flags);
|
SYSERROR("Failed to clone (%#x)", flags);
|
||||||
|
@ -133,7 +133,7 @@ int clone(int (*fn)(void *), void *child_stack,
|
|||||||
* - should call lxc_raw_getpid():
|
* - should call lxc_raw_getpid():
|
||||||
* The child should use lxc_raw_getpid() to retrieve its pid.
|
* The child should use lxc_raw_getpid() to retrieve its pid.
|
||||||
*/
|
*/
|
||||||
extern pid_t lxc_clone(int (*fn)(void *), void *arg, int flags);
|
extern pid_t lxc_clone(int (*fn)(void *), void *arg, int flags, int *pidfd);
|
||||||
|
|
||||||
extern int lxc_namespace_2_cloneflag(const char *namespace);
|
extern int lxc_namespace_2_cloneflag(const char *namespace);
|
||||||
extern int lxc_namespace_2_ns_idx(const char *namespace);
|
extern int lxc_namespace_2_ns_idx(const char *namespace);
|
||||||
|
@ -406,7 +406,9 @@ static int signal_handler(int fd, uint32_t events, void *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (siginfo.ssi_signo == SIGHUP) {
|
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);
|
lxc_raw_pidfd_send_signal(hdlr->proc_pidfd, SIGTERM, NULL, 0);
|
||||||
else
|
else
|
||||||
kill(hdlr->pid, SIGTERM);
|
kill(hdlr->pid, SIGTERM);
|
||||||
@ -416,7 +418,10 @@ static int signal_handler(int fd, uint32_t events, void *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (siginfo.ssi_signo != SIGCHLD) {
|
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,
|
lxc_raw_pidfd_send_signal(hdlr->proc_pidfd,
|
||||||
siginfo.ssi_signo, NULL, 0);
|
siginfo.ssi_signo, NULL, 0);
|
||||||
else
|
else
|
||||||
@ -665,6 +670,8 @@ void lxc_zero_handler(struct lxc_handler *handler)
|
|||||||
|
|
||||||
handler->pinfd = -1;
|
handler->pinfd = -1;
|
||||||
|
|
||||||
|
handler->pidfd = -EBADF;
|
||||||
|
|
||||||
handler->proc_pidfd = -EBADF;
|
handler->proc_pidfd = -EBADF;
|
||||||
|
|
||||||
handler->sigfd = -1;
|
handler->sigfd = -1;
|
||||||
@ -687,6 +694,9 @@ void lxc_free_handler(struct lxc_handler *handler)
|
|||||||
if (handler->pinfd >= 0)
|
if (handler->pinfd >= 0)
|
||||||
close(handler->pinfd);
|
close(handler->pinfd);
|
||||||
|
|
||||||
|
if (handler->pidfd >= 0)
|
||||||
|
close(handler->pidfd);
|
||||||
|
|
||||||
if (handler->proc_pidfd >= 0)
|
if (handler->proc_pidfd >= 0)
|
||||||
close(handler->proc_pidfd);
|
close(handler->proc_pidfd);
|
||||||
|
|
||||||
@ -734,6 +744,7 @@ struct lxc_handler *lxc_init_handler(const char *name, struct lxc_conf *conf,
|
|||||||
handler->conf = conf;
|
handler->conf = conf;
|
||||||
handler->lxcpath = lxcpath;
|
handler->lxcpath = lxcpath;
|
||||||
handler->pinfd = -1;
|
handler->pinfd = -1;
|
||||||
|
handler->pidfd = -EBADF;
|
||||||
handler->proc_pidfd = -EBADF;
|
handler->proc_pidfd = -EBADF;
|
||||||
handler->sigfd = -EBADF;
|
handler->sigfd = -EBADF;
|
||||||
handler->init_died = false;
|
handler->init_died = false;
|
||||||
@ -1096,19 +1107,23 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
|
|||||||
|
|
||||||
void lxc_abort(const char *name, struct lxc_handler *handler)
|
void lxc_abort(const char *name, struct lxc_handler *handler)
|
||||||
{
|
{
|
||||||
int ret, status;
|
int ret = 0;
|
||||||
|
int status;
|
||||||
|
|
||||||
lxc_set_state(name, handler, ABORTING);
|
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);
|
ret = lxc_raw_pidfd_send_signal(handler->proc_pidfd, SIGKILL, NULL, 0);
|
||||||
if (ret < 0)
|
else if (handler->pid > 0)
|
||||||
SYSERROR("Failed to send SIGKILL to %d", handler->pid);
|
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)
|
static int do_start(void *data)
|
||||||
@ -1601,7 +1616,8 @@ static inline int do_share_ns(void *arg)
|
|||||||
|
|
||||||
flags = handler->ns_on_clone_flags;
|
flags = handler->ns_on_clone_flags;
|
||||||
flags |= CLONE_PARENT;
|
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)
|
if (handler->pid < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -1735,7 +1751,7 @@ static int lxc_spawn(struct lxc_handler *handler)
|
|||||||
pid_t attacher_pid;
|
pid_t attacher_pid;
|
||||||
|
|
||||||
attacher_pid = lxc_clone(do_share_ns, handler,
|
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) {
|
if (attacher_pid < 0) {
|
||||||
SYSERROR(LXC_CLONE_ERROR);
|
SYSERROR(LXC_CLONE_ERROR);
|
||||||
goto out_delete_net;
|
goto out_delete_net;
|
||||||
@ -1748,7 +1764,8 @@ static int lxc_spawn(struct lxc_handler *handler)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
handler->pid = lxc_raw_clone_cb(do_start, handler,
|
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) {
|
if (handler->pid < 0) {
|
||||||
SYSERROR(LXC_CLONE_ERROR);
|
SYSERROR(LXC_CLONE_ERROR);
|
||||||
@ -1756,9 +1773,11 @@ static int lxc_spawn(struct lxc_handler *handler)
|
|||||||
}
|
}
|
||||||
TRACE("Cloned child process %d", handler->pid);
|
TRACE("Cloned child process %d", handler->pid);
|
||||||
|
|
||||||
handler->proc_pidfd = proc_pidfd_open(handler->pid);
|
if (handler->pidfd < 0) {
|
||||||
if (handler->proc_pidfd < 0 && (errno != ENOSYS))
|
handler->proc_pidfd = proc_pidfd_open(handler->pid);
|
||||||
goto out_delete_net;
|
if (handler->proc_pidfd < 0 && (errno != ENOSYS))
|
||||||
|
goto out_delete_net;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < LXC_NS_MAX; i++)
|
for (i = 0; i < LXC_NS_MAX; i++)
|
||||||
if (handler->ns_on_clone_flags & ns_info[i].clone_flag)
|
if (handler->ns_on_clone_flags & ns_info[i].clone_flag)
|
||||||
|
@ -102,6 +102,9 @@ struct lxc_handler {
|
|||||||
/* The child's pid. */
|
/* The child's pid. */
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
|
/* The child's pidfd. */
|
||||||
|
int pidfd;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* File descriptor for the /proc/<pid> directory of the container's
|
* File descriptor for the /proc/<pid> directory of the container's
|
||||||
* init process.
|
* init process.
|
||||||
|
@ -266,7 +266,7 @@ static bool clone_attach_nbd(const char *nbd, const char *path)
|
|||||||
data.nbd = nbd;
|
data.nbd = nbd;
|
||||||
data.path = path;
|
data.path = path;
|
||||||
|
|
||||||
pid = lxc_clone(do_attach_nbd, &data, CLONE_NEWPID);
|
pid = lxc_clone(do_attach_nbd, &data, CLONE_NEWPID, NULL);
|
||||||
if (pid < 0)
|
if (pid < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -388,7 +388,7 @@ int main(int argc, char *argv[])
|
|||||||
start_arg.want_hostname = my_args.want_hostname;
|
start_arg.want_hostname = my_args.want_hostname;
|
||||||
start_arg.want_default_mounts = my_args.want_default_mounts;
|
start_arg.want_default_mounts = my_args.want_default_mounts;
|
||||||
|
|
||||||
pid = lxc_clone(do_start, &start_arg, my_args.flags);
|
pid = lxc_clone(do_start, &start_arg, my_args.flags, NULL);
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
ERROR("Failed to clone");
|
ERROR("Failed to clone");
|
||||||
free_ifname_list();
|
free_ifname_list();
|
||||||
|
Loading…
Reference in New Issue
Block a user