From bfc5d283ad9558d169bdb70e6b43876f5aa0062c Mon Sep 17 00:00:00 2001 From: yinbin Date: Tue, 31 Dec 2024 14:45:58 +0800 Subject: [PATCH] SIGNAL: Adjust sigaction function to keep lstack signal function executed successfully. --- src/lstack/api/lstack_unistd.c | 91 ++++++++++++++++++---- src/lstack/core/lstack_dump.c | 4 +- src/lstack/core/lstack_protocol_stack.c | 23 +++++- src/lstack/core/lstack_stack_stat.c | 24 +++--- src/lstack/core/lstack_thread_rpc.c | 1 + src/lstack/include/lstack_protocol_stack.h | 3 + 6 files changed, 117 insertions(+), 29 deletions(-) diff --git a/src/lstack/api/lstack_unistd.c b/src/lstack/api/lstack_unistd.c index 47d80ec..90e603e 100644 --- a/src/lstack/api/lstack_unistd.c +++ b/src/lstack/api/lstack_unistd.c @@ -26,23 +26,54 @@ 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])) +static struct sigaction g_register_sigactions[NSIG]; // NSIG is the signal counts of system, normally equal 65 in Linux. +static void lstack_sig_default_handler(int sig); + +static bool sig_is_registered(int sig) +{ + if (g_register_sigactions[sig].sa_handler != NULL && + g_register_sigactions[sig].sa_handler != (void *) lstack_sig_default_handler) { + return true; + } + return false; +} + static inline bool match_hijack_signal(int sig) { unsigned int i; for (i = 0; i < HIJACK_SIGNAL_COUNT; i++) { if (sig == g_hijack_signal[i]) { - return 1; + return true; } } - return 0; + return false; } -static void lstack_sig_default_handler(int sig) +/* When operations such as pressing Ctrl+C or Kill are executed, we don't need to dump the stack. */ +bool sig_need_dump(int sig) { + if (sig == SIGINT || sig == SIGTERM || sig == SIGKILL) { + return false; + } + return true; +} + +static void lstack_sigaction_default_handler(int sig, siginfo_t *info, void *context) +{ + static bool skip_process_exit = false; + + /* avoiding sig function being executed twice. */ + if (!skip_process_exit) { + skip_process_exit = true; + } else { + return; + } + LSTACK_LOG(ERR, LSTACK, "lstack dumped, caught signal: %d\n", sig); - /* When operations such as pressing Ctrl+C or Kill, the call stack exit is not displayed. */ - if (sig != SIGINT && sig != SIGTERM && sig != SIGKILL) { + stack_stop(); + + if (sig_need_dump(sig)) { /* dump stack info */ dump_stack(); @@ -50,17 +81,31 @@ static void lstack_sig_default_handler(int sig) dump_lstack(); } + if (sig_is_registered(sig)) { + if (g_register_sigactions[sig].sa_flags & SA_SIGINFO) { + g_register_sigactions[sig].sa_sigaction(sig, info, context); + } else { + g_register_sigactions[sig].sa_handler(sig); + } + } + if (get_global_cfg_params() && get_global_cfg_params()->is_primary) { delete_primary_path(); } control_fd_close(); + stack_exit(); lwip_exit(); gazelle_exit(); (void)kill(getpid(), sig); } +static void lstack_sig_default_handler(int sig) +{ + lstack_sigaction_default_handler(sig, NULL, NULL); +} + static void pthread_block_sig(int sig) { sigset_t mask; @@ -105,18 +150,34 @@ int lstack_sigaction(int sig_num, const struct sigaction *action, struct sigacti { struct sigaction new_action; - if ((match_hijack_signal(sig_num) != 0) && (action && action->sa_handler == SIG_DFL)) { + if (match_hijack_signal(sig_num) && action != NULL) { new_action = *action; - new_action.sa_flags |= SA_RESETHAND; - new_action.sa_handler = lstack_sig_default_handler; - return posix_api->sigaction_fn(sig_num, &new_action, old_action); - } - /* SA_INTERRUPT is deprecated, use SA_RESETHAND instead. */ - if ((match_hijack_signal(sig_num) != 0) && (action && action->sa_flags == SA_INTERRUPT)) { - new_action = *action; - new_action.sa_flags |= SA_RESETHAND; - return posix_api->sigaction_fn(sig_num, &new_action, old_action); + if (action->sa_handler == SIG_DFL) { + new_action = *action; + new_action.sa_flags |= SA_RESETHAND; + new_action.sa_handler = lstack_sig_default_handler; + return posix_api->sigaction_fn(sig_num, &new_action, old_action); + } + + /* SA_INTERRUPT is deprecated, use SA_RESETHAND instead. */ + if (action->sa_flags == SA_INTERRUPT) { + new_action = *action; + new_action.sa_flags |= SA_RESETHAND; + return posix_api->sigaction_fn(sig_num, &new_action, old_action); + } + + if (sig_need_dump(sig_num)) { + g_register_sigactions[sig_num] = new_action; + + /* If SA_SIGINFO is setted, we use sa_sigaction. */ + if (action->sa_flags & SA_SIGINFO) { + new_action.sa_sigaction = lstack_sigaction_default_handler; + } else { + new_action.sa_handler = lstack_sig_default_handler; + } + return posix_api->sigaction_fn(sig_num, &new_action, old_action); + } } return posix_api->sigaction_fn(sig_num, action, old_action); diff --git a/src/lstack/core/lstack_dump.c b/src/lstack/core/lstack_dump.c index d415ddc..2a4477d 100644 --- a/src/lstack/core/lstack_dump.c +++ b/src/lstack/core/lstack_dump.c @@ -23,14 +23,16 @@ #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 -v", + "gazellectl lstack show 1 -I", "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", "gazellectl lstack show 1 -c" }; diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c index 2c60a49..1eebac4 100644 --- a/src/lstack/core/lstack_protocol_stack.c +++ b/src/lstack/core/lstack_protocol_stack.c @@ -51,7 +51,7 @@ static void stack_set_state(struct protocol_stack *stack, enum rte_lcore_state_t __atomic_store_n(&stack->state, state, __ATOMIC_RELEASE); } -static enum rte_lcore_state_t stack_get_state(struct protocol_stack *stack) +enum rte_lcore_state_t stack_get_state(struct protocol_stack *stack) { return __atomic_load_n(&stack->state, __ATOMIC_ACQUIRE); } @@ -777,17 +777,32 @@ OUT2: return -1; } -void stack_exit(void) +static void stack_all_fds_close(struct protocol_stack *stack) { - /* close all fd */ for (int i = 3; i < GAZELLE_MAX_CLIENTS + GAZELLE_RESERVED_CLIENTS; i++) { struct lwip_sock *sock = lwip_get_socket(i); - if (!POSIX_IS_CLOSED(sock) && sock->stack == get_protocol_stack()) { + if (!POSIX_IS_CLOSED(sock) && sock->stack == stack) { lwip_close(i); } } } +void stack_exit(void) +{ + struct protocol_stack *stack = get_protocol_stack(); + if (stack != NULL) { + stack_all_fds_close(stack); + } +} + +void stack_stop(void) +{ + struct protocol_stack *stack = get_protocol_stack(); + if (stack != NULL) { + stack_set_state(stack, WAIT); + } +} + void stack_group_exit(void) { int i; diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c index c88da8f..b1eb60e 100644 --- a/src/lstack/core/lstack_stack_stat.c +++ b/src/lstack/core/lstack_stack_stat.c @@ -30,6 +30,7 @@ #include "lstack_dpdk.h" #include "lstack_stack_stat.h" #include "lstack_virtio.h" +#include "lstack_dump.h" void time_stamp_transfer_pbuf(struct pbuf *pbuf_old, struct pbuf *pbuf_new) { @@ -263,11 +264,13 @@ static void get_stack_stats(struct gazelle_stack_dfx_data *dfx, struct protocol_ int32_t rpc_call_result = rpc_msgcnt(&stack->rpc_queue); dfx->data.pkts.call_msg_cnt = (rpc_call_result < 0) ? 0 : rpc_call_result; - rpc_call_result = rpc_call_mbufpoolsize(&stack->dfx_rpc_queue); - dfx->data.pkts.mbufpool_avail_cnt = (rpc_call_result < 0) ? 0 : rpc_call_result; + if (stack_get_state(stack) == RUNNING) { + rpc_call_result = rpc_call_mbufpoolsize(&stack->dfx_rpc_queue); + dfx->data.pkts.mbufpool_avail_cnt = (rpc_call_result < 0) ? 0 : rpc_call_result; - rpc_call_result = rpc_call_recvlistcnt(&stack->dfx_rpc_queue); - dfx->data.pkts.recv_list_cnt = (rpc_call_result < 0) ? 0 : rpc_call_result; + rpc_call_result = rpc_call_recvlistcnt(&stack->dfx_rpc_queue); + dfx->data.pkts.recv_list_cnt = (rpc_call_result < 0) ? 0 : rpc_call_result; + } dfx->data.pkts.conn_num = stack->conn_num; } @@ -343,11 +346,14 @@ static void get_stack_dfx_data(struct gazelle_stack_dfx_data *dfx, struct protoc } break; case GAZELLE_STAT_LSTACK_SHOW_CONN: - rpc_call_result = rpc_call_conntable(&stack->dfx_rpc_queue, dfx->data.conn.conn_list, - GAZELLE_LSTACK_MAX_CONN); - dfx->data.conn.conn_num = (rpc_call_result < 0) ? 0 : rpc_call_result; - rpc_call_result = rpc_call_connnum(&stack->dfx_rpc_queue); - dfx->data.conn.total_conn_num = (rpc_call_result < 0) ? 0 : rpc_call_result; + if (stack_get_state(stack) == RUNNING) { + rpc_call_result = rpc_call_conntable(&stack->dfx_rpc_queue, dfx->data.conn.conn_list, + GAZELLE_LSTACK_MAX_CONN); + dfx->data.conn.conn_num = (rpc_call_result < 0) ? 0 : rpc_call_result; + rpc_call_result = rpc_call_connnum(&stack->dfx_rpc_queue); + dfx->data.conn.total_conn_num = (rpc_call_result < 0) ? 0 : rpc_call_result; + } + break; case GAZELLE_STAT_LSTACK_SHOW_LATENCY: ret = memcpy_s(&dfx->data.latency, sizeof(dfx->data.latency), &stack->latency, sizeof(stack->latency)); diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c index 26bd16a..9f871af 100644 --- a/src/lstack/core/lstack_thread_rpc.c +++ b/src/lstack/core/lstack_thread_rpc.c @@ -146,6 +146,7 @@ static struct rpc_msg *rpc_msg_alloc_except(rpc_func_t func) static void stack_exit_by_rpc(struct rpc_msg *msg) { + stack_stop(); stack_exit(); } diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h index 068e9d2..c7c7efe 100644 --- a/src/lstack/include/lstack_protocol_stack.h +++ b/src/lstack/include/lstack_protocol_stack.h @@ -120,10 +120,13 @@ void thread_bind_stack(struct protocol_stack *stack); int stack_group_init(void); void stack_group_exit(void); void stack_exit(void); +void stack_stop(void); int stack_setup_thread(void); int stack_setup_app_thread(void); int stack_polling(unsigned wakeup_tick); +enum rte_lcore_state_t stack_get_state(struct protocol_stack *stack); + #endif -- 2.33.0