/* * Check if time slice since last check-for-interrupts (CFI) has been exceeded */ void TimeSliceCheck(const char *file, int line) { Assert(gp_test_time_slice); Assert(IsValidReportLevel(gp_test_time_slice_report_level)); struct rusage ru; int32 elapsedMs = 0; /* CFI is disabled inside critical sections */ if (0 != InterruptHoldoffCount || 0 != CritSectionCount) { return; } /* get current user time */ if (getrusage(RUSAGE_SELF, &ru) != 0) { elog(ERROR, "Time slicer: Failed to retrieve user time"); } elapsedMs = timeElapsedMs(&ru.ru_utime, &userTimeLastCFI); Assert(0 <= elapsedMs); /* check elapsed time since last CFI */ if (gp_test_time_slice_interval < elapsedMs) { void *stackAddressesCurrent[MAX_FRAME_DEPTH]; uint32 stackDepthCurrent = gp_backtrace(stackAddressesCurrent, MAX_FRAME_DEPTH); char *stackTraceLastCFI = gp_stacktrace(stackAddressesLastCFI, stackDepthLastCFI); char *stackTraceCurrent = gp_stacktrace(stackAddressesCurrent, stackDepthCurrent); /* report time slice violation error */ ereport(gp_test_time_slice_report_level, (errmsg("Time slice of %d ms exceeded at (%s:%d), last CFI before %d ms.\n" "Stack trace of last CFI:\n%s\n" "Current stack trace:\n%s\n", gp_test_time_slice_interval, file, line, elapsedMs, stackTraceLastCFI, stackTraceCurrent))); } /* reset time slice */ userTimeLastCFI = ru.ru_utime; stackDepthLastCFI = gp_backtrace(stackAddressesLastCFI, MAX_FRAME_DEPTH); }
/* * check if lightweight lock(s) are held; * print stack trace where lock(s) got acquired and error out; */ void LWLockHeldDetect(const void *pv, int lockmode) { Assert(gp_test_deadlock_hazard); Assert(IsValidReportLevel(gp_test_deadlock_hazard_report_level)); const LOCKTAG *locktag = (const LOCKTAG *) pv; if (0 < LWLocksHeld()) { void *stackAddressesCurrent[MAX_FRAME_DEPTH]; uint32 stackDepthCurrent = gp_backtrace(stackAddressesCurrent, MAX_FRAME_DEPTH); char *stackTraceCurrent = gp_stacktrace(stackAddressesCurrent, stackDepthCurrent); const char *stackTraces = LWLocksHeldStackTraces(); Assert(NULL != stackTraces); /* report time slice violation error */ ereport(gp_test_deadlock_hazard_report_level, (errmsg("Attempting to acquire database lock (%s:%d:%d:%d:%d) while holding lightweight lock (%d:%p).\n" "Stack trace(s) where lightweight lock(s) got acquired:\n%s\n" "Current stack trace:\n%s\n", GetLockmodeName(locktag->locktag_lockmethodid, lockmode), locktag->locktag_field1, locktag->locktag_field2, locktag->locktag_field3, locktag->locktag_field4, LWLockHeldLatestId(), LWLockHeldLatestCaller(), stackTraces, stackTraceCurrent))); } }
/* * Build string containing stack traces where all exclusively-held * locks were acquired; */ const char* LWLocksHeldStackTraces() { if (num_held_lwlocks == 0) { return NULL; } StringInfo append = makeStringInfo(); /* palloc'd */ uint32 i = 0, cnt = 1; /* append stack trace for each held lock */ for (i = 0; i < num_held_lwlocks; i++) { if (!LWLOCK_IS_PREDEFINED(held_lwlocks[i])) { continue; } appendStringInfo(append, "%d: LWLock %d:\n", cnt++, held_lwlocks[i] ); char *stackTrace = gp_stacktrace(held_lwlocks_addresses[i], held_lwlocks_depth[i]); Assert(stackTrace != NULL); appendStringInfoString(append, stackTrace); pfree(stackTrace); } Assert(append->len > 0); return append->data; }