diff --git a/src/common/backend/utils/errcodes.txt b/src/common/backend/utils/errcodes.txt index c03fa708..bd2840a9 100644 --- a/src/common/backend/utils/errcodes.txt +++ b/src/common/backend/utils/errcodes.txt @@ -609,3 +609,8 @@ LL002 E ERRCODE_RELFILENODEMAP rel Section: Class TS - Timeseries Error TS000 E ERRCODE_TS_COMMON_ERROR timeseries_common_error TS001 E ERRCODE_TS_KEYTYPE_MISMATCH column_key_type_mismatch + +Section: Class UE - Uncorrected Error & Warning +UE000 E ERRCODE_UE_COMMON_ERROR uce_common_error +UE001 E ERRCODE_UE_DIRTY_PAGE uce_dirty_page_error +UE002 E ERRCODE_UE_CLEAN_PAGE uce_clean_page_error \ No newline at end of file diff --git a/src/gausskernel/cbb/bbox/gs_bbox.cpp b/src/gausskernel/cbb/bbox/gs_bbox.cpp index 905f9490..07cec0bd 100644 --- a/src/gausskernel/cbb/bbox/gs_bbox.cpp +++ b/src/gausskernel/cbb/bbox/gs_bbox.cpp @@ -69,6 +69,11 @@ static void coredump_handler(int sig, siginfo_t *si, void *uc) if (g_instance.attr.attr_common.enable_ffic_log) { (void)gen_err_msg(sig, si, (ucontext_t *)uc); } + if (sig == SIGBUS) { + g_instance.sigbus_cxt.sigbus_addr = si->si_addr; + g_instance.sigbus_cxt.sigbus_code = si->si_code; + SIGBUS_handler(sig); + } } else { /* * Subsequent fatal error will go to here. If it comes from different thread, @@ -97,7 +102,11 @@ static void bbox_handler(int sig, siginfo_t *si, void *uc) if (g_instance.attr.attr_common.enable_ffic_log) { (void)gen_err_msg(sig, si, (ucontext_t *)uc); } - + if (sig == SIGBUS) { + g_instance.sigbus_cxt.sigbus_addr = si->si_addr; + g_instance.sigbus_cxt.sigbus_code = si->si_code; + SIGBUS_handler(sig); + } #ifndef ENABLE_MEMORY_CHECK sigset_t intMask; sigset_t oldMask; diff --git a/src/gausskernel/process/postmaster/postmaster.cpp b/src/gausskernel/process/postmaster/postmaster.cpp index 6c694ed5..721629ad 100755 --- a/src/gausskernel/process/postmaster/postmaster.cpp +++ b/src/gausskernel/process/postmaster/postmaster.cpp @@ -263,7 +263,8 @@ static bool isNeedGetLCName = true; #define PM_POLL_TIMEOUT_SECOND 20 #define PM_POLL_TIMEOUT_MINUTE 58*SECS_PER_MINUTE*60*1000000L #define CHECK_TIMES 10 - +#define SIGBUS_MCEERR_AR 4 +#define SIGBUS_MCEERR_AO 5 static char gaussdb_state_file[MAXPGPATH] = {0}; uint32 noProcLogicTid = 0; @@ -333,6 +334,7 @@ static Port* ConnCreateToRecvGssock(pollfd* ufds, int idx, int* nSockets); static Port* ConnCreate(int serverFd); static void reset_shared(int port); static void SIGHUP_handler(SIGNAL_ARGS); +void SIGBUS_handler(SIGNAL_ARGS); static void pmdie(SIGNAL_ARGS); static void startup_alarm(SIGNAL_ARGS); static void SetWalsndsNodeState(ClusterNodeState requester, ClusterNodeState others); @@ -4245,6 +4247,65 @@ static void SIGHUP_handler(SIGNAL_ARGS) errno = save_errno; } +/* + * SIGBUS -- When uce failure occurs in system memory, sigbus_handler will exit according to the region + of its logical address. + 1. Calculate the buffer pool address range to determine whether the error address is in the buffer pool. + 2. For addresses outside the buffer pool range, print the NIC log and exit + 3. For addresses within the buffer pool range, calculate block_id and judge whether the page is dirty + 4. If the page is not dirty, execute pmdie to exit normally and print warning message. If the page is dirty, + print the PANIC log and exit + */ +void SIGBUS_handler(SIGNAL_ARGS) +{ + uint64 buffer_size; + int buf_id; + int si_code = g_instance.sigbus_cxt.sigbus_code; + unsigned long long sigbus_addr = (unsigned long long)g_instance.sigbus_cxt.sigbus_addr; + if (si_code != SIGBUS_MCEERR_AR && si_code != SIGBUS_MCEERR_AO) { + ereport(PANIC, + (errcode(ERRCODE_UE_COMMON_ERROR), + errmsg("errcode:%u, SIGBUS signal received, Gaussdb will shut down immediately", + ERRCODE_UE_COMMON_ERROR))); + } +#ifdef __aarch64__ + buffer_size = g_instance.attr.attr_storage.NBuffers * (Size)BLCKSZ + PG_CACHE_LINE_SIZE; +#else + buffer_size = g_instance.attr.attr_storage.NBuffers * (Size)BLCKSZ; +#endif + unsigned long long startaddr = (unsigned long long)t_thrd.storage_cxt.BufferBlocks; + unsigned long long endaddr = startaddr + buffer_size; + /* Determine the range of address carried by sigbus, And print the log according to the page state. */ + if (sigbus_addr >= startaddr && sigbus_addr <= endaddr) { + buf_id = floor((sigbus_addr - startaddr) / (Size)BLCKSZ); + BufferDesc* buf_desc = GetBufferDescriptor(buf_id); + if (buf_desc->state & BM_DIRTY || buf_desc->state & BM_JUST_DIRTIED || buf_desc->state & BM_CHECKPOINT_NEEDED || + buf_desc->state & BM_IO_IN_PROGRESS) { + ereport(PANIC, + (errcode(ERRCODE_UE_DIRTY_PAGE), + errmsg("errcode:%u, Uncorrected Error occurred at dirty page. The error address is: 0x%llx. Gaussdb will shut " + "down immediately.", + ERRCODE_UE_DIRTY_PAGE, sigbus_addr))); + } else { + ereport(WARNING, + (errcode(ERRCODE_UE_CLEAN_PAGE), + errmsg("errcode:%u, Uncorrected Error occurred at clean/free page. The error address is: 0x%llx. GaussDB will " + "shutdown.", + ERRCODE_UE_CLEAN_PAGE, sigbus_addr))); + pmdie(SIGBUS); + } + } else if (sigbus_addr == 0) { + ereport(PANIC, + (errcode(ERRCODE_UE_COMMON_ERROR), + errmsg("errcode:%u, SIGBUS signal received, sigbus_addr is None. Gaussdb will shut down immediately", + ERRCODE_UE_COMMON_ERROR))); + } else { + ereport(PANIC, + (errcode(ERRCODE_UE_COMMON_ERROR), + errmsg("errcode:%u, SIGBUS signal received. The error address is: 0x%llx, Gaussdb will shut down immediately", + ERRCODE_UE_COMMON_ERROR, sigbus_addr))); + } +} void KillGraceThreads(void) { @@ -4285,6 +4346,7 @@ static void pmdie(SIGNAL_ARGS) switch (postgres_signal_arg) { case SIGTERM: case SIGINT: + case SIGBUS: if (STANDBY_MODE == t_thrd.postmaster_cxt.HaShmData->current_mode && !dummyStandbyMode && SIGTERM == postgres_signal_arg) { diff --git a/src/include/knl/knl_instance.h b/src/include/knl/knl_instance.h index 3b7d9a35..fd6722ac 100644 --- a/src/include/knl/knl_instance.h +++ b/src/include/knl/knl_instance.h @@ -764,6 +764,11 @@ typedef struct knl_g_hypo_context { List* hypo_index_list; } knl_g_hypo_context; +typedef struct knl_sigbus_context { + void* sigbus_addr; + int sigbus_code; +} knl_sigbus_context; + typedef struct knl_instance_context { knl_virtual_role role; volatile int status; @@ -861,6 +866,7 @@ typedef struct knl_instance_context { knl_g_archive_standby_context archive_standby_cxt; struct HTAB* ngroup_hash_table; knl_g_hypo_context hypo_cxt; + knl_sigbus_context sigbus_cxt; } knl_instance_context; extern long random(); diff --git a/src/include/postmaster/postmaster.h b/src/include/postmaster/postmaster.h index 8170931b..39977f02 100644 --- a/src/include/postmaster/postmaster.h +++ b/src/include/postmaster/postmaster.h @@ -244,4 +244,5 @@ extern uint64_t mc_timers_us(void); extern bool SetDBStateFileState(DbState state, bool optional); extern void GPCResetAll(); extern void initRandomState(TimestampTz start_time, TimestampTz stop_time); +extern void SIGBUS_handler(SIGNAL_ARGS); #endif /* _POSTMASTER_H */