From 71fee80519b321b565cdec74d9e7fae25f9bc750 Mon Sep 17 00:00:00 2001 From: yinbin Date: Sat, 30 Nov 2024 16:05:02 +0800 Subject: [PATCH] DUMP: gazelle supports dump lstack --- src/lstack/api/lstack_unistd.c | 36 +++----- src/lstack/core/lstack_dump.c | 144 +++++++++++++++++++++++++++++++ src/lstack/include/lstack_dump.h | 19 ++++ 3 files changed, 176 insertions(+), 23 deletions(-) create mode 100644 src/lstack/core/lstack_dump.c create mode 100644 src/lstack/include/lstack_dump.h diff --git a/src/lstack/api/lstack_unistd.c b/src/lstack/api/lstack_unistd.c index 1f78626..8fd6490 100644 --- a/src/lstack/api/lstack_unistd.c +++ b/src/lstack/api/lstack_unistd.c @@ -11,7 +11,6 @@ */ #include -#include #include #include @@ -22,28 +21,11 @@ #include "lstack_log.h" #include "lstack_cfg.h" #include "lstack_control_plane.h" +#include "lstack_dump.h" static int g_hijack_signal[] = { SIGTERM, SIGINT, SIGSEGV, SIGBUS, SIGFPE, SIGILL, SIGKILL}; #define HIJACK_SIGNAL_COUNT (sizeof(g_hijack_signal) / sizeof(g_hijack_signal[0])) -#define BACKTRACE_SIZE 64 -static void dump_stack(void) -{ - char **stack_trace = NULL; - void *stack_array[BACKTRACE_SIZE]; - int stack_num = backtrace(stack_array, BACKTRACE_SIZE); - - stack_trace = (char**)backtrace_symbols(stack_array, stack_num); - if (stack_trace == NULL) { - perror("backtrace_symbols"); - return; - } - - for (int i = 0; i < stack_num; i++) { - LSTACK_LOG(ERR, LSTACK, "%s\n", stack_trace[i]); - } - free(stack_trace); -} static inline bool match_hijack_signal(int sig) { unsigned int i; @@ -58,14 +40,22 @@ static inline bool match_hijack_signal(int sig) static void lstack_sig_default_handler(int sig) { LSTACK_LOG(ERR, LSTACK, "lstack dumped, caught signal: %d\n", sig); - if (get_global_cfg_params() && get_global_cfg_params()->is_primary) { - delete_primary_path(); - } - control_fd_close(); + /* When operations such as pressing Ctrl+C or Kill, the call stack exit is not displayed. */ if (sig != SIGINT && sig != SIGTERM && sig != SIGKILL) { + /* dump stack info */ dump_stack(); + + /* dump internal information of lstack */ + dump_lstack(); } + + if (get_global_cfg_params() && get_global_cfg_params()->is_primary) { + delete_primary_path(); + } + + control_fd_close(); + lwip_exit(); gazelle_exit(); (void)kill(getpid(), sig); diff --git a/src/lstack/core/lstack_dump.c b/src/lstack/core/lstack_dump.c new file mode 100644 index 0000000..d415ddc --- /dev/null +++ b/src/lstack/core/lstack_dump.c @@ -0,0 +1,144 @@ +/* +* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. +* gazelle is licensed under the Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +* PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +#include +#include +#include + +#include "lstack_cfg.h" +#include "lstack_log.h" + +#define DUMP_COMMAND_TIMEOUT_MS 2000 +#define DUMP_COMMAND_INTERVAL_MS 1 +#define DUMP_BUF_SZ 1024 +#define DUMP_BACKTRACE_SIZE 64 + +static const char *dump_command[] = { + "gazellectl lstack show 1", + "gazellectl lstack show 1 -s", + "gazellectl lstack show 1 -x", + "gazellectl lstack show 1 -p UDP", + "gazellectl lstack show 1 -p TCP", + "gazellectl lstack show 1 -p ICMP", + "gazellectl lstack show 1 -p IP", + "gazellectl lstack show 1 -p ETHARP", + "gazellectl lstack show 1 -c" +}; + +static int dump_lstack_check(void) +{ + /* In ltran mode, dump commands maybe illegal */ + if (use_ltran()) { + LSTACK_LOG(ERR, LSTACK, "ltran mode doesn't support lstack info dump.\n"); + return -1; + } + + LSTACK_LOG(INFO, LSTACK, "Dump lstack check passed. Dumping information:\n"); + return 0; +} + +#define US_PER_MS (MS_PER_S) +static long timeval_diff_ms(struct timeval *end, struct timeval *begin) +{ + struct timeval result; + long result_ms; + + result.tv_sec = end->tv_sec - begin->tv_sec; + result.tv_usec = end->tv_usec - begin->tv_usec; + + result_ms = result.tv_sec * MS_PER_S + result.tv_usec / US_PER_MS; + return result_ms; +} + +static int dump_command_excute(const char *command) +{ + FILE *fp; + int flags, fd; + char buffer[DUMP_BUF_SZ]; + struct timeval start, now; + long elapsed; + + if ((fp = popen(command, "r")) == NULL) { + LSTACK_LOG(ERR, LSTACK, "popen() failed, command \"%s\" didn't excute.\n", command); + return -1; + } + + fd = fileno(fp); + flags = fcntl(fd, F_GETFL, 0); + fcntl(fd, F_SETFL, flags | O_NONBLOCK); + + gettimeofday(&start, NULL); + + /* Loop to print command output while checking for timeout. */ + while (1) { + gettimeofday(&now, NULL); + elapsed = timeval_diff_ms(&now, &start); + + /* check timeout */ + if (elapsed > DUMP_COMMAND_TIMEOUT_MS) { + LSTACK_LOG(ERR, LSTACK, "Command timeout: %s\n", command); + pclose(fp); + return -1; + } + + /* get and print command output */ + if (fgets(buffer, sizeof(buffer), fp) != NULL) { + LSTACK_LOG(INFO, LSTACK, "\r %s", buffer); + } else if (feof(fp)) { + break; + } else { + usleep(DUMP_COMMAND_INTERVAL_MS * US_PER_MS); // 1ms + } + } + + pclose(fp); + return 0; +} + +void dump_lstack(void) +{ + int ret, command_count; + + ret = dump_lstack_check(); + if (ret < 0) { + LSTACK_LOG(ERR, LSTACK, "lstack dump check failed, dump process exited!\n"); + return; + } + + command_count = sizeof(dump_command) / sizeof(dump_command[0]); + for (int i = 0; i < command_count; ++i) { + LSTACK_LOG(INFO, LSTACK, "Dump command: \"%s\"\n", dump_command[i]); + + ret = dump_command_excute(dump_command[i]); + if (ret < 0) { + LSTACK_LOG(ERR, LSTACK, "Dump command: \"%s\" excute failed.\n", dump_command[i]); + } + } +} + +void dump_stack(void) +{ + char **stack_trace = NULL; + void *stack_array[DUMP_BACKTRACE_SIZE]; + int stack_num = backtrace(stack_array, DUMP_BACKTRACE_SIZE); + + stack_trace = (char**)backtrace_symbols(stack_array, stack_num); + if (stack_trace == NULL) { + LSTACK_LOG(ERR, LSTACK, "Error in backtrace_symbols, errno %d\n", errno); + return; + } + + for (int i = 0; i < stack_num; i++) { + LSTACK_LOG(ERR, LSTACK, "%s\n", stack_trace[i]); + } + free(stack_trace); +} diff --git a/src/lstack/include/lstack_dump.h b/src/lstack/include/lstack_dump.h new file mode 100644 index 0000000..83f2fd9 --- /dev/null +++ b/src/lstack/include/lstack_dump.h @@ -0,0 +1,19 @@ +/* +* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. +* gazelle is licensed under the Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +* PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +#ifndef _GAZELLE_DUMP_H_ +#define _GAZELLE_DUMP_H_ + +void dump_stack(void); +void dump_lstack(void); + +#endif /* _GAZELLE_DUMP_H_ */ -- 2.33.0