Example #1
0
/*
 * Checks if RedZoneHandler_IsVmemRedZone() properly identifies red zone
 */
void
test__RedZoneHandler_IsVmemRedZone__ProperlyIdentifiesRedZone(void **state)
{
	vmemTrackerInited = false;

	/* No red zone detection if vmem tracker is not initialized */
	assert_false(RedZoneHandler_IsVmemRedZone());

	vmemTrackerInited = true;

	static int32 fakeSegmentVmemChunks = 0;
	segmentVmemChunks = &fakeSegmentVmemChunks;

	redZoneChunks = INT32_MAX;
	*segmentVmemChunks = INT32_MAX;
	/* Both segment vmem and red zone is INT32_MAX. It's not a red-zone */
	assert_false(RedZoneHandler_IsVmemRedZone());

	/* 100 chunks */
	*segmentVmemChunks = 100;
	redZoneChunks = 80;
	/* segmentVmemChunks exceeds redZoneChunks. So, should be red zone */
	assert_true(RedZoneHandler_IsVmemRedZone());

	vmemTrackerInited = false;
	/*
	 * segmentVmemChunks exceeds redZoneChunks. But vmem tracker is not
	 * initialized. Therefore, no red zone detection
	 */
	assert_false(RedZoneHandler_IsVmemRedZone());
}
Example #2
0
/*
 * In a red-zone this method identifies the top vmem consuming session,
 * and requests it to cleanup. If the red-zone handler determines itself
 * as the runaway session, it also starts the cleanup.
 */
void
RedZoneHandler_DetectRunawaySession()
{
	/*
	 * InterruptHoldoffCount > 0 indicates we are in a sensitive code path that doesn't
	 * like a control flow disruption as may happen from a pending die/cancel interrupt.
	 * As we may eventually ERROR out from this method (during RunawayCleaner_StartCleanup)
	 * we want to make sure that HOLD_INTERRUPTS() was not called (i.e., InterruptHoldoffCount == 0).
	 *
	 * What happens if we don't check for InterruptHoldoffCount? One example is LWLockAcquire()
	 * which calls HOLD_INTERRUPTS() to ensure that no unexpected control
	 * flow disruption happens because of FATAL/ERROR as done from die/cancel interrupt
	 * handler. If we ignore InterruptHoldoffCount, the PGSemaphoreLock() (called from LWLockAcquire)
	 * would call CHECK_FOR_INTERRUPTS() and we may throw ERROR if the current session is a runaway.
	 * Unfortunately, LWLockAcquire shares the semaphore with the regular lock manager and
	 * ProcWaitForSignal. Therefore, LWLockAcquire may wake up multiple times during its wait
	 * for a semaphore which may not relate to an actual LWLock release. This requires LWLockAcquire
	 * to keep track of how many of those false wake events it has consumed (by decrementing semaphore
	 * when it shouldn't have done so) and LWLockAcquire rollback the semaphore decrements for
	 * the irrelevant wake up events by re-incrementing once it actually acquires the lock.
	 * Therefore, an unexpected control flow out of the LWLockAcquire before it properly rolled back
	 * may prevent the LWLockAcquire to rollback the false wake events. Although we do call LWLockRelease
	 * during an error handling, that doesn't guarantee that the falsely consumed semaphore wake
	 * events would be rolled back (i.e., semaphore does not get re-incremented during error handling) as
	 * done at the end of LWLockAcquire. This may cause the semaphore to never wake up other waiting
	 * processes and therefore may cause other processes to hang perpetually.
	 */
	if (!RedZoneHandler_IsVmemRedZone() || InterruptHoldoffCount > 0 ||
			CritSectionCount > 0)
	{
		return;
	}

	/* We don't support runaway detection/termination from non-owner thread */
	Assert(MemoryProtection_IsOwnerThread());
	Assert(gp_mp_inited);

	RedZoneHandler_FlagTopConsumer();
	RunawayCleaner_StartCleanup();
}