2020-01-05 22:20:49 -05:00
|
|
|
From 1c8e603aed10f387d6f74b51551c76c0154e1ad5 Mon Sep 17 00:00:00 2001
|
2019-09-30 11:03:07 -04:00
|
|
|
From: LiFeng <lifeng68@huawei.com>
|
|
|
|
|
Date: Mon, 14 Jan 2019 04:29:40 -0500
|
2020-01-05 22:20:49 -05:00
|
|
|
Subject: [PATCH 021/138] lxc-attch: add error message
|
2019-09-30 11:03:07 -04:00
|
|
|
|
|
|
|
|
Signed-off-by: LiFeng <lifeng68@huawei.com>
|
|
|
|
|
---
|
2020-01-05 22:20:49 -05:00
|
|
|
src/lxc/attach.c | 49 +++++++++++++++++++++++++++++++++++++++++-----
|
2019-09-30 11:03:07 -04:00
|
|
|
src/lxc/attach.h | 4 ++--
|
2020-01-05 22:20:49 -05:00
|
|
|
src/lxc/attach_options.h | 6 +++---
|
|
|
|
|
src/lxc/conf.c | 27 +++++++++++++++++++++----
|
2019-09-30 11:03:07 -04:00
|
|
|
src/lxc/conf.h | 3 +++
|
|
|
|
|
src/lxc/lxccontainer.c | 4 ++--
|
2020-01-05 22:20:49 -05:00
|
|
|
src/lxc/tools/lxc_attach.c | 8 ++++----
|
2019-09-30 11:03:07 -04:00
|
|
|
src/lxc/tools/lxc_ls.c | 4 ++--
|
2020-01-05 22:20:49 -05:00
|
|
|
src/lxc/utils.c | 21 ++++++++++++++++++++
|
2019-09-30 11:03:07 -04:00
|
|
|
src/lxc/utils.h | 1 +
|
|
|
|
|
10 files changed, 105 insertions(+), 22 deletions(-)
|
|
|
|
|
|
|
|
|
|
diff --git a/src/lxc/attach.c b/src/lxc/attach.c
|
2020-01-05 22:20:49 -05:00
|
|
|
index 1886bde..570b9d0 100644
|
2019-09-30 11:03:07 -04:00
|
|
|
--- a/src/lxc/attach.c
|
|
|
|
|
+++ b/src/lxc/attach.c
|
|
|
|
|
@@ -757,10 +757,15 @@ static int attach_child_main(struct attach_clone_payload *payload)
|
|
|
|
|
gid_t ns_root_gid = 0;
|
|
|
|
|
lxc_attach_options_t* options = payload->options;
|
|
|
|
|
struct lxc_proc_context_info* init_ctx = payload->init_ctx;
|
|
|
|
|
+ int msg_fd = -1;
|
|
|
|
|
bool needs_lsm = (options->namespaces & CLONE_NEWNS) &&
|
|
|
|
|
(options->attach_flags & LXC_ATTACH_LSM) &&
|
|
|
|
|
init_ctx->lsm_label;
|
|
|
|
|
|
|
|
|
|
+ /*isulad: record errpipe fd*/
|
|
|
|
|
+ msg_fd = init_ctx->container->lxc_conf->errpipe[1];
|
|
|
|
|
+ init_ctx->container->lxc_conf->errpipe[1] = -1;
|
|
|
|
|
+
|
|
|
|
|
/* A description of the purpose of this functionality is provided in the
|
|
|
|
|
* lxc-attach(1) manual page. We have to remount here and not in the
|
|
|
|
|
* parent process, otherwise /proc may not properly reflect the new pid
|
|
|
|
|
@@ -980,7 +985,7 @@ static int attach_child_main(struct attach_clone_payload *payload)
|
|
|
|
|
goto on_error;
|
|
|
|
|
|
|
|
|
|
/* We're done, so we can now do whatever the user intended us to do. */
|
|
|
|
|
- _exit(payload->exec_function(payload->exec_payload));
|
|
|
|
|
+ _exit(payload->exec_function(payload->exec_payload, msg_fd));
|
|
|
|
|
|
|
|
|
|
on_error:
|
|
|
|
|
lxc_put_attach_clone_payload(payload);
|
|
|
|
|
@@ -1085,7 +1090,7 @@ static inline void lxc_attach_terminal_close_log(struct lxc_terminal *terminal)
|
|
|
|
|
|
|
|
|
|
int lxc_attach(const char *name, const char *lxcpath,
|
|
|
|
|
lxc_attach_exec_t exec_function, void *exec_payload,
|
|
|
|
|
- lxc_attach_options_t *options, pid_t *attached_process)
|
|
|
|
|
+ lxc_attach_options_t *options, pid_t *attached_process, char **err_msg)
|
|
|
|
|
{
|
|
|
|
|
int i, ret, status;
|
|
|
|
|
int ipc_sockets[2];
|
|
|
|
|
@@ -1268,6 +1273,15 @@ int lxc_attach(const char *name, const char *lxcpath,
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
|
+ /* isulad: pipdfd for get error message of child or grandchild process. */
|
|
|
|
|
+ if (pipe2(conf->errpipe, O_CLOEXEC) != 0) {
|
|
|
|
|
+ SYSERROR("Failed to init errpipe");
|
|
|
|
|
+ free(cwd);
|
|
|
|
|
+ lxc_proc_put_context_info(init_ctx);
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
/* Create intermediate subprocess, two reasons:
|
|
|
|
|
* 1. We can't setns() in the child itself, since we want to make
|
|
|
|
|
* sure we are properly attached to the pidns.
|
|
|
|
|
@@ -1291,6 +1305,11 @@ int lxc_attach(const char *name, const char *lxcpath,
|
|
|
|
|
/* close unneeded file descriptors */
|
|
|
|
|
close(ipc_sockets[1]);
|
|
|
|
|
free(cwd);
|
|
|
|
|
+
|
|
|
|
|
+ /* isulad: close errpipe */
|
|
|
|
|
+ close(conf->errpipe[1]);
|
|
|
|
|
+ conf->errpipe[1] = -1;
|
|
|
|
|
+
|
|
|
|
|
lxc_proc_close_ns_fd(init_ctx);
|
|
|
|
|
if (options->attach_flags & LXC_ATTACH_TERMINAL)
|
|
|
|
|
lxc_attach_terminal_close_slave(&terminal);
|
|
|
|
|
@@ -1399,6 +1418,19 @@ int lxc_attach(const char *name, const char *lxcpath,
|
|
|
|
|
|
|
|
|
|
*attached_process = attached_pid;
|
|
|
|
|
|
|
|
|
|
+ /* isulad: read error msg from pipe */
|
|
|
|
|
+ ssize_t size_read;
|
|
|
|
|
+ char errbuf[BUFSIZ + 1] = {0};
|
|
|
|
|
+
|
|
|
|
|
+ size_read = read(conf->errpipe[0], errbuf, BUFSIZ);
|
|
|
|
|
+ if (size_read > 0) {
|
|
|
|
|
+ if (err_msg)
|
|
|
|
|
+ *err_msg = strdup(errbuf);
|
|
|
|
|
+ if (!(*err_msg))
|
|
|
|
|
+ ERROR("Out of memory");
|
|
|
|
|
+ goto close_mainloop;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
/* Now shut down communication with child, we're done. */
|
|
|
|
|
shutdown(ipc_sockets[0], SHUT_RDWR);
|
|
|
|
|
close(ipc_sockets[0]);
|
|
|
|
|
@@ -1439,7 +1471,11 @@ int lxc_attach(const char *name, const char *lxcpath,
|
|
|
|
|
|
|
|
|
|
/* close unneeded file descriptors */
|
|
|
|
|
close(ipc_sockets[0]);
|
|
|
|
|
- ipc_sockets[0] = -EBADF;
|
|
|
|
|
+ ipc_sockets[0] = -EBADF;\
|
|
|
|
|
+
|
|
|
|
|
+ /* isulad: close errpipe */
|
|
|
|
|
+ close(conf->errpipe[0]);
|
|
|
|
|
+ conf->errpipe[0] = -1;
|
|
|
|
|
|
|
|
|
|
if (options->attach_flags & LXC_ATTACH_TERMINAL) {
|
|
|
|
|
lxc_attach_terminal_close_master(&terminal);
|
|
|
|
|
@@ -1539,7 +1575,7 @@ int lxc_attach(const char *name, const char *lxcpath,
|
|
|
|
|
_exit(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
-int lxc_attach_run_command(void *payload)
|
|
|
|
|
+int lxc_attach_run_command(void *payload, int msg_fd)
|
|
|
|
|
{
|
|
|
|
|
int ret = -1;
|
|
|
|
|
lxc_attach_command_t *cmd = payload;
|
|
|
|
|
@@ -1556,11 +1592,14 @@ int lxc_attach_run_command(void *payload)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /* isulad: write errorm messages */
|
|
|
|
|
+ lxc_write_error_message(msg_fd, "exec: \"%s\": %s", cmd->program, strerror(errno));
|
|
|
|
|
+
|
|
|
|
|
SYSERROR("Failed to exec \"%s\"", cmd->program);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
-int lxc_attach_run_shell(void* payload)
|
|
|
|
|
+int lxc_attach_run_shell(void* payload, int msg_fd)
|
|
|
|
|
{
|
|
|
|
|
uid_t uid;
|
|
|
|
|
struct passwd pwent;
|
|
|
|
|
diff --git a/src/lxc/attach.h b/src/lxc/attach.h
|
2020-01-05 22:20:49 -05:00
|
|
|
index 4bf9578..e62b98b 100644
|
2019-09-30 11:03:07 -04:00
|
|
|
--- a/src/lxc/attach.h
|
|
|
|
|
+++ b/src/lxc/attach.h
|
|
|
|
|
@@ -42,7 +42,7 @@ struct lxc_proc_context_info {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
extern int lxc_attach(const char *name, const char *lxcpath,
|
|
|
|
|
- lxc_attach_exec_t exec_function, void *exec_payload,
|
|
|
|
|
- lxc_attach_options_t *options, pid_t *attached_process);
|
|
|
|
|
+ lxc_attach_exec_t exec_function, void *exec_payload,
|
|
|
|
|
+ lxc_attach_options_t *options, pid_t *attached_process, char **err_msg);
|
|
|
|
|
|
|
|
|
|
#endif /* __LXC_ATTACH_H */
|
|
|
|
|
diff --git a/src/lxc/attach_options.h b/src/lxc/attach_options.h
|
2020-01-05 22:20:49 -05:00
|
|
|
index 081618c..7b0a8cb 100644
|
2019-09-30 11:03:07 -04:00
|
|
|
--- a/src/lxc/attach_options.h
|
|
|
|
|
+++ b/src/lxc/attach_options.h
|
|
|
|
|
@@ -71,7 +71,7 @@ enum {
|
|
|
|
|
*
|
|
|
|
|
* \return Function should return \c 0 on success, and any other value to denote failure.
|
|
|
|
|
*/
|
|
|
|
|
-typedef int (*lxc_attach_exec_t)(void* payload);
|
|
|
|
|
+typedef int (*lxc_attach_exec_t)(void* payload, int msg_fd);
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* LXC attach options for \ref lxc_container \c attach().
|
|
|
|
|
@@ -173,7 +173,7 @@ typedef struct lxc_attach_command_t {
|
|
|
|
|
*
|
|
|
|
|
* \return \c -1 on error, exit code of lxc_attach_command_t program on success.
|
|
|
|
|
*/
|
|
|
|
|
-extern int lxc_attach_run_command(void* payload);
|
|
|
|
|
+extern int lxc_attach_run_command(void* payload, int msg_fd);
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* \brief Run a shell command in the container.
|
|
|
|
|
@@ -182,7 +182,7 @@ extern int lxc_attach_run_command(void* payload);
|
|
|
|
|
*
|
|
|
|
|
* \return Exit code of shell.
|
|
|
|
|
*/
|
|
|
|
|
-extern int lxc_attach_run_shell(void* payload);
|
|
|
|
|
+extern int lxc_attach_run_shell(void* payload, int msg_fd);
|
|
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
}
|
|
|
|
|
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
|
2020-01-05 22:20:49 -05:00
|
|
|
index 537f956..8d8230f 100644
|
2019-09-30 11:03:07 -04:00
|
|
|
--- a/src/lxc/conf.c
|
|
|
|
|
+++ b/src/lxc/conf.c
|
|
|
|
|
@@ -2803,10 +2803,6 @@ struct lxc_conf *lxc_conf_init(void)
|
|
|
|
|
new->console.slave = -1;
|
|
|
|
|
new->console.name[0] = '\0';
|
|
|
|
|
memset(&new->console.ringbuf, 0, sizeof(struct lxc_ringbuf));
|
|
|
|
|
- /* isulad init console fifos */
|
|
|
|
|
- new->console.init_fifo[0] = NULL;
|
|
|
|
|
- new->console.init_fifo[1] = NULL;
|
|
|
|
|
- lxc_list_init(&new->console.fifos);
|
|
|
|
|
new->maincmd_fd = -1;
|
|
|
|
|
new->nbd_idx = -1;
|
|
|
|
|
new->rootfs.mount = strdup(default_rootfs_mount);
|
|
|
|
|
@@ -2851,6 +2847,14 @@ struct lxc_conf *lxc_conf_init(void)
|
|
|
|
|
lxc_list_init(&new->rootfs.maskedpaths);
|
|
|
|
|
lxc_list_init(&new->rootfs.ropaths);
|
|
|
|
|
new->exit_fd = -1;
|
|
|
|
|
+ /* isulad init console fifos */
|
|
|
|
|
+ new->console.init_fifo[0] = NULL;
|
|
|
|
|
+ new->console.init_fifo[1] = NULL;
|
|
|
|
|
+ lxc_list_init(&new->console.fifos);
|
|
|
|
|
+
|
|
|
|
|
+ new->errmsg = NULL;
|
|
|
|
|
+ new->errpipe[0] = -1;
|
|
|
|
|
+ new->errpipe[1] = -1;
|
|
|
|
|
/* isulad add end */
|
|
|
|
|
|
|
|
|
|
return new;
|
|
|
|
|
@@ -4280,6 +4284,19 @@ int lxc_clear_rootfs_ro_paths(struct lxc_conf *c)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+/*isulad: close error pipe */
|
|
|
|
|
+void lxc_close_error_pipe(int *errpipe)
|
|
|
|
|
+{
|
|
|
|
|
+ if (errpipe[0] >= 0) {
|
|
|
|
|
+ close(errpipe[0]);
|
|
|
|
|
+ errpipe[0] = -1;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (errpipe[1] >= 0) {
|
|
|
|
|
+ close(errpipe[1]);
|
|
|
|
|
+ errpipe[1] = -1;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
void lxc_conf_free(struct lxc_conf *conf)
|
|
|
|
|
{
|
|
|
|
|
if (!conf)
|
|
|
|
|
@@ -4333,6 +4350,8 @@ void lxc_conf_free(struct lxc_conf *conf)
|
|
|
|
|
free(conf->container_info_file);
|
|
|
|
|
if (conf->exit_fd != -1)
|
|
|
|
|
close(conf->exit_fd);
|
|
|
|
|
+ free(conf->errmsg);
|
|
|
|
|
+ lxc_close_error_pipe(conf->errpipe);
|
|
|
|
|
/* isulad add end */
|
|
|
|
|
free(conf);
|
|
|
|
|
}
|
|
|
|
|
diff --git a/src/lxc/conf.h b/src/lxc/conf.h
|
2020-01-05 22:20:49 -05:00
|
|
|
index 7927812..db474e1 100644
|
2019-09-30 11:03:07 -04:00
|
|
|
--- a/src/lxc/conf.h
|
|
|
|
|
+++ b/src/lxc/conf.h
|
|
|
|
|
@@ -413,6 +413,9 @@ struct lxc_conf {
|
|
|
|
|
char *container_info_file;
|
|
|
|
|
|
|
|
|
|
int exit_fd; /* exit fifo fd*/
|
|
|
|
|
+
|
|
|
|
|
+ char *errmsg; /* record error messages */
|
|
|
|
|
+ int errpipe[2];//pipdfd for get error message of child or grandchild process.
|
|
|
|
|
/* isulad add end */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
|
2020-01-05 22:20:49 -05:00
|
|
|
index 8029f33..31f4819 100644
|
2019-09-30 11:03:07 -04:00
|
|
|
--- a/src/lxc/lxccontainer.c
|
|
|
|
|
+++ b/src/lxc/lxccontainer.c
|
|
|
|
|
@@ -4063,7 +4063,7 @@ static int lxcapi_attach(struct lxc_container *c, lxc_attach_exec_t exec_functio
|
|
|
|
|
|
|
|
|
|
current_config = c->lxc_conf;
|
|
|
|
|
|
|
|
|
|
- ret = lxc_attach(c->name, c->config_path, exec_function, exec_payload, options, attached_process);
|
|
|
|
|
+ ret = lxc_attach(c->name, c->config_path, exec_function, exec_payload, options, attached_process, &c->lxc_conf->errmsg);
|
|
|
|
|
current_config = NULL;
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
@@ -4080,7 +4080,7 @@ static int do_lxcapi_attach_run_wait(struct lxc_container *c, lxc_attach_options
|
|
|
|
|
command.program = (char*)program;
|
|
|
|
|
command.argv = (char**)argv;
|
|
|
|
|
|
|
|
|
|
- r = lxc_attach(c->name, c->config_path, lxc_attach_run_command, &command, options, &pid);
|
|
|
|
|
+ r = lxc_attach(c->name, c->config_path, lxc_attach_run_command, &command, options, &pid, NULL);
|
|
|
|
|
if (r < 0) {
|
|
|
|
|
ERROR("ups");
|
|
|
|
|
return r;
|
|
|
|
|
diff --git a/src/lxc/tools/lxc_attach.c b/src/lxc/tools/lxc_attach.c
|
2020-01-05 22:20:49 -05:00
|
|
|
index 6d0ffe5..a590fd1 100644
|
2019-09-30 11:03:07 -04:00
|
|
|
--- a/src/lxc/tools/lxc_attach.c
|
|
|
|
|
+++ b/src/lxc/tools/lxc_attach.c
|
|
|
|
|
@@ -295,8 +295,8 @@ static int do_attach_foreground(struct lxc_container *c, lxc_attach_command_t *c
|
|
|
|
|
wexit = ExitSignalOffset + signal;
|
|
|
|
|
}
|
|
|
|
|
out:
|
|
|
|
|
- //if (c->lxc_conf->errmsg)
|
|
|
|
|
- // *errmsg = strdup(c->lxc_conf->errmsg);
|
|
|
|
|
+ if (c->lxc_conf->errmsg)
|
|
|
|
|
+ *errmsg = strdup(c->lxc_conf->errmsg);
|
|
|
|
|
return wexit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -376,8 +376,8 @@ static int do_attach_background(struct lxc_container *c, lxc_attach_command_t *c
|
|
|
|
|
else
|
|
|
|
|
ret = c->attach(c, lxc_attach_run_shell, NULL, attach_options, &pid);
|
|
|
|
|
if (ret < 0) {
|
|
|
|
|
- //if (c->lxc_conf->errmsg)
|
|
|
|
|
- // lxc_write_error_message(msgpipe[1], "%s", c->lxc_conf->errmsg);
|
|
|
|
|
+ if (c->lxc_conf->errmsg)
|
|
|
|
|
+ lxc_write_error_message(msgpipe[1], "%s", c->lxc_conf->errmsg);
|
|
|
|
|
close(msgpipe[1]);
|
|
|
|
|
msgpipe[1] = -1;
|
|
|
|
|
ret = -1;
|
|
|
|
|
diff --git a/src/lxc/tools/lxc_ls.c b/src/lxc/tools/lxc_ls.c
|
2020-01-05 22:20:49 -05:00
|
|
|
index cb3eb1e..e261c7b 100644
|
2019-09-30 11:03:07 -04:00
|
|
|
--- a/src/lxc/tools/lxc_ls.c
|
|
|
|
|
+++ b/src/lxc/tools/lxc_ls.c
|
|
|
|
|
@@ -122,7 +122,7 @@ struct wrapargs {
|
|
|
|
|
/*
|
|
|
|
|
* Takes struct wrapargs as argument.
|
|
|
|
|
*/
|
|
|
|
|
-static int ls_get_wrapper(void *wrap);
|
|
|
|
|
+static int ls_get_wrapper(void *wrap, int msgfd);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* To calculate swap usage we should not simply check memory.usage_in_bytes and
|
|
|
|
|
@@ -1023,7 +1023,7 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
-static int ls_get_wrapper(void *wrap)
|
|
|
|
|
+static int ls_get_wrapper(void *wrap, int msgfd)
|
|
|
|
|
{
|
|
|
|
|
int ret = -1;
|
|
|
|
|
size_t len = 0;
|
|
|
|
|
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
|
2020-01-05 22:20:49 -05:00
|
|
|
index 74e74a1..8ec9f46 100644
|
2019-09-30 11:03:07 -04:00
|
|
|
--- a/src/lxc/utils.c
|
|
|
|
|
+++ b/src/lxc/utils.c
|
|
|
|
|
@@ -1971,3 +1971,24 @@ out:
|
|
|
|
|
return startat;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+/* isulad: write error message */
|
|
|
|
|
+void lxc_write_error_message(int errfd, const char *format, ...)
|
|
|
|
|
+{
|
|
|
|
|
+ int ret;
|
|
|
|
|
+ char errbuf[BUFSIZ + 1] = {0};
|
|
|
|
|
+ ssize_t sret;
|
|
|
|
|
+ va_list argp;
|
|
|
|
|
+
|
|
|
|
|
+ if (errfd <= 0)
|
|
|
|
|
+ return;
|
|
|
|
|
+
|
|
|
|
|
+ va_start(argp, format);
|
|
|
|
|
+ ret = vsnprintf(errbuf, BUFSIZ, format, argp);
|
|
|
|
|
+ va_end(argp);
|
|
|
|
|
+ if (ret < 0)
|
|
|
|
|
+ SYSERROR("Failed to call vsnprintf");
|
|
|
|
|
+ sret = write(errfd, errbuf, strlen(errbuf));
|
|
|
|
|
+ if (sret < 0)
|
|
|
|
|
+ SYSERROR("Write errbuf failed");
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
|
2020-01-05 22:20:49 -05:00
|
|
|
index 364bf67..3d56fd9 100644
|
2019-09-30 11:03:07 -04:00
|
|
|
--- a/src/lxc/utils.h
|
|
|
|
|
+++ b/src/lxc/utils.h
|
|
|
|
|
@@ -314,5 +314,6 @@ extern int lxc_setup_env_home(uid_t uid);
|
|
|
|
|
|
|
|
|
|
extern int fd_nonblock(int fd);
|
|
|
|
|
extern int unsigned long long lxc_get_process_startat(pid_t pid);
|
|
|
|
|
+extern void lxc_write_error_message(int errfd, const char *format, ...);
|
|
|
|
|
|
|
|
|
|
#endif /* __LXC_UTILS_H */
|
|
|
|
|
--
|
2020-01-05 22:20:49 -05:00
|
|
|
1.8.3.1
|
2019-09-30 11:03:07 -04:00
|
|
|
|