From e671d01c7ab6183a602c9c3e4b7f30d619831719 Mon Sep 17 00:00:00 2001
From: zhongtao <zhongtao17@huawei.com>
Date: Tue, 6 Jun 2023 11:55:16 +0000
Subject: [PATCH 10/15] !2047 distinguishing exit codes between shim and
 container processes * distinguishing exit codes between shim and container
 processes

---
 src/cmd/isulad-shim/main.c                    | 10 ++-
 src/cmd/isulad-shim/process.c                 |  8 ++-
 .../modules/runtime/isula/isula_rt_ops.c      | 65 +++++++++++++++----
 3 files changed, 65 insertions(+), 18 deletions(-)

diff --git a/src/cmd/isulad-shim/main.c b/src/cmd/isulad-shim/main.c
index ed55805c..e2625aac 100644
--- a/src/cmd/isulad-shim/main.c
+++ b/src/cmd/isulad-shim/main.c
@@ -160,5 +160,13 @@ int main(int argc, char **argv)
 
     released_timeout_exit();
 
-    return process_signal_handle_routine(p, tid_epoll, timeout);
+    ret = process_signal_handle_routine(p, tid_epoll, timeout);
+    if (ret == SHIM_ERR) {
+        exit(EXIT_FAILURE);
+    }
+    if (ret == SHIM_ERR_TIMEOUT) {
+        exit(SHIM_EXIT_TIMEOUT);
+    }
+
+    exit(EXIT_SUCCESS);
 }
diff --git a/src/cmd/isulad-shim/process.c b/src/cmd/isulad-shim/process.c
index aa3aa37c..138a71fb 100644
--- a/src/cmd/isulad-shim/process.c
+++ b/src/cmd/isulad-shim/process.c
@@ -1264,7 +1264,7 @@ int process_signal_handle_routine(process_t *p, const pthread_t tid_epoll, const
         nret = kill(p->ctr_pid, SIGKILL);
         if (nret < 0 && errno != ESRCH) {
             write_message(g_log_fd, ERR_MSG, "Can not kill process (pid=%d) with SIGKILL", p->ctr_pid);
-            exit(EXIT_FAILURE);
+            return SHIM_ERR;
         }
     }
 
@@ -1302,8 +1302,10 @@ int process_signal_handle_routine(process_t *p, const pthread_t tid_epoll, const
 
     if (ret == SHIM_ERR_TIMEOUT) {
         write_message(g_log_fd, INFO_MSG, "Wait %d timeout", p->ctr_pid);
-        exit(SHIM_EXIT_TIMEOUT);
+        return SHIM_ERR_TIMEOUT;
     }
-    return status;
 
+    // write container process exit_code in stdout
+    (void)write_nointr(STDOUT_FILENO, &status, sizeof(int));
+    return SHIM_OK;
 }
