* Copyright (c) 2023 Huawei Technologies Co.,Ltd.
*
* DSS is licensed under 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.
* -------------------------------------------------------------------------
*
* dss_blackbox.c
*
*
* IDENTIFICATION
* src/service/dss_blackbox.c
*
* -------------------------------------------------------------------------
*/
#ifndef WIN32
#include <cm_signal.h>
#include <mes_func.h>
#include <cm_backtrace.h>
#include "dss_file_def.h"
#include "dss_session.h"
#include "dss_instance.h"
#include "dss_diskgroup.h"
#include "dss_ga.h"
#include "dss_blackbox.h"
#include "config.h"
#ifdef __cplusplus
extern "C" {
#endif
int32 g_sign_array[] = {SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGSEGV, SIGUSR2, SIGALRM,
SIGTERM, SIGSTKFLT, SIGTSTP, SIGTTIN, SIGTTOU, SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGIO, SIGPWR, SIGSYS};
box_excp_item_t g_excep_info = {0};
static const char *g_core_state_file = "dss.core.state";
char g_dss_state_file[CM_FILE_NAME_BUFFER_SIZE] = {0};
sig_info_t g_known_signal_info[] = {
{"Signal 0", TERMINATE_SIG},
{"Hang up controlling terminal or process", TERMINATE_SIG},
{"Interrupt from keyboard, Control-C", TERMINATE_SIG},
{"Quit from keyboard, Control-\\", DUMP_SIG},
{"Illegal instruction", DUMP_SIG},
{"Breakpoint for debugging", DUMP_SIG},
{"Abnormal termination", DUMP_SIG},
{"Bus error", DUMP_SIG},
{"Floating-point exception", DUMP_SIG},
{"Forced-process termination", TERMINATE_SIG},
{"User use", STOP_SIG},
{"Invalid memory reference", DUMP_SIG},
{"Available to processes", TERMINATE_SIG},
{"Write to pipe with no readers", TERMINATE_SIG},
{"Real-timer clock", TERMINATE_SIG},
{"Process termination", TERMINATE_SIG},
{"Coprocessor stack error", TERMINATE_SIG},
{"Child process stopped or terminated", IGNORE_SIG},
{"Resume execution, if stopped", CONTINUE_SIG},
{"Stop process execution, Ctrl-Z", STOP_SIG},
{"Stop process issued from tty", STOP_SIG},
{"Background process requires input", STOP_SIG},
{"Background process requires output", STOP_SIG},
{"Urgent condition on socket", IGNORE_SIG},
{"CPU time limit exceeded", DUMP_SIG},
{"File size limit exceeded", DUMP_SIG},
{"Virtual timer clock", TERMINATE_SIG},
{"Profile timer clock", TERMINATE_SIG},
{"Window resizing", IGNORE_SIG},
{"I/O now possible", TERMINATE_SIG},
{"Power supply failure", TERMINATE_SIG},
{"Bad system call", DUMP_SIG},
};
static inline bool8 need_dump(int signum)
{
if (signum >= 0 && signum < __SIGRTMIN) {
return g_known_signal_info[signum].action == DUMP_SIG;
}
return CM_FALSE;
}
const char *const g_other_signal_format = "Real-time signal %d";
const char *const g_unknown_signal_format = "Unknown signal %d";
void dss_get_signal_info(int signum, char *buf, uint32 buf_size)
{
int len;
sig_info_t *sig_info = NULL;
if (signum >= 0 && signum < __SIGRTMIN) {
sig_info = &g_known_signal_info[signum];
len = sprintf_s(buf, buf_size, "%s", sig_info->comment);
if (len < 0) {
buf[0] = 0x00;
}
return;
}
#ifdef SIGRTMIN
if (signum >= SIGRTMIN && signum <= SIGRTMAX) {
len = snprintf_s(buf, buf_size, buf_size - 1, g_other_signal_format, signum - SIGRTMIN);
if (len < 0) {
buf[0] = 0x00;
}
return;
}
#endif
}
static void dss_sig_collect_uds_lsnr_bt(uint32 log_id)
{
uds_lsnr_t *lsnr = &g_dss_instance.lsnr;
if (lsnr->status == LSNR_STATUS_RUNNING) {
cm_sig_collect_backtrace(log_id, &lsnr->thread, "uds_lsnr");
}
}
static void dss_sig_collect_timer_bt(uint32 log_id)
{
gs_timer_t *timer = g_timer();
if (!timer->init) {
return;
}
cm_sig_collect_backtrace(log_id, &timer->thread, "timer");
}
static void dss_sig_collect_recovery_bt(uint32 log_id)
{
uint32 recovery_thread_id = dss_get_udssession_startid() - (uint32)DSS_BACKGROUND_TASK_NUM;
cm_sig_collect_backtrace(log_id, &(g_dss_instance.threads[recovery_thread_id]), "recovery");
}
static void dss_sig_collect_hashmap_dynamic_extend_and_redistribute_bt(uint32 log_id)
{
uint32 hashmap_extend_idx = dss_get_hashmap_dynamic_extend_task_idx();
cm_sig_collect_backtrace(
log_id, &(g_dss_instance.threads[hashmap_extend_idx]), "hashmap_dynamic_extend_and_redistribute");
}
static void dss_sig_collect_alarm_check_bt(uint32 log_id)
{
uint32 vg_usage_thread_id = dss_get_alarm_check_task_idx();
cm_sig_collect_backtrace(log_id, &(g_dss_instance.threads[vg_usage_thread_id]), "alarm_check");
}
static void dss_sig_collect_delay_clean_bt(uint32 log_id)
{
uint32 delay_clean_thread_id = dss_get_delay_clean_task_idx();
cm_sig_collect_backtrace(log_id, &(g_dss_instance.threads[delay_clean_thread_id]), "delay_clean");
}
static void dss_sig_collect_recycle_meta_task_bt(uint32 log_id)
{
uint32 task_num = g_vgs_info->group_num;
if (task_num > DSS_RECYLE_META_TASK_NUM_MAX) {
task_num = DSS_RECYLE_META_TASK_NUM_MAX;
}
for (uint32 i = 0; i < task_num; i++) {
uint32 work_idx = dss_get_recycle_meta_task_idx(i);
cm_sig_collect_backtrace(log_id, &(g_dss_instance.threads[work_idx]), "recycle_meta %u", i);
}
}
static void dss_sig_collect_meta_syn_bt(uint32 log_id)
{
uint32 task_num = g_vgs_info->group_num;
if (task_num > DSS_META_SYN_BG_TASK_NUM_MAX) {
task_num = DSS_META_SYN_BG_TASK_NUM_MAX;
}
for (uint32 i = 0; i < task_num; i++) {
uint32 work_idx = dss_get_meta_syn_task_idx(i);
cm_sig_collect_backtrace(log_id, &(g_dss_instance.threads[work_idx]), "meta_syn %u", i);
}
}
static void dss_sig_collect_mes_task_bt(uint32 log_id)
{
uint32 count = mes_get_started_task_count(CM_FALSE);
for (uint32 i = 0; i < count; i++) {
cm_sig_collect_backtrace(log_id, &MES_GLOBAL_INST_MSG.recv_mq.tasks[i].thread, "mes task %d", i);
}
}
static void dss_sig_collect_mes_listener_bt(uint32 log_id)
{
mes_lsnr_t *lsnr = &MES_GLOBAL_INST_MSG.mes_ctx.lsnr;
if (MES_GLOBAL_INST_MSG.profile.pipe_type == MES_TYPE_TCP) {
tcp_lsnr_t *tcp_lsnr = &lsnr->tcp;
cm_sig_collect_backtrace(log_id, &tcp_lsnr->thread, "tcp lsnr");
}
}
static void dss_sig_collect_reactor_bt(uint32 log_id)
{
reactor_t *reactor = NULL;
reactors_t *pool = &g_dss_instance.reactors;
for (uint32 i = 0; i < pool->reactor_count; i++) {
reactor = &pool->reactor_arr[i];
if (reactor->status != REACTOR_STATUS_RUNNING) {
continue;
}
cm_sig_collect_backtrace(log_id, &reactor->iothread, "reactor %d", i);
}
}
static void dss_sig_collect_background_bt(uint32 log_id)
{
dss_sig_collect_mes_task_bt(log_id);
dss_sig_collect_mes_listener_bt(log_id);
dss_sig_collect_recovery_bt(log_id);
dss_sig_collect_hashmap_dynamic_extend_and_redistribute_bt(log_id);
dss_sig_collect_delay_clean_bt(log_id);
dss_sig_collect_alarm_check_bt(log_id);
dss_sig_collect_meta_syn_bt(log_id);
dss_sig_collect_recycle_meta_task_bt(log_id);
dss_sig_collect_uds_lsnr_bt(log_id);
dss_sig_collect_timer_bt(log_id);
dss_sig_collect_reactor_bt(log_id);
}
static void dss_sig_collect_work_session_bt(uint32 log_id)
{
dss_session_ctrl_t *session_ctrl = dss_get_session_ctrl();
for (uint32 i = 0; i < session_ctrl->alloc_sessions; i++) {
dss_session_t *session = session_ctrl->sessions[i];
if (session == NULL || session->is_closed) {
continue;
}
dss_workthread_t *workthread_ctx = (dss_workthread_t *)session->workthread_ctx;
if (workthread_ctx != NULL && workthread_ctx->status == THREAD_STATUS_PROCESSSING) {
cm_sig_collect_backtrace(log_id, &workthread_ctx->thread_obj->thread, "session %d", session->id);
}
}
}
void dss_sig_collect_all_backtrace(uint32 log_id)
{
dss_sig_collect_work_session_bt(log_id);
dss_sig_collect_background_bt(log_id);
}
void dss_print_global_variable(uint32 log_id)
{
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "\n===============================global variable===============================\n");
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "g_is_dss_read_write is %u\n", dss_get_server_status_flag());
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "g_master_instance_id is %u\n", dss_get_master_id());
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "dss_instance status is %u, is_maintain is %u.\n",
(uint32)g_dss_instance.status, (uint32)g_dss_instance.is_maintain);
dss_config_t *cfg = dss_get_inst_cfg();
dss_nodes_list_t nodes_list = cfg->params.nodes_list;
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "inst cnt is %u, inst_map is %llu, inst_work_status_map is %llu.\n",
nodes_list.inst_cnt, nodes_list.inst_map, g_dss_instance.inst_work_status_map);
for (uint32 i = 0; i < DSS_MAX_INSTANCES; i++) {
if (nodes_list.ports[i] != 0) {
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(
log_id, "%u: node_ip is %s, port is %hu.\n", i, nodes_list.nodes[i], nodes_list.ports[i]);
}
}
}
void dss_print_effect_param(uint32 log_id)
{
uint32 audit_level = cm_log_param_instance()->audit_level;
uint32 log_level = cm_log_param_instance()->log_level;
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(
log_id, "\n===============================key param===============================\n");
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "_LOG_LEVEL is %u.\n", log_level);
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "_AUDIT_LEVEL is %u.\n", audit_level);
}
void dss_write_block_pool(uint32 log_id, int32 handle, int64 *length, ga_pool_id_e pool_id)
{
ga_pool_t *pool = &g_app_pools[GA_POOL_IDX((uint32)pool_id)];
if (pool == NULL) {
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "Failed to get ga pool\n.");
return;
}
if (pool->ctrl->ex_count > GA_MAX_EXTENDED_POOLS) {
LOG_RUN_ERR("Invalid pool info[id=%u]: ex_count is %u, larger than maximum %u", pool_id, pool->ctrl->ex_count,
GA_MAX_EXTENDED_POOLS);
return;
}
uint32 object_cost = pool->ctrl->def.object_size + (uint32)sizeof(ga_object_map_t);
uint64 ex_pool_size = (uint64)object_cost * pool->ctrl->def.object_count;
uint64 total_size = pool->capacity + ex_pool_size * pool->ctrl->ex_count;
status_t ret = dss_write_shm_memory_file_inner(handle, length, &total_size, sizeof(uint64));
if (ret != CM_SUCCESS) {
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "Failed to write ga pool size, pool id is %u\n.", (uint32)pool_id);
}
ret = dss_write_shm_memory_file_inner(handle, length, (char *)pool->addr, (int32)pool->capacity);
if (ret != CM_SUCCESS) {
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "Failed to write init ga pool, pool id is %u\n.", (uint32)pool_id);
}
for (uint32 i = 0; i < pool->ctrl->ex_count; i++) {
ret = dss_write_shm_memory_file_inner(handle, length, pool->ex_pool_addr[i], (int32)ex_pool_size);
if (ret != CM_SUCCESS) {
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(
log_id, "Failed to write extend ga pool, pool id is %u, ex_num is %u\n.", (uint32)pool_id, i);
}
}
}
static void dss_update_shm_memory_length(uint32 log_id, int32 handle, int64 length, int64 begin)
{
int64 end = cm_seek_file(handle, 0, SEEK_CUR);
if (end == -1) {
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "Failed to seek file %d", handle);
return;
}
int64 offset = cm_seek_file(handle, begin, SEEK_SET);
if (offset == -1) {
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "Failed to seek file %d", handle);
return;
}
status_t ret = cm_write_file(handle, &length, sizeof(int64));
if (ret != CM_SUCCESS) {
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "Failed to update length %lld\n.", length);
}
offset = cm_seek_file(handle, end, SEEK_SET);
if (offset == -1) {
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "Failed to seek file %d", handle);
}
}
void dss_write_share_vg_info(uint32 log_id, int32 handle)
{
int64 length = 0;
int64 begin = cm_seek_file(handle, 0, SEEK_CUR);
if (begin == -1) {
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "Failed to seek file %d", handle);
}
status_t status = dss_write_shm_memory_file_inner(handle, &length, &length, sizeof(int64));
if (status != CM_SUCCESS) {
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "Failed to write length %lld\n.", length);
}
status = dss_write_shm_memory_file_inner(handle, &length, &g_vgs_info->group_num, sizeof(uint32_t));
if (status != CM_SUCCESS) {
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "Failed to write vg num %u\n.", g_vgs_info->group_num);
}
for (uint32 i = 0; i < g_vgs_info->group_num; i++) {
dss_vg_info_item_t *vg = &g_vgs_info->volume_group[i];
uint32 software_version = dss_get_software_version(&vg->dss_ctrl->vg_info);
status = dss_write_shm_memory_file_inner(handle, &length, &software_version, sizeof(uint32_t));
if (status != CM_SUCCESS) {
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "Failed to write software version %u.\n", software_version);
}
status = dss_write_shm_memory_file_inner(handle, &length, vg->dss_ctrl->vg_info.vg_name, DSS_MAX_NAME_LEN);
if (status != CM_SUCCESS) {
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "Failed to write vg name %s\n.", vg->dss_ctrl->vg_info.vg_name);
}
status = dss_write_shm_memory_file_inner(handle, &length, vg->dss_ctrl, sizeof(dss_ctrl_t));
if (status != CM_SUCCESS) {
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "Failed to write ctrl info of vg %u\n.", i);
}
}
dss_update_shm_memory_length(log_id, handle, length, begin);
}
void dss_write_hashmap_and_pool_info(uint32 log_id, int32 handle)
{
int64 length = 0;
int64 begin = cm_seek_file(handle, 0, SEEK_CUR);
if (begin == -1) {
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "Failed to seek file %d", handle);
}
status_t ret = dss_write_shm_memory_file_inner(handle, &length, &length, sizeof(int64));
if (ret != CM_SUCCESS) {
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "Failed to write length %lld\n.", length);
}
ret = dss_write_shm_memory_file_inner(handle, &length, &g_vgs_info->group_num, sizeof(uint32_t));
if (ret != CM_SUCCESS) {
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "Failed to write vg num %u\n.", g_vgs_info->group_num);
}
uint64 dir_size = DSS_MAX_SEGMENT_NUM * (uint32)sizeof(uint32_t);
for (uint32 i = 0; i < g_vgs_info->group_num; i++) {
dss_vg_info_item_t *vg = &g_vgs_info->volume_group[i];
ret = dss_write_shm_memory_file_inner(handle, &length, vg->dss_ctrl->vg_info.vg_name, DSS_MAX_NAME_LEN);
if (ret != CM_SUCCESS) {
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "Failed to write vg name %s\n.", vg->dss_ctrl->vg_info.vg_name);
}
ret = dss_write_shm_memory_file_inner(handle, &length, vg->buffer_cache, sizeof(shm_hashmap_t));
if (ret != CM_SUCCESS) {
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(
log_id, "Failed to write vg buffer cache %s\n.", vg->dss_ctrl->vg_info.vg_name);
}
shm_hash_ctrl_t *hash_ctrl = &vg->buffer_cache->hash_ctrl;
uint32 *dirs = (uint32 *)OFFSET_TO_ADDR(hash_ctrl->dirs);
ret = dss_write_shm_memory_file_inner(handle, &length, (char *)dirs, (int32)dir_size);
if (ret != CM_SUCCESS) {
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "Failed to write hashmap dir of vg %u\n.", i);
}
}
dss_write_block_pool(log_id, handle, &length, GA_8K_POOL);
dss_write_block_pool(log_id, handle, &length, GA_16K_POOL);
dss_write_block_pool(log_id, handle, &length, GA_FS_AUX_POOL);
dss_write_block_pool(log_id, handle, &length, GA_SEGMENT_POOL);
dss_update_shm_memory_length(log_id, handle, length, begin);
}
void dss_write_shm_memory(uint32 log_id)
{
dss_config_t *inst_cfg = dss_get_inst_cfg();
bool32 blackbox_detail_on = inst_cfg->params.blackbox_detail_on;
if (!blackbox_detail_on) {
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "_BLACKBOX_DETAIL_ON is FALSE, no need to print shm_memory.\n.");
return;
}
int32 handle = 0;
char timestamp[CM_MAX_NAME_LEN] = {0};
char file_name[CM_FILE_NAME_BUFFER_SIZE] = {0};
date_detail_t detail = g_timer()->detail;
errno_t errcode = snprintf_s(timestamp, CM_MAX_NAME_LEN, CM_MAX_NAME_LEN - 1, "%4u%02u%02u%02u%02u%02u%03u",
detail.year, detail.mon, detail.day, detail.hour, detail.min, detail.sec, detail.millisec);
if (SECUREC_UNLIKELY(errcode == -1)) {
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "print dss_shm_file failed.");
return;
}
if (log_id == LOG_BLACKBOX) {
errcode = snprintf_s(file_name, CM_FILE_NAME_BUFFER_SIZE, CM_FILE_NAME_BUFFER_SIZE - 1, "%s/%s/%s_%s",
cm_log_param_instance()->log_home, "blackbox", "dss_shm", timestamp);
} else {
errcode = snprintf_s(file_name, CM_FILE_NAME_BUFFER_SIZE, CM_FILE_NAME_BUFFER_SIZE - 1, "%s/%s/%s_%s",
cm_log_param_instance()->log_home, "dyn", "dss_shm", timestamp);
}
if (SECUREC_UNLIKELY(errcode == -1)) {
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "printf dss_shm_file failed.");
return;
}
if (cm_open_file_ex(file_name, O_SYNC | O_CREAT | O_RDWR | O_TRUNC | O_BINARY, S_IRUSR | S_IWUSR, &handle) !=
CM_SUCCESS) {
DSS_LOG_BLACKBOX_OR_DYNAMIC_INF(log_id, "open %s failed.", file_name);
return;
}
dss_write_share_vg_info(log_id, handle);
dss_write_hashmap_and_pool_info(log_id, handle);
cm_close_file(handle);
}
static void sig_print_excep_info(box_excp_item_t *excep_info, int32 sig_num, siginfo_t *siginfo, void *context)
{
cm_reset_error();
cm_proc_sig_get_header(excep_info, sig_num, siginfo, context);
char signal_name[CM_NAME_BUFFER_SIZE];
signal_name[0] = 0x00;
dss_get_signal_info(sig_num, signal_name, sizeof(signal_name) - 1);
int ret = strncpy_s(excep_info->sig_name, CM_NAME_BUFFER_SIZE, signal_name, strlen(signal_name));
securec_check_panic(ret);
cm_proc_get_register_info(&(excep_info->reg_info), (ucontext_t *)context);
cm_print_sig_info(excep_info, (void *)&(excep_info->reg_info));
cm_print_reg(&(excep_info->reg_info));
cm_print_assembly(&(excep_info->reg_info));
cm_print_call_link(&(excep_info->reg_info));
cm_save_proc_maps_file(excep_info);
cm_save_proc_meminfo_file();
LOG_BLACKBOX_INF("\n===============================threads backtrace===============================\n");
dss_sig_collect_all_backtrace(LOG_BLACKBOX);
dss_print_global_variable(LOG_BLACKBOX);
dss_print_effect_param(LOG_BLACKBOX);
dss_write_shm_memory(LOG_BLACKBOX);
}
uint32 g_sign_mutex = 0;
void dss_exit_proc(int32 exit_code)
{
while (CM_TRUE) {
CM_MFENCE;
if (g_sign_mutex == 0) {
_exit(exit_code);
}
cm_sleep(CM_SLEEP_500_FIXED);
}
_exit(exit_code);
}
void dss_proc_sign_func_core(int32 sig_num, siginfo_t *sig_info, void *context, bool32 *dump)
{
box_excp_item_t *excep_info = &g_excep_info;
uint64 loc_id = 0;
sigset_t sign_old_mask;
sigset_t sign_mask;
char signal_name[CM_NAME_BUFFER_SIZE] = {0};
char date[CM_MAX_TIME_STRLEN] = {0};
if (g_sign_mutex != 0) {
return;
}
g_sign_mutex = 1;
CM_MFENCE;
(void)sigprocmask(0, NULL, &sign_old_mask);
(void)sigfillset(&sign_mask);
(void)sigprocmask(SIG_SETMASK, &sign_mask, NULL);
if (!need_dump(sig_num)) {
loc_id = excep_info->loc_id;
dss_get_signal_info(sig_num, signal_name, sizeof(signal_name) - 1);
(void)cm_date2str(g_timer()->now, "yyyy-mm-dd hh24:mi:ss.ff3", date, CM_MAX_TIME_STRLEN);
LOG_BLACKBOX_INF("Location[0x%016llx] has been terminated, signum : %d, signal name : %s, current data : %s\n",
loc_id, sig_num, signal_name, date);
cm_fync_logfile();
g_sign_mutex = 0;
(void)sigprocmask(SIG_SETMASK, &sign_old_mask, NULL);
return;
}
status_t ret = dss_update_state_file(CM_TRUE);
if (ret != CM_SUCCESS) {
LOG_RUN_WAR("Failed to update core state file.");
cm_reset_error();
}
if (excep_info != NULL) {
sig_print_excep_info(excep_info, sig_num, sig_info, context);
}
cm_fync_logfile();
*dump = CM_TRUE;
}
void dss_proc_sign_func(int32 sig_num, siginfo_t *sig_info, void *context)
{
bool32 need_dump = CM_FALSE;
dss_proc_sign_func_core(sig_num, sig_info, context, &need_dump);
if (need_dump) {
(void)signal(SIGABRT, SIG_DFL);
abort();
}
}
status_t dss_update_state_file(bool32 coredump)
{
if (strlen(g_dss_state_file) == 0) {
PRTS_RETURN_IFERR(snprintf_s(g_dss_state_file, CM_FILE_NAME_BUFFER_SIZE, CM_FILE_NAME_BUFFER_SIZE - 1, "%s/%s",
g_inst_cfg->home, g_core_state_file));
}
if (!g_inst_cfg->params.enable_core_state_collect || !coredump) {
if (cm_file_exist(g_dss_state_file)) {
(void)cm_remove_file(g_dss_state_file);
}
return CM_SUCCESS;
}
FILE *fp;
CM_RETURN_IFERR(cm_fopen(g_dss_state_file, "w+", S_IRUSR | S_IWUSR, &fp));
int32 size = fprintf(fp, "%u", (uint32)coredump);
(void)fflush(stdout);
if (size < 0) {
LOG_DEBUG_ERR("write core state failed, write size is %d.", size);
(void)fclose(fp);
return CM_ERROR;
}
(void)fclose(fp);
return CM_SUCCESS;
}
static status_t dss_sigcap_reg_proc(int32 sig_num)
{
status_t ret = cm_regist_signal_restart(sig_num, dss_proc_sign_func);
if (ret != CM_SUCCESS) {
LOG_DEBUG_ERR("Register the signal cap failed:%d", sig_num);
return CM_ERROR;
}
LOG_DEBUG_INF("Register the signal cap success:%d", sig_num);
return CM_SUCCESS;
}
static status_t dss_sig_reg_backtrace()
{
status_t ret = cm_regist_signal_restart(SIG_BACKTRACE, cm_sig_backtrace_func);
if (ret != CM_SUCCESS) {
LOG_DEBUG_ERR("Register the signal backtrace failed");
return CM_ERROR;
}
LOG_DEBUG_INF("Register the signal backtrace success");
return CM_SUCCESS;
}
static status_t dss_proc_sign_init()
{
if (cm_proc_sign_init(&g_excep_info) != CM_SUCCESS) {
return CM_ERROR;
}
cm_proc_sig_get_fixed_header(&g_excep_info);
char *version = (char *)DEF_DSS_VERSION;
errno_t errcode = strncpy_s(g_excep_info.version, BOX_VERSION_LEN, version, strlen(version));
if (errcode != EOK) {
CM_THROW_ERROR(ERR_SYSTEM_CALL, errcode);
return CM_ERROR;
}
return CM_SUCCESS;
}
#define SIG_HOTPATCH (37)
status_t dss_sigcap_handle_reg()
{
cm_init_backtrace_handle();
if (dss_proc_sign_init() != CM_SUCCESS) {
return CM_ERROR;
}
for (uint32 sig_num = 0; sig_num < ARRAY_NUM(g_sign_array); sig_num++) {
if (dss_sigcap_reg_proc(g_sign_array[sig_num]) != CM_SUCCESS) {
return CM_ERROR;
}
}
for (uint32 sig_num = SIGRTMIN; sig_num <= SIGRTMAX; sig_num++) {
if (sig_num == SIG_BACKTRACE || sig_num == SIG_HOTPATCH || sig_num == SIG_DYN_LOG) {
continue;
}
if (dss_sigcap_reg_proc(sig_num) != CM_SUCCESS) {
return CM_ERROR;
}
}
return dss_sig_reg_backtrace();
}
#ifdef __cplusplus
}
#endif
#endif