1313 lines
44 KiB
Diff
1313 lines
44 KiB
Diff
From aaf1b46c66aa596ec718c11c4f4270e41e7b570e Mon Sep 17 00:00:00 2001
|
|
From: zhongtao <zhongtao17@huawei.com>
|
|
Date: Tue, 7 Nov 2023 16:39:35 +0800
|
|
Subject: [PATCH 11/14] add runc attach implement
|
|
|
|
Signed-off-by: zhongtao <zhongtao17@huawei.com>
|
|
---
|
|
.../connect/grpc/grpc_containers_client.cc | 9 +
|
|
src/cmd/isula/stream/attach.c | 12 +-
|
|
src/cmd/isulad-shim/common.c | 116 ++++-
|
|
src/cmd/isulad-shim/common.h | 30 ++
|
|
src/cmd/isulad-shim/main.c | 14 +
|
|
src/cmd/isulad-shim/process.c | 453 ++++++++++++++++--
|
|
src/cmd/isulad-shim/process.h | 7 +-
|
|
src/cmd/isulad-shim/terminal.c | 2 +-
|
|
.../executor/container_cb/execution_stream.c | 1 +
|
|
src/daemon/modules/api/runtime_api.h | 1 +
|
|
.../modules/runtime/isula/isula_rt_ops.c | 168 ++++++-
|
|
src/utils/cutils/error.h | 4 +-
|
|
12 files changed, 755 insertions(+), 62 deletions(-)
|
|
|
|
diff --git a/src/client/connect/grpc/grpc_containers_client.cc b/src/client/connect/grpc/grpc_containers_client.cc
|
|
index 2dd73100..bcb1e8da 100644
|
|
--- a/src/client/connect/grpc/grpc_containers_client.cc
|
|
+++ b/src/client/connect/grpc/grpc_containers_client.cc
|
|
@@ -1394,6 +1394,8 @@ public:
|
|
auto run(const struct isula_attach_request *request, struct isula_attach_response *response) -> int override
|
|
{
|
|
ClientContext context;
|
|
+ bool detach = false;
|
|
+ std::string attach_detach_msg = "read escape sequence";
|
|
|
|
if (set_custom_header_metadata(context, request) != 0) {
|
|
ERROR("Failed to translate request to grpc");
|
|
@@ -1415,6 +1417,9 @@ public:
|
|
break;
|
|
}
|
|
if (!stream_response.stdout().empty()) {
|
|
+ if (strcmp(stream_response.stdout().c_str(), attach_detach_msg.c_str()) == 0) {
|
|
+ detach = true;
|
|
+ }
|
|
std::cout << stream_response.stdout() << std::flush;
|
|
}
|
|
if (!stream_response.stderr().empty()) {
|
|
@@ -1437,6 +1442,10 @@ public:
|
|
response->cc = ISULAD_ERR_EXEC;
|
|
}
|
|
|
|
+ if (detach) {
|
|
+ response->server_errono = ISULAD_INFO_DETACH;
|
|
+ }
|
|
+
|
|
out:
|
|
if (request->attach_stdin) {
|
|
pthread_cancel(writer.native_handle());
|
|
diff --git a/src/cmd/isula/stream/attach.c b/src/cmd/isula/stream/attach.c
|
|
index ff49af92..b61c9350 100644
|
|
--- a/src/cmd/isula/stream/attach.c
|
|
+++ b/src/cmd/isula/stream/attach.c
|
|
@@ -37,6 +37,7 @@
|
|
#include "connect.h"
|
|
#include "constants.h"
|
|
#include "client_helpers.h"
|
|
+#include "error.h"
|
|
#ifndef GRPC_CONNECTOR
|
|
#include "client_console.h"
|
|
#endif
|
|
@@ -70,8 +71,10 @@ static int check_tty(bool tty, struct termios *oldtios, bool *reset_tty)
|
|
}
|
|
*reset_tty = true;
|
|
} else {
|
|
- INFO("the input device is not a TTY");
|
|
- return 0;
|
|
+ // if it is trying to attach to a container TTY
|
|
+ // from a non-TTY client input stream, returns -1.
|
|
+ COMMAND_ERROR("the input device is not a TTY");
|
|
+ return -1;
|
|
}
|
|
|
|
return 0;
|
|
@@ -353,6 +356,7 @@ static int client_attach(struct client_arguments *args, uint32_t *exit_code)
|
|
#endif
|
|
|
|
config = get_connect_config(args);
|
|
+ // Obtain the container's real exit code by waiting for the container to stop.
|
|
container_wait_thread(args, exit_code, &sem_exited);
|
|
ret = ops->container.attach(&request, response, &config);
|
|
if (ret != 0) {
|
|
@@ -374,7 +378,9 @@ static int client_attach(struct client_arguments *args, uint32_t *exit_code)
|
|
|
|
if (sem_timedwait(&sem_exited, &ts) != 0) {
|
|
if (errno == ETIMEDOUT) {
|
|
- COMMAND_ERROR("Wait container status timeout.");
|
|
+ if (response->server_errono != ISULAD_INFO_DETACH) {
|
|
+ INFO("Wait container stopped status timeout.");
|
|
+ }
|
|
} else {
|
|
CMD_SYSERROR("Failed to wait sem");
|
|
}
|
|
diff --git a/src/cmd/isulad-shim/common.c b/src/cmd/isulad-shim/common.c
|
|
index 781dc004..48d266dc 100644
|
|
--- a/src/cmd/isulad-shim/common.c
|
|
+++ b/src/cmd/isulad-shim/common.c
|
|
@@ -33,16 +33,26 @@
|
|
#include <isula_libutils/utils_file.h>
|
|
|
|
int g_log_fd = -1;
|
|
+int g_attach_log_fd = -1;
|
|
|
|
int init_shim_log(void)
|
|
{
|
|
- g_log_fd = open_no_inherit(SHIM_LOG_NAME, O_CREAT | O_WRONLY | O_APPEND | O_SYNC, 0640);
|
|
+ g_log_fd = open_no_inherit(SHIM_LOG_NAME, O_CREAT | O_WRONLY | O_APPEND | O_SYNC, LOG_FILE_MODE);
|
|
if (g_log_fd < 0) {
|
|
return SHIM_ERR;
|
|
}
|
|
return SHIM_OK;
|
|
}
|
|
|
|
+int init_attach_log(void)
|
|
+{
|
|
+ g_attach_log_fd = open_no_inherit(ATTACH_LOG_NAME, O_CREAT | O_WRONLY | O_APPEND | O_SYNC, LOG_FILE_MODE);
|
|
+ if (g_attach_log_fd < 0) {
|
|
+ return SHIM_ERR;
|
|
+ }
|
|
+ return SHIM_OK;
|
|
+}
|
|
+
|
|
void signal_routine(int sig)
|
|
{
|
|
switch (sig) {
|
|
@@ -162,11 +172,24 @@ int generate_random_str(char *id, size_t len)
|
|
return SHIM_OK;
|
|
}
|
|
|
|
-void write_message(const char *level, const char *fmt, ...)
|
|
-{
|
|
#define MAX_MSG_JSON_TEMPLATE 32
|
|
#define MAX_MESSAGE_CONTENT_LEN 128
|
|
#define MAX_MESSAGE_LEN (MAX_MSG_JSON_TEMPLATE + MAX_MESSAGE_CONTENT_LEN)
|
|
+
|
|
+static void format_log_msg(const char *level, const char *buf, char *msg, int max_message_len)
|
|
+{
|
|
+ time_t current_time = time(NULL);
|
|
+ struct tm *local_time = localtime(¤t_time);
|
|
+ char time_str[20];
|
|
+
|
|
+ strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", local_time);
|
|
+
|
|
+ (void)snprintf(msg, max_message_len - 1, "{\"time\": \"%s\", \"level\": \"%s\", \"msg\": \"%s\"}\n", time_str, level,
|
|
+ buf);
|
|
+}
|
|
+
|
|
+void write_message(const char *level, const char *fmt, ...)
|
|
+{
|
|
if (g_log_fd < 0) {
|
|
return;
|
|
}
|
|
@@ -183,15 +206,31 @@ void write_message(const char *level, const char *fmt, ...)
|
|
return;
|
|
}
|
|
|
|
- nwrite = snprintf(msg, MAX_MESSAGE_LEN - 1, "{\"level\": \"%s\", \"msg\": \"%s\"}\n", level, buf);
|
|
- if (nwrite < 0 || (size_t)nwrite >= (MAX_MESSAGE_LEN - 1)) {
|
|
+ format_log_msg(level, buf, msg, MAX_MESSAGE_CONTENT_LEN);
|
|
+
|
|
+ (void)isula_file_total_write_nointr(g_log_fd, msg, strlen(msg));
|
|
+}
|
|
+
|
|
+void write_attach_message(const char *level, const char *fmt, ...)
|
|
+{
|
|
+ char buf[MAX_MESSAGE_CONTENT_LEN] = { 0 };
|
|
+ char msg[MAX_MESSAGE_LEN] = { 0 };
|
|
+ int nwrite = -1;
|
|
+
|
|
+ if (g_attach_log_fd < 0) {
|
|
return;
|
|
}
|
|
-
|
|
- nwrite = isula_file_total_write_nointr(g_log_fd, msg, strlen(msg));
|
|
- if (nwrite < 0 || (size_t)nwrite != strlen(msg)) {
|
|
+ va_list arg_list;
|
|
+ va_start(arg_list, fmt);
|
|
+ nwrite = vsnprintf(buf, MAX_MESSAGE_CONTENT_LEN, fmt, arg_list);
|
|
+ va_end(arg_list);
|
|
+ if (nwrite < 0) {
|
|
return;
|
|
}
|
|
+
|
|
+ format_log_msg(level, buf, msg, MAX_MESSAGE_CONTENT_LEN);
|
|
+
|
|
+ (void)isula_file_total_write_nointr(g_attach_log_fd, msg, strlen(msg));
|
|
}
|
|
|
|
/* note: This function can only read small text file. */
|
|
@@ -272,3 +311,64 @@ int open_no_inherit(const char *path, int flag, mode_t mode)
|
|
|
|
return fd;
|
|
}
|
|
+
|
|
+/* judge the fd whether is attach fifo */
|
|
+struct isula_linked_list *get_attach_fifo_item(int fd, struct isula_linked_list *list)
|
|
+{
|
|
+ struct isula_linked_list *it = NULL;
|
|
+ struct isula_linked_list *next = NULL;
|
|
+
|
|
+ if (fd <= 0 || list == NULL || isula_linked_list_empty(list)) {
|
|
+ return it;
|
|
+ }
|
|
+
|
|
+ isula_linked_list_for_each_safe(it, list, next) {
|
|
+ struct shim_fifos_fd *elem = (struct shim_fifos_fd *)it->elem;
|
|
+ if (elem == NULL) {
|
|
+ continue;
|
|
+ }
|
|
+ if (elem->in_fd == fd) {
|
|
+ return it;
|
|
+ }
|
|
+ if (elem->out_fd == fd) {
|
|
+ return it;
|
|
+ }
|
|
+ if (elem->err_fd == fd) {
|
|
+ return it;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return it;
|
|
+}
|
|
+
|
|
+void free_shim_fifos_fd(struct shim_fifos_fd *item)
|
|
+{
|
|
+ if (item == NULL) {
|
|
+ return;
|
|
+ }
|
|
+ if (item->in_fifo != NULL) {
|
|
+ free(item->in_fifo);
|
|
+ item->in_fifo = NULL;
|
|
+ }
|
|
+ if (item->out_fifo != NULL) {
|
|
+ free(item->out_fifo);
|
|
+ item->out_fifo = NULL;
|
|
+ }
|
|
+ if (item->err_fifo != NULL) {
|
|
+ free(item->err_fifo);
|
|
+ item->err_fifo = NULL;
|
|
+ }
|
|
+ if (item->in_fd >= 0) {
|
|
+ close(item->in_fd);
|
|
+ item->in_fd = -1;
|
|
+ }
|
|
+ if (item->out_fd >= 0) {
|
|
+ close(item->out_fd);
|
|
+ item->out_fd = -1;
|
|
+ }
|
|
+ if (item->err_fd >= 0) {
|
|
+ close(item->err_fd);
|
|
+ item->err_fd = -1;
|
|
+ }
|
|
+ free(item);
|
|
+}
|
|
\ No newline at end of file
|
|
diff --git a/src/cmd/isulad-shim/common.h b/src/cmd/isulad-shim/common.h
|
|
index 55efdc28..2020a799 100644
|
|
--- a/src/cmd/isulad-shim/common.h
|
|
+++ b/src/cmd/isulad-shim/common.h
|
|
@@ -21,6 +21,7 @@
|
|
#include <sys/types.h>
|
|
#include <stdint.h>
|
|
#include <isula_libutils/utils.h>
|
|
+#include <isula_libutils/utils_linked_list.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
@@ -59,8 +60,22 @@ extern "C" {
|
|
#define CONTAINER_ACTION_REBOOT 129
|
|
#define CONTAINER_ACTION_SHUTDOWN 130
|
|
|
|
+#define ATTACH_SOCKET "attach_socket.sock"
|
|
+#define ATTACH_LOG_NAME "attach-log.json"
|
|
+#define ATTACH_DETACH_MSG "read escape sequence"
|
|
+#define MAX_ATTACH_NUM 16
|
|
+
|
|
+#define CTRL_Q 0x11 // ASCII code control character ctrl + Q
|
|
+
|
|
+#define LOG_FILE_MODE 0600
|
|
+
|
|
+#define SOCKET_DIRECTORY_MODE 0600
|
|
+#define ATTACH_FIFOPATH_MODE 0600
|
|
+
|
|
int init_shim_log(void);
|
|
|
|
+int init_attach_log(void);
|
|
+
|
|
void signal_routine(int sig);
|
|
|
|
/**
|
|
@@ -90,18 +105,33 @@ void signal_routine(int sig);
|
|
} \
|
|
} while (0)
|
|
|
|
+struct shim_fifos_fd {
|
|
+ char *in_fifo;
|
|
+ char *out_fifo;
|
|
+ char *err_fifo;
|
|
+ int in_fd;
|
|
+ int out_fd;
|
|
+ int err_fd;
|
|
+};
|
|
+
|
|
char *read_text_file(const char *path);
|
|
|
|
int cmd_combined_output(const char *binary, const char *params[], void *output, int *output_len);
|
|
|
|
void write_message(const char *level, const char *fmt, ...);
|
|
|
|
+void write_attach_message(const char *level, const char *fmt, ...);
|
|
+
|
|
int generate_random_str(char *id, size_t len);
|
|
|
|
void close_fd(int *pfd);
|
|
|
|
int open_no_inherit(const char *path, int flag, mode_t mode);
|
|
|
|
+struct isula_linked_list *get_attach_fifo_item(int fd, struct isula_linked_list *list);
|
|
+
|
|
+void free_shim_fifos_fd(struct shim_fifos_fd *item);
|
|
+
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
diff --git a/src/cmd/isulad-shim/main.c b/src/cmd/isulad-shim/main.c
|
|
index 454011d0..deb07271 100644
|
|
--- a/src/cmd/isulad-shim/main.c
|
|
+++ b/src/cmd/isulad-shim/main.c
|
|
@@ -145,6 +145,20 @@ int main(int argc, char **argv)
|
|
}
|
|
}
|
|
|
|
+ if (p->state->attach_socket != NULL) {
|
|
+ ret = prepare_attach_socket(p);
|
|
+ if (ret != SHIM_OK) {
|
|
+ write_message(ERR_MSG, "failed to prepare attach socket:%d", ret);
|
|
+ exit(EXIT_FAILURE);
|
|
+ }
|
|
+
|
|
+ ret = init_attach_log();
|
|
+ if (ret != SHIM_OK) {
|
|
+ write_message(ERR_MSG, "failed to init shim attach log");
|
|
+ exit(EXIT_FAILURE);
|
|
+ }
|
|
+ }
|
|
+
|
|
/* start epoll for io copy */
|
|
ret = process_io_start(p, &tid_epoll);
|
|
if (ret != SHIM_OK) {
|
|
diff --git a/src/cmd/isulad-shim/process.c b/src/cmd/isulad-shim/process.c
|
|
index 40908102..187067d2 100644
|
|
--- a/src/cmd/isulad-shim/process.c
|
|
+++ b/src/cmd/isulad-shim/process.c
|
|
@@ -19,20 +19,22 @@
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/un.h>
|
|
+#include <sys/ioctl.h>
|
|
+#include <sys/eventfd.h>
|
|
+#include <sys/resource.h> // IWYU pragma: keep
|
|
+#include <sys/stat.h>
|
|
+#include <sys/wait.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <limits.h>
|
|
-#include <sys/wait.h>
|
|
#include <semaphore.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
-#include <sys/ioctl.h>
|
|
-#include <sys/eventfd.h>
|
|
#include <termios.h> // IWYU pragma: keep
|
|
-#include <sys/resource.h> // IWYU pragma: keep
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
+#include <stddef.h>
|
|
|
|
#include <isula_libutils/json_common.h>
|
|
#include <isula_libutils/shim_client_process_state.h>
|
|
@@ -42,6 +44,8 @@
|
|
#include <isula_libutils/utils_mainloop.h>
|
|
#include <isula_libutils/auto_cleanup.h>
|
|
#include <isula_libutils/utils_buffer.h>
|
|
+#include <isula_libutils/utils_linked_list.h>
|
|
+#include <isula_libutils/utils_array.h>
|
|
|
|
#include "common.h"
|
|
#include "terminal.h"
|
|
@@ -57,7 +61,7 @@ static shim_client_process_state *load_process()
|
|
|
|
p_state = shim_client_process_state_parse_file("process.json", NULL, &err);
|
|
if (p_state == NULL) {
|
|
- write_message(ERR_MSG, "parse process state failed");
|
|
+ write_message(ERR_MSG, "parse process state failed: %s", err);
|
|
}
|
|
/* "err" will definitely be allocated memory in the function above */
|
|
free(err);
|
|
@@ -168,6 +172,99 @@ static int sync_exit_cb(int fd, uint32_t events, void *cbdata, isula_epoll_descr
|
|
return EPOLL_LOOP_HANDLE_CLOSE;
|
|
}
|
|
|
|
+static bool fifo_exists(const char *path)
|
|
+{
|
|
+ struct stat sb;
|
|
+ int ret;
|
|
+
|
|
+ ret = stat(path, &sb);
|
|
+ if (ret < 0) {
|
|
+ // could be something other than exist, just return false
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ return S_ISFIFO(sb.st_mode);
|
|
+}
|
|
+
|
|
+static int add_attach_terminal_fifos(const char *in, const char *out, const char *err, int *input_fd, process_t *p)
|
|
+{
|
|
+ __isula_auto_close int fifofd_in = -1;
|
|
+ __isula_auto_close int fifofd_out = -1;
|
|
+ __isula_auto_close int fifofd_err = -1;
|
|
+ struct shim_fifos_fd *fifos = NULL;
|
|
+ struct isula_linked_list *node = NULL;
|
|
+
|
|
+ bool invalid = (in != NULL && !fifo_exists(in)) || (out != NULL && !fifo_exists(out)) || (err != NULL &&
|
|
+ !fifo_exists(err));
|
|
+ if (invalid) {
|
|
+ write_attach_message(ERR_MSG, "File %s or %s or %s does not refer to a FIFO", in, out, err);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (in != NULL) {
|
|
+ fifofd_in = isula_file_open(in, O_RDONLY | O_NONBLOCK | O_CLOEXEC, 0);
|
|
+ if (fifofd_in < 0) {
|
|
+ write_attach_message(ERR_MSG, "Failed to open FIFO: %s", in);
|
|
+ return -1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (out != NULL) {
|
|
+ fifofd_out = isula_file_open(out, O_WRONLY | O_NONBLOCK | O_CLOEXEC, 0);
|
|
+ if (fifofd_out < 0) {
|
|
+ write_attach_message(ERR_MSG, "Failed to open FIFO: %s", out);
|
|
+ return -1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (err != NULL) {
|
|
+ fifofd_err = isula_file_open(err, O_WRONLY | O_NONBLOCK | O_CLOEXEC, 0);
|
|
+ if (fifofd_err < 0) {
|
|
+ write_attach_message(ERR_MSG, "Failed to open FIFO: %s", err);
|
|
+ return -1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ fifos = isula_common_calloc_s(sizeof(*fifos));
|
|
+ if (fifos == NULL) {
|
|
+ write_attach_message(ERR_MSG, "Out of memory");
|
|
+ goto err_out;
|
|
+ }
|
|
+
|
|
+ fifos->in_fifo = isula_strdup_s(in);
|
|
+ fifos->out_fifo = isula_strdup_s(out);
|
|
+ fifos->err_fifo = isula_strdup_s(err);
|
|
+
|
|
+ fifos->in_fd = isula_transfer_fd(fifofd_in);
|
|
+ fifos->out_fd = isula_transfer_fd(fifofd_out);
|
|
+ fifos->err_fd = isula_transfer_fd(fifofd_err);
|
|
+ node = isula_common_calloc_s(sizeof(struct isula_linked_list));
|
|
+ if (node == NULL) {
|
|
+ write_attach_message(ERR_MSG, "Out of memory");
|
|
+ goto err_out;
|
|
+ }
|
|
+
|
|
+ node->elem = fifos;
|
|
+ isula_linked_list_add(p->attach_fifos, node);
|
|
+
|
|
+ if (input_fd != NULL) {
|
|
+ *input_fd = fifos->in_fd;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+err_out:
|
|
+ free_shim_fifos_fd(fifos);
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+static void remove_attach_terminal_fifos(isula_epoll_descr_t *descr, struct isula_linked_list *item)
|
|
+{
|
|
+ struct shim_fifos_fd *elem = (struct shim_fifos_fd *)item->elem;
|
|
+ isula_epoll_remove_handler(descr, elem->in_fd);
|
|
+ isula_linked_list_del(item);
|
|
+ free_shim_fifos_fd(elem);
|
|
+}
|
|
+
|
|
static int stdin_cb(int fd, uint32_t events, void *cbdata, isula_epoll_descr_t *descr)
|
|
{
|
|
process_t *p = (process_t *)cbdata;
|
|
@@ -210,6 +307,57 @@ static int stdin_cb(int fd, uint32_t events, void *cbdata, isula_epoll_descr_t *
|
|
return EPOLL_LOOP_HANDLE_CONTINUE;
|
|
}
|
|
|
|
+static int attach_stdin_cb(int fd, uint32_t events, void *cbdata, isula_epoll_descr_t *descr)
|
|
+{
|
|
+ process_t *p = (process_t *)cbdata;
|
|
+ int r_count = 0;
|
|
+ int w_count = 0;
|
|
+ int *fd_to = NULL;
|
|
+ struct isula_linked_list *item;
|
|
+
|
|
+ if (events & EPOLLHUP) {
|
|
+ write_message(ERR_MSG, "attach stdin %d received the EPOLLHUP event", fd);
|
|
+ goto err_out;
|
|
+ }
|
|
+
|
|
+ if (!(events & EPOLLIN)) {
|
|
+ return EPOLL_LOOP_HANDLE_CONTINUE;
|
|
+ }
|
|
+
|
|
+ (void)memset(p->buf, 0, DEFAULT_IO_COPY_BUF);
|
|
+
|
|
+ r_count = isula_file_read_nointr(fd, p->buf, DEFAULT_IO_COPY_BUF);
|
|
+ if (r_count <= 0) {
|
|
+ write_message(ERR_MSG, "failed to read from attach stdin %d, error:%d", fd, SHIM_SYS_ERR(errno));
|
|
+ goto err_out;
|
|
+ }
|
|
+
|
|
+ if (p->state->terminal) {
|
|
+ fd_to = &(p->recv_fd);
|
|
+ } else {
|
|
+ fd_to = &(p->shim_io->in);
|
|
+ }
|
|
+
|
|
+ if (fd_to == NULL || *fd_to == -1) {
|
|
+ return EPOLL_LOOP_HANDLE_CONTINUE;
|
|
+ }
|
|
+ w_count = isula_file_total_write_nointr(*fd_to, p->buf, r_count);
|
|
+ if (w_count < 0) {
|
|
+ /* When any error occurs, set the write fd -1 */
|
|
+ write_message(WARN_MSG, "write in_fd %d error:%d", *fd_to, SHIM_SYS_ERR(errno));
|
|
+ close(*fd_to);
|
|
+ *fd_to = -1;
|
|
+ }
|
|
+
|
|
+ return EPOLL_LOOP_HANDLE_CONTINUE;
|
|
+err_out:
|
|
+ item = get_attach_fifo_item(fd, p->attach_fifos);
|
|
+ if (item != NULL && item->elem != NULL) {
|
|
+ remove_attach_terminal_fifos(descr, item);
|
|
+ }
|
|
+ return EPOLL_LOOP_HANDLE_CONTINUE;
|
|
+}
|
|
+
|
|
static int stdout_cb(int fd, uint32_t events, void *cbdata, isula_epoll_descr_t *descr)
|
|
{
|
|
process_t *p = (process_t *)cbdata;
|
|
@@ -237,16 +385,29 @@ static int stdout_cb(int fd, uint32_t events, void *cbdata, isula_epoll_descr_t
|
|
|
|
shim_write_container_log_file(p->terminal, STDID_OUT, p->buf, r_count);
|
|
|
|
- if (p->isulad_io->out == -1) {
|
|
+ if (p->isulad_io->out != -1) {
|
|
+ w_count = isula_file_total_write_nointr(p->isulad_io->out, p->buf, r_count);
|
|
+ if (w_count < 0) {
|
|
+ /* When any error occurs, set the write fd -1 */
|
|
+ write_message(WARN_MSG, "write out_fd %d error:%d", p->isulad_io->out, SHIM_SYS_ERR(errno));
|
|
+ close(p->isulad_io->out);
|
|
+ p->isulad_io->out = -1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (isula_linked_list_empty(p->attach_fifos)) {
|
|
return EPOLL_LOOP_HANDLE_CONTINUE;
|
|
}
|
|
|
|
- w_count = isula_file_total_write_nointr(p->isulad_io->out, p->buf, r_count);
|
|
- if (w_count < 0) {
|
|
- /* When any error occurs, set the write fd -1 */
|
|
- write_message(WARN_MSG, "write out_fd %d error:%d", p->isulad_io->out, SHIM_SYS_ERR(errno));
|
|
- close(p->isulad_io->out);
|
|
- p->isulad_io->out = -1;
|
|
+ struct isula_linked_list *it = NULL;
|
|
+ struct isula_linked_list *next = NULL;
|
|
+
|
|
+ isula_linked_list_for_each_safe(it, p->attach_fifos, next) {
|
|
+ struct shim_fifos_fd *elem = (struct shim_fifos_fd *)it->elem;
|
|
+ w_count = isula_file_total_write_nointr(elem->out_fd, p->buf, r_count);
|
|
+ if (w_count < 0) {
|
|
+ remove_attach_terminal_fifos(descr, it);
|
|
+ }
|
|
}
|
|
|
|
return EPOLL_LOOP_HANDLE_CONTINUE;
|
|
@@ -279,16 +440,29 @@ static int stderr_cb(int fd, uint32_t events, void *cbdata, isula_epoll_descr_t
|
|
|
|
shim_write_container_log_file(p->terminal, STDID_ERR, p->buf, r_count);
|
|
|
|
- if (p->isulad_io->err == -1) {
|
|
+ if (p->isulad_io->err != -1) {
|
|
+ w_count = isula_file_total_write_nointr(p->isulad_io->err, p->buf, r_count);
|
|
+ if (w_count < 0) {
|
|
+ /* When any error occurs, set the write fd -1 */
|
|
+ write_message(WARN_MSG, "write err_fd %d error:%d", p->isulad_io->err, SHIM_SYS_ERR(errno));
|
|
+ close(p->isulad_io->err);
|
|
+ p->isulad_io->err = -1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (isula_linked_list_empty(p->attach_fifos)) {
|
|
return EPOLL_LOOP_HANDLE_CONTINUE;
|
|
}
|
|
|
|
- w_count = isula_file_total_write_nointr(p->isulad_io->err, p->buf, r_count);
|
|
- if (w_count < 0) {
|
|
- /* When any error occurs, set the write fd -1 */
|
|
- write_message(WARN_MSG, "write err_fd %d error:%d", p->isulad_io->err, SHIM_SYS_ERR(errno));
|
|
- close(p->isulad_io->err);
|
|
- p->isulad_io->err = -1;
|
|
+ struct isula_linked_list *it = NULL;
|
|
+ struct isula_linked_list *next = NULL;
|
|
+
|
|
+ isula_linked_list_for_each_safe(it, p->attach_fifos, next) {
|
|
+ struct shim_fifos_fd *elem = (struct shim_fifos_fd *)it->elem;
|
|
+ w_count = isula_file_total_write_nointr(elem->out_fd, p->buf, r_count);
|
|
+ if (w_count < 0) {
|
|
+ remove_attach_terminal_fifos(descr, it);
|
|
+ }
|
|
}
|
|
|
|
return EPOLL_LOOP_HANDLE_CONTINUE;
|
|
@@ -326,6 +500,159 @@ static int resize_cb(int fd, uint32_t events, void *cbdata, isula_epoll_descr_t
|
|
return EPOLL_LOOP_HANDLE_CONTINUE;
|
|
}
|
|
|
|
+static bool attach_fifopath_security_check(process_t *p, const char *fifopath)
|
|
+{
|
|
+ struct stat st = { 0 };
|
|
+ char real_path[PATH_MAX] = { 0 };
|
|
+
|
|
+ if (isula_validate_absolute_path(fifopath) != 0) {
|
|
+ write_attach_message(ERR_MSG, "attach fifo path \"%s\" must be an valid absolute path", fifopath);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (realpath(fifopath, real_path) == NULL) {
|
|
+ write_attach_message(ERR_MSG, "Failed to get realpath for '%s': %s.", real_path, SHIM_SYS_ERR(errno));
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (!isula_has_prefix(real_path, p->workdir)) {
|
|
+ write_attach_message(ERR_MSG, "attach fifo path \"%s\" must be under the state path", real_path, p->workdir);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (lstat(real_path, &st) != 0) {
|
|
+ write_attach_message(ERR_MSG, "Failed to lstat %s : %s", real_path, SHIM_SYS_ERR(errno));
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (!S_ISFIFO(st.st_mode)) {
|
|
+ write_attach_message(ERR_MSG, "attach fifo path \"%s\" must be an FIFO", real_path);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if ((st.st_mode & 0777) != ATTACH_FIFOPATH_MODE) {
|
|
+ write_attach_message(ERR_MSG, "attach fifo path \"%s\" permission invalid", real_path);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (st.st_uid != 0) {
|
|
+ write_attach_message(ERR_MSG, "attach fifo path \"%s\" uid invalid", real_path);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+// attach_cb needs to read the content from communication fd and parse it.
|
|
+// at the same time, it also needs to establish a connection between the attach fd and the container fd.
|
|
+// 1. if it fails, it needs to write an error message to attach log file,
|
|
+// and write -1 to connection fd to let isulad know that it has failed.
|
|
+// 2. if it succeeds, write 0 to let isulad know that it is ready.
|
|
+// attach_cb returns EPOLL_LOOP_HANDLE_CONTINUE regardless of success or failure,
|
|
+// because whether the attach operation is successful or not does not affect the first process of the container.
|
|
+static int attach_cb(int fd, uint32_t events, void *cbdata, isula_epoll_descr_t *descr)
|
|
+{
|
|
+ process_t *p = (process_t *)cbdata;
|
|
+ int r_count = 0;
|
|
+ char tmp_buf[BUFSIZ + 1] = { 0 };
|
|
+ char *in = NULL, *out = NULL, *err = NULL;
|
|
+ int fifofd_in = -1;
|
|
+ isula_string_array *tmp_str_array = NULL;
|
|
+ int ret = 0;
|
|
+ // attach execution return value
|
|
+ int status = -1;
|
|
+ bool valid = true;
|
|
+
|
|
+ // after receiving the event that isulad closes the connection,
|
|
+ // close the communication fd and remove it from epoll.
|
|
+ if (events & EPOLLHUP) {
|
|
+ close(fd);
|
|
+ isula_epoll_remove_handler(descr, fd);
|
|
+ return EPOLL_LOOP_HANDLE_CONTINUE;
|
|
+ }
|
|
+
|
|
+ if (!(events & EPOLLIN)) {
|
|
+ return EPOLL_LOOP_HANDLE_CONTINUE;
|
|
+ }
|
|
+
|
|
+ r_count = isula_file_read_nointr(fd, tmp_buf, sizeof(tmp_buf) - 1);
|
|
+ if (r_count <= 0) {
|
|
+ write_attach_message(ERR_MSG, "Failed to read msg from attach conn fd");
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ // limit the number of attach connections to MAX_ATTACH_NUM
|
|
+ if (isula_linked_list_len(p->attach_fifos) >= MAX_ATTACH_NUM) {
|
|
+ write_attach_message(ERR_MSG, "The number of attach connections exceeds the limit:%d, and this connection is rejected.",
|
|
+ MAX_ATTACH_NUM);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ tmp_str_array = isula_string_split_to_multi(tmp_buf, ' ');
|
|
+ if (tmp_str_array->len != 3) {
|
|
+ write_attach_message(ERR_MSG, "Invalid attach msg from isulad");
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ for (int i = 0; i < tmp_str_array->len; i++) {
|
|
+ valid = valid && attach_fifopath_security_check(p, tmp_str_array->items[i]);
|
|
+ }
|
|
+
|
|
+ if (!valid) {
|
|
+ write_attach_message(ERR_MSG, "Invalid attach fifo path from isulad");
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ in = tmp_str_array->items[0];
|
|
+ out = tmp_str_array->items[1];
|
|
+ err = tmp_str_array->items[2];
|
|
+
|
|
+ if (add_attach_terminal_fifos(in, out, err, &fifofd_in, p) < 0) {
|
|
+ write_attach_message(ERR_MSG, "Failed to add attach terminal fifos");
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ // attach stdin --> container stdin
|
|
+ ret = isula_epoll_add_handler(descr, fifofd_in, attach_stdin_cb, p);
|
|
+ if (ret != SHIM_OK) {
|
|
+ write_attach_message(ERR_MSG, "add fifofd_in fd %d to epoll loop failed:%d", fifofd_in, SHIM_SYS_ERR(errno));
|
|
+ struct isula_linked_list *item = get_attach_fifo_item(fd, p->attach_fifos);
|
|
+ if (item != NULL && item->elem != NULL) {
|
|
+ remove_attach_terminal_fifos(descr, item);
|
|
+ }
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ status = 0;
|
|
+out:
|
|
+ isula_string_array_free(tmp_str_array);
|
|
+ (void)isula_file_write_nointr(fd, &status, sizeof(int));
|
|
+ return EPOLL_LOOP_HANDLE_CONTINUE;
|
|
+}
|
|
+
|
|
+// do_attach_socket_accept returns EPOLL_LOOP_HANDLE_CONTINUE regardless of success or failure,
|
|
+// because whether the attach operation is successful or not does not affect the first process of the container.
|
|
+static int do_attach_socket_accept(int fd, uint32_t events, void *cbdata, isula_epoll_descr_t *descr)
|
|
+{
|
|
+ process_t *p = (process_t *)cbdata;
|
|
+ int conn_fd = -1;
|
|
+ int ret = SHIM_ERR;
|
|
+
|
|
+ conn_fd = accept(p->attach_socket_fd, NULL, NULL);
|
|
+ if (conn_fd < 0) {
|
|
+ write_attach_message(ERR_MSG, "accept from fd %d failed:%d", p->attach_socket_fd, SHIM_SYS_ERR(errno));
|
|
+ return EPOLL_LOOP_HANDLE_CONTINUE;
|
|
+ }
|
|
+
|
|
+ ret = isula_epoll_add_handler(descr, conn_fd, attach_cb, p);
|
|
+ if (ret != SHIM_OK) {
|
|
+ write_attach_message(ERR_MSG, "add recv_fd %d to epoll loop failed:%d", conn_fd, SHIM_SYS_ERR(errno));
|
|
+ close(conn_fd);
|
|
+ return EPOLL_LOOP_HANDLE_CONTINUE;
|
|
+ }
|
|
+ return EPOLL_LOOP_HANDLE_CONTINUE;
|
|
+}
|
|
+
|
|
static int task_console_accept(int fd, uint32_t events, void *cbdata, isula_epoll_descr_t *descr)
|
|
{
|
|
process_t *p = (process_t *)cbdata;
|
|
@@ -399,6 +726,7 @@ static void stdio_release(int (*stdio_fd)[2])
|
|
for (j = 0; j < 2; j++) {
|
|
if (stdio_fd[i][j] > 0) {
|
|
close(stdio_fd[i][j]);
|
|
+ stdio_fd[i][j] = -1;
|
|
}
|
|
}
|
|
}
|
|
@@ -568,24 +896,6 @@ static int open_generic_io(process_t *p, isula_epoll_descr_t *descr)
|
|
return SHIM_OK;
|
|
}
|
|
|
|
-static int set_non_block(int fd)
|
|
-{
|
|
- int flag = -1;
|
|
- int ret = SHIM_ERR;
|
|
-
|
|
- flag = fcntl(fd, F_GETFL, 0);
|
|
- if (flag < 0) {
|
|
- return SHIM_ERR;
|
|
- }
|
|
-
|
|
- ret = fcntl(fd, F_SETFL, flag | O_NONBLOCK);
|
|
- if (ret != 0) {
|
|
- return SHIM_ERR;
|
|
- }
|
|
-
|
|
- return SHIM_OK;
|
|
-}
|
|
-
|
|
/*
|
|
std_id: channel type
|
|
isulad_stdio: one side of the isulad fifo file
|
|
@@ -623,6 +933,14 @@ static void *io_epoll_loop(void *data)
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
+ if (p->state->attach_socket != NULL) {
|
|
+ ret = isula_epoll_add_handler(&descr, p->attach_socket_fd, do_attach_socket_accept, p);
|
|
+ if (ret != SHIM_OK) {
|
|
+ write_message(ERR_MSG, "add attach_socket_fd %d to epoll loop failed:%d", p->attach_socket_fd, SHIM_SYS_ERR(errno));
|
|
+ exit(EXIT_FAILURE);
|
|
+ }
|
|
+ }
|
|
+
|
|
if (p->state->terminal) {
|
|
ret = open_terminal_io(p, &descr);
|
|
} else {
|
|
@@ -651,7 +969,7 @@ static void *io_epoll_loop(void *data)
|
|
}
|
|
|
|
if (fd_out > 0) {
|
|
- ret = set_non_block(fd_out);
|
|
+ ret = isula_set_non_block(fd_out);
|
|
if (ret != SHIM_OK) {
|
|
write_message(ERR_MSG, "set fd %d non_block failed:%d", fd_out, SHIM_SYS_ERR(errno));
|
|
exit(EXIT_FAILURE);
|
|
@@ -666,7 +984,7 @@ static void *io_epoll_loop(void *data)
|
|
}
|
|
|
|
if (fd_err > 0) {
|
|
- ret = set_non_block(fd_err);
|
|
+ ret = isula_set_non_block(fd_err);
|
|
if (ret != SHIM_OK) {
|
|
write_message(ERR_MSG, "set fd %d non_block failed:%d", fd_err, SHIM_SYS_ERR(errno));
|
|
exit(EXIT_FAILURE);
|
|
@@ -807,15 +1125,19 @@ failure:
|
|
if (p->isulad_io != NULL) {
|
|
if (p->isulad_io->in > 0) {
|
|
close(p->isulad_io->in);
|
|
+ p->isulad_io->in = -1;
|
|
}
|
|
if (p->isulad_io->out > 0) {
|
|
close(p->isulad_io->out);
|
|
+ p->isulad_io->out = -1;
|
|
}
|
|
if (p->isulad_io->err > 0) {
|
|
close(p->isulad_io->err);
|
|
+ p->isulad_io->err = -1;
|
|
}
|
|
if (p->isulad_io->resize > 0) {
|
|
close(p->isulad_io->resize);
|
|
+ p->isulad_io->resize = -1;
|
|
}
|
|
free(p->isulad_io);
|
|
p->isulad_io = NULL;
|
|
@@ -937,6 +1259,13 @@ process_t *new_process(char *id, char *bundle, char *runtime)
|
|
goto failure;
|
|
}
|
|
|
|
+ p->attach_fifos = isula_common_calloc_s(sizeof(struct isula_linked_list));
|
|
+ if (p->attach_fifos == NULL) {
|
|
+ goto failure;
|
|
+ }
|
|
+
|
|
+ isula_linked_list_init(p->attach_fifos);
|
|
+
|
|
return p;
|
|
|
|
failure:
|
|
@@ -1368,3 +1697,49 @@ int process_signal_handle_routine(process_t *p, const pthread_t tid_epoll, const
|
|
(void)isula_file_write_nointr(STDOUT_FILENO, &status, sizeof(int));
|
|
return SHIM_OK;
|
|
}
|
|
+
|
|
+int prepare_attach_socket(process_t *p)
|
|
+{
|
|
+ struct sockaddr_un addr;
|
|
+ int ret = -1;
|
|
+
|
|
+ if (strlen(p->state->attach_socket) >= sizeof(addr.sun_path)) {
|
|
+ write_message(ERR_MSG, "Invalid attach socket path: %s", p->state->attach_socket);
|
|
+ return SHIM_ERR;
|
|
+ }
|
|
+
|
|
+ p->attach_socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
|
+ if (p->attach_socket_fd < 0) {
|
|
+ write_message(ERR_MSG, "Failed to create socket:%d", SHIM_SYS_ERR(errno));
|
|
+ return SHIM_ERR;
|
|
+ }
|
|
+
|
|
+ (void)memset(&addr, 0, sizeof(addr));
|
|
+ addr.sun_family = AF_UNIX;
|
|
+ (void)strncpy(addr.sun_path, p->state->attach_socket, sizeof(addr.sun_path) - 1);
|
|
+
|
|
+ ret = bind(p->attach_socket_fd, (struct sockaddr *)&addr, sizeof(addr));
|
|
+ if (ret < 0) {
|
|
+ write_message(ERR_MSG, "bind console fd failed:%d", SHIM_SYS_ERR(errno));
|
|
+ return SHIM_ERR;
|
|
+ }
|
|
+
|
|
+ ret = chmod(p->state->attach_socket, SOCKET_DIRECTORY_MODE);
|
|
+ if (ret != 0) {
|
|
+ write_message(ERR_MSG, "Failed to chmod for socket: %s", p->state->attach_socket);
|
|
+ return SHIM_ERR;
|
|
+ }
|
|
+
|
|
+ //If the backlog argument is greater than the value in
|
|
+ // /proc/sys/net/core/somaxconn, then it is silently capped to that
|
|
+ // value. Since Linux 5.4, the default in this file is 4096; in
|
|
+ // earlier kernels, the default value is 128. Before Linux 2.4.25,
|
|
+ // this limit was a hard coded value, SOMAXCONN, with the value 128.
|
|
+ // The maximum number of attach we allow here is MAX_ATTACH_NUM, so just use it directly
|
|
+ ret = listen(p->attach_socket_fd, MAX_ATTACH_NUM);
|
|
+ if (ret < 0) {
|
|
+ write_message(ERR_MSG, "listen console fd failed:%d", SHIM_SYS_ERR(errno));
|
|
+ return SHIM_ERR;
|
|
+ }
|
|
+ return SHIM_OK;
|
|
+}
|
|
\ No newline at end of file
|
|
diff --git a/src/cmd/isulad-shim/process.h b/src/cmd/isulad-shim/process.h
|
|
index 280d9874..5607316c 100644
|
|
--- a/src/cmd/isulad-shim/process.h
|
|
+++ b/src/cmd/isulad-shim/process.h
|
|
@@ -19,7 +19,8 @@
|
|
#include <pthread.h>
|
|
#include <semaphore.h>
|
|
#include <stdbool.h>
|
|
-#include "isula_libutils/shim_client_process_state.h"
|
|
+#include <isula_libutils/shim_client_process_state.h>
|
|
+#include "isula_libutils/utils_linked_list.h"
|
|
#include "terminal.h"
|
|
|
|
#ifdef __cplusplus
|
|
@@ -49,6 +50,7 @@ typedef struct process {
|
|
char *root_path;
|
|
int io_loop_fd;
|
|
int exit_fd;
|
|
+ int attach_socket_fd; // the server socket fd that establishes a connection with isulad
|
|
int ctr_pid;
|
|
int sync_fd;
|
|
int listen_fd;
|
|
@@ -58,6 +60,7 @@ typedef struct process {
|
|
stdio_t *stdio; // shim to on runtime side, in:r out/err: w
|
|
stdio_t *shim_io; // shim io on isulad side, in: w out/err: r
|
|
stdio_t *isulad_io; // isulad io, in:r out/err: w
|
|
+ struct isula_linked_list *attach_fifos; /* isulad: fifos used to attach teminal */
|
|
shim_client_process_state *state;
|
|
sem_t sem_mainloop;
|
|
char *buf;
|
|
@@ -70,6 +73,8 @@ typedef struct {
|
|
|
|
process_t* new_process(char *id, char *bundle, char *runtime);
|
|
|
|
+int prepare_attach_socket(process_t *p);
|
|
+
|
|
int process_io_start(process_t *p, pthread_t *tid_epoll);
|
|
int create_process(process_t *p);
|
|
int process_signal_handle_routine(process_t *p, const pthread_t tid_epoll, const uint64_t timeout);
|
|
diff --git a/src/cmd/isulad-shim/terminal.c b/src/cmd/isulad-shim/terminal.c
|
|
index 0653dc45..1c063300 100644
|
|
--- a/src/cmd/isulad-shim/terminal.c
|
|
+++ b/src/cmd/isulad-shim/terminal.c
|
|
@@ -162,7 +162,7 @@ static int shim_json_data_write(log_terminal *terminal, const char *buf, int rea
|
|
* shouldn't happen, otherwise, discard some last bytes.
|
|
*/
|
|
nret = isula_file_total_write_nointr(terminal->fd, buf,
|
|
- terminal->log_maxsize < read_count ? terminal->log_maxsize : read_count);
|
|
+ terminal->log_maxsize < read_count ? terminal->log_maxsize : read_count);
|
|
if (nret < 0) {
|
|
ret = -1;
|
|
goto out;
|
|
diff --git a/src/daemon/executor/container_cb/execution_stream.c b/src/daemon/executor/container_cb/execution_stream.c
|
|
index 7db96b19..124dcfe2 100644
|
|
--- a/src/daemon/executor/container_cb/execution_stream.c
|
|
+++ b/src/daemon/executor/container_cb/execution_stream.c
|
|
@@ -346,6 +346,7 @@ static int container_attach_cb(const container_attach_request *request, containe
|
|
}
|
|
|
|
params.rootpath = cont->root_path;
|
|
+ params.state = cont->state_path;
|
|
params.stdin = fifos[0];
|
|
params.stdout = fifos[1];
|
|
params.stderr = fifos[2];
|
|
diff --git a/src/daemon/modules/api/runtime_api.h b/src/daemon/modules/api/runtime_api.h
|
|
index edb33d02..3c2100f5 100644
|
|
--- a/src/daemon/modules/api/runtime_api.h
|
|
+++ b/src/daemon/modules/api/runtime_api.h
|
|
@@ -161,6 +161,7 @@ typedef struct _rt_resume_params_t {
|
|
|
|
typedef struct _rt_attach_params_t {
|
|
const char *rootpath;
|
|
+ const char *state;
|
|
const char *stdin;
|
|
const char *stdout;
|
|
const char *stderr;
|
|
diff --git a/src/daemon/modules/runtime/isula/isula_rt_ops.c b/src/daemon/modules/runtime/isula/isula_rt_ops.c
|
|
index cb1ee26f..1787170b 100644
|
|
--- a/src/daemon/modules/runtime/isula/isula_rt_ops.c
|
|
+++ b/src/daemon/modules/runtime/isula/isula_rt_ops.c
|
|
@@ -18,6 +18,10 @@
|
|
#include "isula_rt_ops.h"
|
|
#include <unistd.h>
|
|
#include <sys/wait.h>
|
|
+#include <stdio.h>
|
|
+#include <sys/socket.h>
|
|
+#include <sys/un.h>
|
|
+#include <sys/types.h>
|
|
#include <limits.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
@@ -26,6 +30,7 @@
|
|
#include <isula_libutils/isulad_daemon_configs.h>
|
|
#include <isula_libutils/json_common.h>
|
|
#include <isula_libutils/oci_runtime_spec.h>
|
|
+#include <isula_libutils/utils_file.h>
|
|
#include <signal.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
@@ -52,9 +57,11 @@
|
|
|
|
#define SHIM_BINARY "isulad-shim"
|
|
#define RESIZE_FIFO_NAME "resize_fifo"
|
|
+#define ATTACH_SOCKET "attach_socket.sock"
|
|
#define SHIM_LOG_SIZE ((BUFSIZ - 100) / 2)
|
|
#define RESIZE_DATA_SIZE 100
|
|
#define PID_WAIT_TIME 120
|
|
+#define ATTACH_WAIT_TIME 120
|
|
#define SHIM_EXIT_TIMEOUT 2
|
|
|
|
// file name formats of cgroup resources json
|
|
@@ -223,6 +230,19 @@ static void show_shim_runtime_errlog(const char *workdir)
|
|
isulad_set_error_message(buf);
|
|
}
|
|
|
|
+static void show_shim_attach_errlog(const char *workdir)
|
|
+{
|
|
+ char buf[SHIM_LOG_SIZE] = { 0 };
|
|
+
|
|
+ if (g_isulad_errmsg != NULL) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ get_err_message(buf, sizeof(buf), workdir, "attach-log.json");
|
|
+ ERROR("shim-log: %s", buf);
|
|
+ isulad_set_error_message("shim-log error:\n%s\n", buf);
|
|
+}
|
|
+
|
|
bool rt_isula_detect(const char *runtime)
|
|
{
|
|
if (runtime != NULL && (strcasecmp(runtime, "lcr") != 0)) {
|
|
@@ -463,8 +483,9 @@ static void runtime_exec_param_init(runtime_exec_info *rei)
|
|
}
|
|
}
|
|
|
|
-static int runtime_exec_info_init(runtime_exec_info *rei, const char *workdir, const char *root_path, const char *runtime, const char *subcmd,
|
|
- const char **opts, size_t opts_len, const char *id, char **params, size_t params_num)
|
|
+static int runtime_exec_info_init(runtime_exec_info *rei, const char *workdir, const char *root_path,
|
|
+ const char *runtime, const char *subcmd, const char **opts, size_t opts_len, const char *id, char **params,
|
|
+ size_t params_num)
|
|
{
|
|
int ret = 0;
|
|
rei->workdir = workdir;
|
|
@@ -1012,6 +1033,7 @@ int rt_isula_create(const char *id, const char *runtime, const rt_create_params_
|
|
size_t runtime_args_len = 0;
|
|
int ret = 0;
|
|
char workdir[PATH_MAX] = { 0 };
|
|
+ char attach_socket[PATH_MAX] = { 0 };
|
|
shim_client_process_state p = { 0 };
|
|
int shim_exit_code = 0;
|
|
int nret = 0;
|
|
@@ -1034,6 +1056,13 @@ int rt_isula_create(const char *id, const char *runtime, const rt_create_params_
|
|
goto out;
|
|
}
|
|
|
|
+ nret = snprintf(attach_socket, sizeof(attach_socket), "%s/%s", workdir, ATTACH_SOCKET);
|
|
+ if (nret < 0 || (size_t)nret >= sizeof(attach_socket)) {
|
|
+ INFO("Failed to get full attach socket path");
|
|
+ ret = -1;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
p.exit_fifo = (char *)params->exit_fifo;
|
|
p.open_tty = params->tty;
|
|
p.open_stdin = params->open_stdin;
|
|
@@ -1042,6 +1071,7 @@ int rt_isula_create(const char *id, const char *runtime, const rt_create_params_
|
|
p.isulad_stderr = (char *)params->stderr;
|
|
p.runtime_args = (char **)runtime_args;
|
|
p.runtime_args_len = runtime_args_len;
|
|
+ p.attach_socket = attach_socket;
|
|
copy_process(&p, config->process);
|
|
copy_annotations(&p, config->annotations);
|
|
|
|
@@ -1224,7 +1254,7 @@ static bool fg_exec(const rt_exec_params_t *params)
|
|
return false;
|
|
}
|
|
|
|
-static char *try_generate_exec_id()
|
|
+static char *try_generate_random_id()
|
|
{
|
|
char *id = NULL;
|
|
|
|
@@ -1324,7 +1354,7 @@ int rt_isula_exec(const char *id, const char *runtime, const rt_exec_params_t *p
|
|
if (params->suffix != NULL) {
|
|
exec_id = util_strdup_s(params->suffix);
|
|
} else {
|
|
- exec_id = try_generate_exec_id();
|
|
+ exec_id = try_generate_random_id();
|
|
}
|
|
if (exec_id == NULL) {
|
|
ERROR("Out of memory or generate exec id failed");
|
|
@@ -1423,13 +1453,133 @@ out:
|
|
return ret;
|
|
}
|
|
|
|
-int rt_isula_attach(const char *id, const char *runtime, const rt_attach_params_t *params)
|
|
+static int get_container_attach_statuscode(const char *workdir, int attach_shim_fd)
|
|
{
|
|
- ERROR("isula attach not support on isulad-shim");
|
|
- isulad_set_error_message("isula attach not support on isulad-shim");
|
|
+ int status_code = 0;
|
|
+ int ret = -1;
|
|
+ struct timespec beg = { 0 };
|
|
+ struct timespec end = { 0 };
|
|
+
|
|
+ if (clock_gettime(CLOCK_MONOTONIC, &beg) != 0) {
|
|
+ ERROR("Failed get time");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ while (true) {
|
|
+ if (clock_gettime(CLOCK_MONOTONIC, &end) != 0) {
|
|
+ ERROR("Failed get time");
|
|
+ return -1;
|
|
+ }
|
|
+ if (end.tv_sec - beg.tv_sec > ATTACH_WAIT_TIME) {
|
|
+ ERROR("Wait container attach exitcode timeout");
|
|
+ return -1;
|
|
+ }
|
|
+ ret = util_read_nointr(attach_shim_fd, &status_code, sizeof(int));
|
|
+ if (ret <= 0) {
|
|
+ if (shim_alive(workdir)) {
|
|
+ // wait 100 millisecond to read exit code
|
|
+ util_usleep_nointerupt(100000);
|
|
+ continue;
|
|
+ }
|
|
+ ERROR("Failed read pid from dead shim %s", workdir);
|
|
+ return -1;
|
|
+ }
|
|
+ return status_code; /* success */
|
|
+ }
|
|
return -1;
|
|
}
|
|
|
|
+static int get_attach_socketfd(const char *attach_socket, int *socket_fd)
|
|
+{
|
|
+ struct sockaddr_un addr = { 0 };
|
|
+ __isula_auto_close int tmp_socket = -1;
|
|
+
|
|
+ if (strlen(attach_socket) >= sizeof(addr.sun_path)) {
|
|
+ SYSERROR("Invalid attach socket path: %s", attach_socket);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ tmp_socket = socket(AF_UNIX, SOCK_STREAM, 0);
|
|
+ if (tmp_socket < 0) {
|
|
+ SYSERROR("Failed to create attach socket");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (isula_set_non_block(tmp_socket) < 0) {
|
|
+ SYSERROR("Failed to set socket non block");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ (void)memset(&addr, 0, sizeof(addr));
|
|
+ addr.sun_family = AF_UNIX;
|
|
+ (void)strcpy(addr.sun_path, attach_socket);
|
|
+
|
|
+ if (connect(tmp_socket, (void *)&addr, sizeof(addr)) < 0) {
|
|
+ SYSERROR("Failed to connect attach socket: %s", attach_socket);
|
|
+ return -1;
|
|
+ }
|
|
+ *socket_fd = isula_transfer_fd(tmp_socket);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int rt_isula_attach(const char *id, const char *runtime, const rt_attach_params_t *params)
|
|
+{
|
|
+ int ret = 0;
|
|
+ int len = 0;
|
|
+ int status_code = 0;
|
|
+ __isula_auto_close int socket_fd = -1;
|
|
+ char buf[BUFSIZ] = { 0 };
|
|
+ char workdir[PATH_MAX] = { 0 };
|
|
+ char attach_socket[PATH_MAX] = { 0 };
|
|
+
|
|
+ if (id == NULL || runtime == NULL || params == NULL) {
|
|
+ ERROR("Null argument");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ ret = snprintf(workdir, sizeof(workdir), "%s/%s", params->state, id);
|
|
+ if (ret < 0 || (size_t)ret >= sizeof(workdir)) {
|
|
+ ERROR("Failed join exec full path");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ // the communication format between isulad and isulad-shim attach is:
|
|
+ // stdin-path stdout-path stderr-path
|
|
+ len = snprintf(buf, sizeof(buf), "%s %s %s", params->stdin, params->stdout, params->stderr);
|
|
+ if (len < 0 || (size_t)len >= sizeof(buf)) {
|
|
+ ERROR("Failed to snprintf string");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ ret = snprintf(attach_socket, sizeof(attach_socket), "%s/%s", workdir, ATTACH_SOCKET);
|
|
+ if (ret < 0 || (size_t)ret >= sizeof(attach_socket)) {
|
|
+ ERROR("Failed to get full attach socket path");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ ret = get_attach_socketfd(attach_socket, &socket_fd);
|
|
+ if (ret < 0) {
|
|
+ ERROR("Failed to get attach socketfd");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ DEBUG("write %s to attach fd", buf);
|
|
+
|
|
+ ret = isula_file_write_nointr(socket_fd, buf, len);
|
|
+ if (ret < 0) {
|
|
+ SYSERROR("Failed to write attach isulad fd");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ status_code = get_container_attach_statuscode(workdir, socket_fd);
|
|
+ if (status_code < 0) {
|
|
+ show_shim_attach_errlog(workdir);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int to_engine_resources_unified(const host_config *hostconfig, shim_client_cgroup_resources *cr)
|
|
{
|
|
int i;
|
|
@@ -1673,7 +1823,7 @@ static int parse_ps_data(char *stdout_msg, rt_listpids_out_t *out)
|
|
}
|
|
|
|
static int runtime_call_ps(const char *workdir, const char *runtime, const char *id,
|
|
- rt_listpids_out_t *out)
|
|
+ rt_listpids_out_t *out)
|
|
{
|
|
__isula_auto_free char *stdout_msg = NULL;
|
|
__isula_auto_free char *stderr_msg = NULL;
|
|
@@ -1681,7 +1831,7 @@ static int runtime_call_ps(const char *workdir, const char *runtime, const char
|
|
int ret = 0;
|
|
int nret = 0;
|
|
char *params[PARAM_NUM] = { 0 };
|
|
- const char *opts[2] = { "--format" , "json" };
|
|
+ const char *opts[2] = { "--format", "json" };
|
|
char root_path[PATH_MAX] = { 0 };
|
|
|
|
nret = snprintf(root_path, PATH_MAX, "%s/%s", workdir, runtime);
|
|
diff --git a/src/utils/cutils/error.h b/src/utils/cutils/error.h
|
|
index 088ed261..75eae760 100644
|
|
--- a/src/utils/cutils/error.h
|
|
+++ b/src/utils/cutils/error.h
|
|
@@ -44,8 +44,10 @@ extern "C" {
|
|
/* err in runtime module */ \
|
|
XX(ERR_RUNTIME, DEF_ERR_RUNTIME_STR) \
|
|
\
|
|
+ /* info for detach */ \
|
|
+ XX(INFO_DETACH, "Attach detach") \
|
|
/* err max */ \
|
|
- XX(ERR_UNKNOWN, "Unknown error")
|
|
+ XX(ERR_UNKNOWN, "Unknown error")
|
|
|
|
#define ISULAD_ERRNO_GEN(n, s) ISULAD_##n,
|
|
typedef enum { ISULAD_ERRNO_MAP(ISULAD_ERRNO_GEN) } isulad_errno_t;
|
|
--
|
|
2.42.0
|
|
|