mirror of
git://github.com/lxc/lxc
synced 2025-09-01 14:09:29 +00:00
Merge pull request #1255 from brauner/2016-10-27/cleanup_netdevs_lxd#2439_lxc#1253
remove veth device from host
This commit is contained in:
@@ -220,9 +220,8 @@ static void lxc_proc_put_context_info(struct lxc_proc_context_info *ctx)
|
|||||||
|
|
||||||
static int lxc_attach_to_ns(pid_t pid, int which)
|
static int lxc_attach_to_ns(pid_t pid, int which)
|
||||||
{
|
{
|
||||||
char path[MAXPATHLEN];
|
|
||||||
/* according to <http://article.gmane.org/gmane.linux.kernel.containers.lxc.devel/1429>,
|
/* according to <http://article.gmane.org/gmane.linux.kernel.containers.lxc.devel/1429>,
|
||||||
* the file for user namepsaces in /proc/$pid/ns will be called
|
* the file for user namespaces in /proc/$pid/ns will be called
|
||||||
* 'user' once the kernel supports it
|
* 'user' once the kernel supports it
|
||||||
*/
|
*/
|
||||||
static char *ns[] = { "user", "mnt", "pid", "uts", "ipc", "net", "cgroup" };
|
static char *ns[] = { "user", "mnt", "pid", "uts", "ipc", "net", "cgroup" };
|
||||||
@@ -235,8 +234,7 @@ static int lxc_attach_to_ns(pid_t pid, int which)
|
|||||||
int i, j, saved_errno;
|
int i, j, saved_errno;
|
||||||
|
|
||||||
|
|
||||||
snprintf(path, MAXPATHLEN, "/proc/%d/ns", pid);
|
if (access("/proc/self/ns", X_OK)) {
|
||||||
if (access(path, X_OK)) {
|
|
||||||
ERROR("Does this kernel version support 'attach' ?");
|
ERROR("Does this kernel version support 'attach' ?");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -250,8 +248,7 @@ static int lxc_attach_to_ns(pid_t pid, int which)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(path, MAXPATHLEN, "/proc/%d/ns/%s", pid, ns[i]);
|
fd[i] = lxc_preserve_ns(pid, ns[i]);
|
||||||
fd[i] = open(path, O_RDONLY | O_CLOEXEC);
|
|
||||||
if (fd[i] < 0) {
|
if (fd[i] < 0) {
|
||||||
saved_errno = errno;
|
saved_errno = errno;
|
||||||
|
|
||||||
@@ -262,7 +259,7 @@ static int lxc_attach_to_ns(pid_t pid, int which)
|
|||||||
close(fd[j]);
|
close(fd[j]);
|
||||||
|
|
||||||
errno = saved_errno;
|
errno = saved_errno;
|
||||||
SYSERROR("failed to open '%s'", path);
|
SYSERROR("failed to open namespace: '%s'.", ns[i]);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2399,24 +2399,20 @@ static int setup_network(struct lxc_list *network)
|
|||||||
/* try to move physical nics to the init netns */
|
/* try to move physical nics to the init netns */
|
||||||
void lxc_restore_phys_nics_to_netns(int netnsfd, struct lxc_conf *conf)
|
void lxc_restore_phys_nics_to_netns(int netnsfd, struct lxc_conf *conf)
|
||||||
{
|
{
|
||||||
int i, ret, oldfd;
|
int i, oldfd;
|
||||||
char path[MAXPATHLEN];
|
|
||||||
char ifname[IFNAMSIZ];
|
char ifname[IFNAMSIZ];
|
||||||
|
|
||||||
if (netnsfd < 0 || conf->num_savednics == 0)
|
if (netnsfd < 0 || conf->num_savednics == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
INFO("running to reset %d nic names", conf->num_savednics);
|
INFO("Running to reset %d nic names.", conf->num_savednics);
|
||||||
|
|
||||||
ret = snprintf(path, MAXPATHLEN, "/proc/self/ns/net");
|
oldfd = lxc_preserve_ns(getpid(), "net");
|
||||||
if (ret < 0 || ret >= MAXPATHLEN) {
|
if (oldfd < 0) {
|
||||||
WARN("Failed to open monitor netns fd");
|
SYSERROR("Failed to open monitor netns fd.");
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ((oldfd = open(path, O_RDONLY)) < 0) {
|
|
||||||
SYSERROR("Failed to open monitor netns fd");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setns(netnsfd, 0) != 0) {
|
if (setns(netnsfd, 0) != 0) {
|
||||||
SYSERROR("Failed to enter container netns to reset nics");
|
SYSERROR("Failed to enter container netns to reset nics");
|
||||||
close(oldfd);
|
close(oldfd);
|
||||||
@@ -2591,6 +2587,7 @@ static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
|
|||||||
veth1, netdev->link, strerror(-err));
|
veth1, netdev->link, strerror(-err));
|
||||||
goto out_delete;
|
goto out_delete;
|
||||||
}
|
}
|
||||||
|
INFO("Attached '%s': to the bridge '%s': ", veth1, netdev->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
err = lxc_netdev_up(veth1);
|
err = lxc_netdev_up(veth1);
|
||||||
@@ -2883,36 +2880,83 @@ int lxc_create_network(struct lxc_handler *handler)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lxc_delete_network(struct lxc_handler *handler)
|
bool lxc_delete_network(struct lxc_handler *handler)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
struct lxc_list *network = &handler->conf->network;
|
struct lxc_list *network = &handler->conf->network;
|
||||||
struct lxc_list *iterator;
|
struct lxc_list *iterator;
|
||||||
struct lxc_netdev *netdev;
|
struct lxc_netdev *netdev;
|
||||||
|
bool deleted_all = true;
|
||||||
|
|
||||||
lxc_list_for_each(iterator, network) {
|
lxc_list_for_each(iterator, network) {
|
||||||
netdev = iterator->elem;
|
netdev = iterator->elem;
|
||||||
|
|
||||||
if (netdev->ifindex != 0 && netdev->type == LXC_NET_PHYS) {
|
if (netdev->ifindex != 0 && netdev->type == LXC_NET_PHYS) {
|
||||||
if (lxc_netdev_rename_by_index(netdev->ifindex, netdev->link))
|
if (lxc_netdev_rename_by_index(netdev->ifindex, netdev->link))
|
||||||
WARN("failed to rename to the initial name the " \
|
WARN("Failed to rename interface with index %d "
|
||||||
"netdev '%s'", netdev->link);
|
"to its initial name \"%s\".",
|
||||||
|
netdev->ifindex, netdev->link);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (netdev_deconf[netdev->type](handler, netdev)) {
|
if (netdev_deconf[netdev->type](handler, netdev)) {
|
||||||
WARN("failed to destroy netdev");
|
WARN("Failed to destroy netdev");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Recent kernel remove the virtual interfaces when the network
|
/* Recent kernel remove the virtual interfaces when the network
|
||||||
* namespace is destroyed but in case we did not moved the
|
* namespace is destroyed but in case we did not moved the
|
||||||
* interface to the network namespace, we have to destroy it
|
* interface to the network namespace, we have to destroy it
|
||||||
*/
|
*/
|
||||||
if (netdev->ifindex != 0 &&
|
if (netdev->ifindex != 0) {
|
||||||
lxc_netdev_delete_by_index(netdev->ifindex))
|
ret = lxc_netdev_delete_by_index(netdev->ifindex);
|
||||||
WARN("failed to remove interface %d '%s'",
|
if (-ret == ENODEV) {
|
||||||
netdev->ifindex,
|
INFO("Interface \"%s\" with index %d already "
|
||||||
netdev->name ? netdev->name : "(null)");
|
"deleted or existing in different network "
|
||||||
|
"namespace.",
|
||||||
|
netdev->name ? netdev->name : "(null)",
|
||||||
|
netdev->ifindex);
|
||||||
|
} else if (ret < 0) {
|
||||||
|
deleted_all = false;
|
||||||
|
WARN("Failed to remove interface \"%s\" with "
|
||||||
|
"index %d: %s.",
|
||||||
|
netdev->name ? netdev->name : "(null)",
|
||||||
|
netdev->ifindex, strerror(-ret));
|
||||||
|
} else {
|
||||||
|
INFO("Removed interface \"%s\" with index %d.",
|
||||||
|
netdev->name ? netdev->name : "(null)",
|
||||||
|
netdev->ifindex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Explicitly delete host veth device to prevent lingering
|
||||||
|
* devices. We had issues in LXD around this.
|
||||||
|
*/
|
||||||
|
if (netdev->type == LXC_NET_VETH) {
|
||||||
|
char *hostveth;
|
||||||
|
if (netdev->priv.veth_attr.pair) {
|
||||||
|
hostveth = netdev->priv.veth_attr.pair;
|
||||||
|
ret = lxc_netdev_delete_by_name(hostveth);
|
||||||
|
if (ret < 0) {
|
||||||
|
WARN("Failed to remove interface \"%s\" from host: %s.", hostveth, strerror(-ret));
|
||||||
|
} else {
|
||||||
|
INFO("Removed interface \"%s\" from host.", hostveth);
|
||||||
|
free(netdev->priv.veth_attr.pair);
|
||||||
|
netdev->priv.veth_attr.pair = NULL;
|
||||||
|
}
|
||||||
|
} else if (strlen(netdev->priv.veth_attr.veth1) > 0) {
|
||||||
|
hostveth = netdev->priv.veth_attr.veth1;
|
||||||
|
ret = lxc_netdev_delete_by_name(hostveth);
|
||||||
|
if (ret < 0) {
|
||||||
|
WARN("Failed to remove \"%s\" from host: %s.", hostveth, strerror(-ret));
|
||||||
|
} else {
|
||||||
|
INFO("Removed interface \"%s\" from host.", hostveth);
|
||||||
|
memset((void *)&netdev->priv.veth_attr.veth1, 0, sizeof(netdev->priv.veth_attr.veth1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return deleted_all;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LXC_USERNIC_PATH LIBEXECDIR "/lxc/lxc-user-nic"
|
#define LXC_USERNIC_PATH LIBEXECDIR "/lxc/lxc-user-nic"
|
||||||
@@ -3050,7 +3094,7 @@ int lxc_assign_network(const char *lxcpath, char *lxcname,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG("move '%s' to '%d'", netdev->name, pid);
|
DEBUG("move '%s'/'%s' to '%d': .", ifname, netdev->name, pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@@ -408,7 +408,7 @@ extern int pin_rootfs(const char *rootfs);
|
|||||||
|
|
||||||
extern int lxc_requests_empty_network(struct lxc_handler *handler);
|
extern int lxc_requests_empty_network(struct lxc_handler *handler);
|
||||||
extern int lxc_create_network(struct lxc_handler *handler);
|
extern int lxc_create_network(struct lxc_handler *handler);
|
||||||
extern void lxc_delete_network(struct lxc_handler *handler);
|
extern bool lxc_delete_network(struct lxc_handler *handler);
|
||||||
extern int lxc_assign_network(const char *lxcpath, char *lxcname,
|
extern int lxc_assign_network(const char *lxcpath, char *lxcname,
|
||||||
struct lxc_list *networks, pid_t pid);
|
struct lxc_list *networks, pid_t pid);
|
||||||
extern int lxc_map_ids(struct lxc_list *idmap, pid_t pid);
|
extern int lxc_map_ids(struct lxc_list *idmap, pid_t pid);
|
||||||
|
@@ -46,13 +46,12 @@ extern int lxc_error_set_and_log(int pid, int status)
|
|||||||
if (WIFEXITED(status)) {
|
if (WIFEXITED(status)) {
|
||||||
ret = WEXITSTATUS(status);
|
ret = WEXITSTATUS(status);
|
||||||
if (ret)
|
if (ret)
|
||||||
INFO("child <%d> ended on error (%d)", pid, ret);
|
INFO("Child <%d> ended on error (%d).", pid, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WIFSIGNALED(status)) {
|
if (WIFSIGNALED(status)) {
|
||||||
int signal = WTERMSIG(status);
|
int signal = WTERMSIG(status);
|
||||||
|
INFO("Child <%d> ended on signal (%d).", pid, signal);
|
||||||
INFO("child <%d> ended on signal (%d)", pid, signal);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@@ -673,25 +673,21 @@ again:
|
|||||||
|
|
||||||
static int rename_in_ns(int pid, char *oldname, char **newnamep)
|
static int rename_in_ns(int pid, char *oldname, char **newnamep)
|
||||||
{
|
{
|
||||||
char nspath[MAXPATHLEN];
|
|
||||||
int fd = -1, ofd = -1, ret, ifindex = -1;
|
int fd = -1, ofd = -1, ret, ifindex = -1;
|
||||||
bool grab_newname = false;
|
bool grab_newname = false;
|
||||||
|
|
||||||
ret = snprintf(nspath, MAXPATHLEN, "/proc/%d/ns/net", getpid());
|
ofd = lxc_preserve_ns(getpid(), "net");
|
||||||
if (ret < 0 || ret >= MAXPATHLEN)
|
if (ofd < 0) {
|
||||||
return -1;
|
fprintf(stderr, "Failed opening network namespace path for '%d'.", getpid());
|
||||||
if ((ofd = open(nspath, O_RDONLY)) < 0) {
|
|
||||||
fprintf(stderr, "Opening %s\n", nspath);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ret = snprintf(nspath, MAXPATHLEN, "/proc/%d/ns/net", pid);
|
|
||||||
if (ret < 0 || ret >= MAXPATHLEN)
|
|
||||||
goto out_err;
|
|
||||||
|
|
||||||
if ((fd = open(nspath, O_RDONLY)) < 0) {
|
fd = lxc_preserve_ns(pid, "net");
|
||||||
fprintf(stderr, "Opening %s\n", nspath);
|
if (fd < 0) {
|
||||||
goto out_err;
|
fprintf(stderr, "Failed opening network namespace path for '%d'.", pid);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setns(fd, 0) < 0) {
|
if (setns(fd, 0) < 0) {
|
||||||
fprintf(stderr, "setns to container network namespace\n");
|
fprintf(stderr, "setns to container network namespace\n");
|
||||||
goto out_err;
|
goto out_err;
|
||||||
|
@@ -64,29 +64,29 @@ pid_t lxc_clone(int (*fn)(void *), void *arg, int flags)
|
|||||||
ret = clone(do_clone, stack + stack_size, flags | SIGCHLD, &clone_arg);
|
ret = clone(do_clone, stack + stack_size, flags | SIGCHLD, &clone_arg);
|
||||||
#endif
|
#endif
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
ERROR("failed to clone (%#x): %s", flags, strerror(errno));
|
ERROR("Failed to clone (%#x): %s.", flags, strerror(errno));
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char * const namespaces_list[] = {
|
const struct ns_info ns_info[LXC_NS_MAX] = {
|
||||||
"MOUNT", "PID", "UTSNAME", "IPC",
|
[LXC_NS_MNT] = {"mnt", CLONE_NEWNS, "CLONE_NEWNS"},
|
||||||
"USER", "NETWORK"
|
[LXC_NS_PID] = {"pid", CLONE_NEWPID, "CLONE_NEWPID"},
|
||||||
};
|
[LXC_NS_UTS] = {"uts", CLONE_NEWUTS, "CLONE_NEWUTS"},
|
||||||
static const int cloneflags_list[] = {
|
[LXC_NS_IPC] = {"ipc", CLONE_NEWIPC, "CLONE_NEWIPC"},
|
||||||
CLONE_NEWNS, CLONE_NEWPID, CLONE_NEWUTS, CLONE_NEWIPC,
|
[LXC_NS_USER] = {"user", CLONE_NEWUSER, "CLONE_NEWUSER"},
|
||||||
CLONE_NEWUSER, CLONE_NEWNET
|
[LXC_NS_NET] = {"net", CLONE_NEWNET, "CLONE_NEWNET"},
|
||||||
|
[LXC_NS_CGROUP] = {"cgroup", CLONE_NEWCGROUP, "CLONE_NEWCGROUP"}
|
||||||
};
|
};
|
||||||
|
|
||||||
int lxc_namespace_2_cloneflag(char *namespace)
|
int lxc_namespace_2_cloneflag(char *namespace)
|
||||||
{
|
{
|
||||||
int i, len;
|
int i;
|
||||||
len = sizeof(namespaces_list)/sizeof(namespaces_list[0]);
|
for (i = 0; i < LXC_NS_MAX; i++)
|
||||||
for (i = 0; i < len; i++)
|
if (!strcasecmp(ns_info[i].proc_name, namespace))
|
||||||
if (!strcmp(namespaces_list[i], namespace))
|
return ns_info[i].clone_flag;
|
||||||
return cloneflags_list[i];
|
|
||||||
|
|
||||||
ERROR("invalid namespace name %s", namespace);
|
ERROR("Invalid namespace name: %s.", namespace);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ int lxc_fill_namespace_flags(char *flaglist, int *flags)
|
|||||||
int aflag;
|
int aflag;
|
||||||
|
|
||||||
if (!flaglist) {
|
if (!flaglist) {
|
||||||
ERROR("need at least one namespace to unshare");
|
ERROR("At least one namespace is needed.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -53,6 +53,23 @@
|
|||||||
# define CLONE_NEWNET 0x40000000
|
# define CLONE_NEWNET 0x40000000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
enum {
|
||||||
|
LXC_NS_MNT,
|
||||||
|
LXC_NS_PID,
|
||||||
|
LXC_NS_UTS,
|
||||||
|
LXC_NS_IPC,
|
||||||
|
LXC_NS_USER,
|
||||||
|
LXC_NS_NET,
|
||||||
|
LXC_NS_CGROUP,
|
||||||
|
LXC_NS_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const struct ns_info {
|
||||||
|
const char *proc_name;
|
||||||
|
int clone_flag;
|
||||||
|
const char *flag_name;
|
||||||
|
} ns_info[LXC_NS_MAX];
|
||||||
|
|
||||||
#if defined(__ia64__)
|
#if defined(__ia64__)
|
||||||
int __clone2(int (*__fn) (void *__arg), void *__child_stack_base,
|
int __clone2(int (*__fn) (void *__arg), void *__child_stack_base,
|
||||||
size_t __child_stack_size, int __flags, void *__arg, ...);
|
size_t __child_stack_size, int __flags, void *__arg, ...);
|
||||||
@@ -62,7 +79,6 @@ int clone(int (*fn)(void *), void *child_stack,
|
|||||||
/* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ );
|
/* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
extern pid_t lxc_clone(int (*fn)(void *), void *arg, int flags);
|
extern pid_t lxc_clone(int (*fn)(void *), void *arg, int flags);
|
||||||
|
|
||||||
extern int lxc_namespace_2_cloneflag(char *namespace);
|
extern int lxc_namespace_2_cloneflag(char *namespace);
|
||||||
|
631
src/lxc/start.c
631
src/lxc/start.c
File diff suppressed because it is too large
Load Diff
@@ -42,24 +42,6 @@ struct lxc_operations {
|
|||||||
|
|
||||||
struct cgroup_desc;
|
struct cgroup_desc;
|
||||||
|
|
||||||
enum {
|
|
||||||
LXC_NS_MNT,
|
|
||||||
LXC_NS_PID,
|
|
||||||
LXC_NS_UTS,
|
|
||||||
LXC_NS_IPC,
|
|
||||||
LXC_NS_USER,
|
|
||||||
LXC_NS_NET,
|
|
||||||
LXC_NS_CGROUP,
|
|
||||||
LXC_NS_MAX
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ns_info {
|
|
||||||
const char *proc_name;
|
|
||||||
int clone_flag;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern const struct ns_info ns_info[LXC_NS_MAX];
|
|
||||||
|
|
||||||
struct lxc_handler {
|
struct lxc_handler {
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
char *name;
|
char *name;
|
||||||
@@ -77,6 +59,7 @@ struct lxc_handler {
|
|||||||
int ttysock[2]; // socketpair for child->parent tty fd passing
|
int ttysock[2]; // socketpair for child->parent tty fd passing
|
||||||
bool backgrounded; // indicates whether should we close std{in,out,err} on start
|
bool backgrounded; // indicates whether should we close std{in,out,err} on start
|
||||||
int nsfd[LXC_NS_MAX];
|
int nsfd[LXC_NS_MAX];
|
||||||
|
int netnsfd;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1968,3 +1968,23 @@ int lxc_append_string(char ***list, char *entry)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int lxc_preserve_ns(const int pid, const char *ns)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
/* 5 /proc + 21 /int_as_str + 3 /ns + 20 /NS_NAME + 1 \0 */
|
||||||
|
#define __NS_PATH_LEN 50
|
||||||
|
char path[__NS_PATH_LEN];
|
||||||
|
|
||||||
|
/* This way we can use this function to also check whether namespaces
|
||||||
|
* are supported by the kernel by passing in the NULL or the empty
|
||||||
|
* string.
|
||||||
|
*/
|
||||||
|
ret = snprintf(path, __NS_PATH_LEN, "/proc/%d/ns%s%s", pid,
|
||||||
|
!ns || strcmp(ns, "") == 0 ? "" : "/",
|
||||||
|
!ns || strcmp(ns, "") == 0 ? "" : ns);
|
||||||
|
if (ret < 0 || (size_t)ret >= __NS_PATH_LEN)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return open(path, O_RDONLY | O_CLOEXEC);
|
||||||
|
}
|
||||||
|
@@ -312,6 +312,7 @@ int open_devnull(void);
|
|||||||
int set_stdfds(int fd);
|
int set_stdfds(int fd);
|
||||||
int null_stdfds(void);
|
int null_stdfds(void);
|
||||||
int lxc_count_file_lines(const char *fn);
|
int lxc_count_file_lines(const char *fn);
|
||||||
|
int lxc_preserve_ns(const int pid, const char *ns);
|
||||||
|
|
||||||
/* Check whether a signal is blocked by a process. */
|
/* Check whether a signal is blocked by a process. */
|
||||||
bool task_blocking_signal(pid_t pid, int signal);
|
bool task_blocking_signal(pid_t pid, int signal);
|
||||||
|
Reference in New Issue
Block a user