diff --git a/src/daemon/modules/runtime/isula/isula_rt_ops.c b/src/daemon/modules/runtime/isula/isula_rt_ops.c
index 9fe3ac4b..3fe895f8 100644
--- a/src/daemon/modules/runtime/isula/isula_rt_ops.c
+++ b/src/daemon/modules/runtime/isula/isula_rt_ops.c
@@ -672,9 +672,9 @@ static int runtime_call_kill_and_check(const char *workdir, const char *runtime,
 static int runtime_call_delete_force(const char *workdir, const char *runtime, const char *id)
 {
     const char *opts[1] = { "--force" };
-    // delete succeed, return 0; 
-    // When the runc version is less than or equal to v1.0.0-rc3, 
-    // if the container does not exist when force deleting it, 
+    // delete succeed, return 0;
+    // When the runc version is less than or equal to v1.0.0-rc3,
+    // if the container does not exist when force deleting it,
     // runc will report an error and isulad does not need to retry the deletion again.
     // related PR ID:d1a743674a98e23d348b29f52c43436356f56b79
     // non_existent_output_check succeed, return 0;
@@ -699,11 +699,16 @@ static int status_to_exit_code(int status)
     return exit_code;
 }
 
+/*
+    exit_code records the exit code of the container, obtained by reading the stdout of isulad-shim;
+    shim_exit_code records the exit code of isulad-shim, obtained through waitpid;
+*/
 static int shim_create(bool fg, const char *id, const char *workdir, const char *bundle, const char *runtime_cmd,
-                       int *exit_code, const char* timeout)
+                       int *exit_code, const char* timeout, int* shim_exit_code)
 {
     pid_t pid = 0;
     int exec_fd[2] = { -1, -1 };
+    int shim_stdout_pipe[2] = { -1, -1 };
     int num = 0;
     int ret = 0;
     char exec_buff[BUFSIZ + 1] = { 0 };
@@ -733,11 +738,18 @@ static int shim_create(bool fg, const char *id, const char *workdir, const char
         return -1;
     }
 
+    if (pipe2(shim_stdout_pipe, O_CLOEXEC) != 0) {
+        ERROR("Failed to create pipe for shim exit code");
+        return -1;
+    }
+
     pid = fork();
     if (pid < 0) {
         ERROR("Failed fork for shim parent %s", strerror(errno));
         close(exec_fd[0]);
         close(exec_fd[1]);
+        close(shim_stdout_pipe[0]);
+        close(shim_stdout_pipe[1]);
         return -1;
     }
 
@@ -772,12 +784,21 @@ static int shim_create(bool fg, const char *id, const char *workdir, const char
 realexec:
         /* real shim process. */
         close(exec_fd[0]);
+        close(shim_stdout_pipe[0]);
+        // child process, dup2 shim_stdout_pipe[1] to STDOUT
+        if (dup2(shim_stdout_pipe[1], STDOUT_FILENO) < 0) {
+            (void)dprintf(exec_fd[1], "Dup fd error: %s", strerror(errno));
+            exit(EXIT_FAILURE);
+        }
+        
         if (setsid() < 0) {
             (void)dprintf(exec_fd[1], "%s: failed setsid for process %d", id, getpid());
             exit(EXIT_FAILURE);
         }
-
-        if (util_check_inherited(true, exec_fd[1]) != 0) {
+        int ignore_fd[2] = {-1, -1};
+        ignore_fd[0] = exec_fd[1];
+        ignore_fd[1] = shim_stdout_pipe[1];
+        if (util_check_inherited_exclude_fds(true, ignore_fd, 2) != 0) {
             (void)dprintf(exec_fd[1], "close inherited fds failed");
         }
 
@@ -786,26 +807,40 @@ realexec:
     }
 
     close(exec_fd[1]);
+    close(shim_stdout_pipe[1]);
     num = util_read_nointr(exec_fd[0], exec_buff, sizeof(exec_buff) - 1);
-    close(exec_fd[0]);
     if (num > 0) {
-        ERROR("exec failed: %s", exec_buff);
+        ERROR("Exec failed: %s", exec_buff);
         ret = -1;
         goto out;
     }
 
     status = util_wait_for_pid_status(pid);
     if (status < 0) {
-        ERROR("failed wait shim-parent %d exit %s", pid, strerror(errno));
+        ERROR("Failed wait shim-parent %d exit %s", pid, strerror(errno));
         ret = -1;
         goto out;
     }
 
-    if (exit_code != NULL) {
-        *exit_code = status_to_exit_code(status);
+    *shim_exit_code = status_to_exit_code(status);
+    if (*shim_exit_code != 0) {
+        ERROR("Isulad-shim exit error");
+        ret = -1;
+        goto out;
     }
 
+    if (exit_code == NULL) {
+        goto out;
+    }
+    ret = util_read_nointr(shim_stdout_pipe[0], exit_code, sizeof(int));
+    if (ret <= 0) {
+        *exit_code = 137;
+    }
+    ret = 0;
+
 out:
+    close(exec_fd[0]);
+    close(shim_stdout_pipe[0]);
     if (ret != 0) {
         show_shim_runtime_errlog(workdir);
         if (timeout <= 0) {
@@ -887,6 +922,7 @@ int rt_isula_create(const char *id, const char *runtime, const rt_create_params_
     int ret = 0;
     char workdir[PATH_MAX] = { 0 };
     shim_client_process_state p = { 0 };
+    int shim_exit_code = 0;
 
     if (id == NULL || runtime == NULL || params == NULL) {
         ERROR("nullptr arguments not allowed");
@@ -919,7 +955,7 @@ int rt_isula_create(const char *id, const char *runtime, const rt_create_params_
     }
 
     get_runtime_cmd(runtime, &cmd);
-    ret = shim_create(false, id, workdir, params->bundle, cmd, NULL, NULL);
+    ret = shim_create(false, id, workdir, params->bundle, cmd, NULL, NULL, &shim_exit_code);
     if (ret != 0) {
         runtime_call_delete_force(workdir, runtime, id);
         ERROR("%s: failed create shim process", id);
@@ -1124,6 +1160,7 @@ int rt_isula_exec(const char *id, const char *runtime, const rt_exec_params_t *p
     int pid = 0;
     shim_client_process_state p = { 0 };
     char *timeout = NULL;
+    int shim_exit_code = 0;
 
     if (id == NULL || runtime == NULL || params == NULL || exit_code == NULL) {
         ERROR("nullptr arguments not allowed");
@@ -1199,13 +1236,13 @@ int rt_isula_exec(const char *id, const char *runtime, const rt_exec_params_t *p
         }
     }
 
-    ret = shim_create(fg_exec(params), id, workdir, bundle, cmd, exit_code, timeout);
+    ret = shim_create(fg_exec(params), id, workdir, bundle, cmd, exit_code, timeout, &shim_exit_code);
     if (ret != 0) {
         ERROR("%s: failed create shim process for exec %s", id, exec_id);
         goto errlog_out;
     }
 
-    if (*exit_code == SHIM_EXIT_TIMEOUT) {
+    if (shim_exit_code == SHIM_EXIT_TIMEOUT) {
         ret = -1;
         isulad_set_error_message("Exec container error;exec timeout");
         ERROR("isulad-shim %d exit for execing timeout", pid);
-- 
2.25.1

