Michael Paquier <mich...@paquier.xyz> writes: > Indeed, this was incorrect. And you may not have noticed, but we have > a second instance of that in LogicalIncreaseRestartDecodingForSlot() > that goes down to 9.4 and b89e151. I used a dirty-still-efficient > hack to detect that, and that's the only instance I have spotted.
Ugh, that is just horrid. I experimented with the attached patch but it did not find any other problems. Still, that only proves something about code paths that are taken during check-world, and we know that our test coverage is not very good :-(. Should we think about adding automated detection of this type of mistake? I don't like the attached as-is because of the #include footprint expansion, but maybe we can find a better way. > I am not sure if that's worth worrying a back-patch, but we should > really address that at least on HEAD. It's actually worse in the back branches, because elog() did not have a good short-circuit path like ereport() does. +1 for back-patch. regards, tom lane
diff --git a/src/backend/storage/lmgr/spin.c b/src/backend/storage/lmgr/spin.c index 4d2a4c6641..f95f83d039 100644 --- a/src/backend/storage/lmgr/spin.c +++ b/src/backend/storage/lmgr/spin.c @@ -27,6 +27,8 @@ #include "storage/spin.h" +volatile slock_t *held_spinlock = NULL; + #ifndef HAVE_SPINLOCKS PGSemaphore *SpinlockSemaArray; #endif diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index 14fa127ab1..247d9a8089 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -28,6 +28,10 @@ #include "datatype/timestamp.h" /* for TimestampTz */ #include "pgtime.h" /* for pg_time_t */ +#ifndef FRONTEND +#include "storage/spin.h" +#endif + #define InvalidPid (-1) @@ -98,6 +102,7 @@ extern void ProcessInterrupts(void); #define CHECK_FOR_INTERRUPTS() \ do { \ + NotHoldingSpinLock(); \ if (InterruptPending) \ ProcessInterrupts(); \ } while(0) @@ -105,6 +110,7 @@ do { \ #define CHECK_FOR_INTERRUPTS() \ do { \ + NotHoldingSpinLock(); \ if (UNBLOCKED_SIGNAL_QUEUE()) \ pgwin32_dispatch_queued_signals(); \ if (InterruptPending) \ @@ -113,7 +119,11 @@ do { \ #endif /* WIN32 */ -#define HOLD_INTERRUPTS() (InterruptHoldoffCount++) +#define HOLD_INTERRUPTS() \ +do { \ + NotHoldingSpinLock(); \ + InterruptHoldoffCount++; \ +} while(0) #define RESUME_INTERRUPTS() \ do { \ diff --git a/src/include/storage/spin.h b/src/include/storage/spin.h index 5ad25d0f6f..6d806620a1 100644 --- a/src/include/storage/spin.h +++ b/src/include/storage/spin.h @@ -56,12 +56,26 @@ #include "storage/pg_sema.h" #endif +extern volatile slock_t *held_spinlock; + +#define NotHoldingSpinLock() \ + Assert(held_spinlock == NULL) #define SpinLockInit(lock) S_INIT_LOCK(lock) -#define SpinLockAcquire(lock) S_LOCK(lock) +#define SpinLockAcquire(lock) \ + do { \ + Assert(held_spinlock == NULL); \ + S_LOCK(lock); \ + held_spinlock = (lock); \ + } while (0) -#define SpinLockRelease(lock) S_UNLOCK(lock) +#define SpinLockRelease(lock) \ + do { \ + Assert(held_spinlock == (lock)); \ + S_UNLOCK(lock); \ + held_spinlock = NULL; \ + } while (0) #define SpinLockFree(lock) S_LOCK_FREE(lock) diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h index 1e09ee0541..902996fed4 100644 --- a/src/include/utils/elog.h +++ b/src/include/utils/elog.h @@ -16,6 +16,10 @@ #include <setjmp.h> +#ifndef FRONTEND +#include "storage/spin.h" +#endif + /* Error level codes */ #define DEBUG5 10 /* Debugging messages, in categories of * decreasing detail. */ @@ -124,6 +128,7 @@ #define ereport_domain(elevel, domain, ...) \ do { \ pg_prevent_errno_in_scope(); \ + NotHoldingSpinLock(); \ if (errstart(elevel, domain)) \ __VA_ARGS__, errfinish(__FILE__, __LINE__, PG_FUNCNAME_MACRO); \ if (__builtin_constant_p(elevel) && (elevel) >= ERROR) \ @@ -134,6 +139,7 @@ do { \ const int elevel_ = (elevel); \ pg_prevent_errno_in_scope(); \ + NotHoldingSpinLock(); \ if (errstart(elevel_, domain)) \ __VA_ARGS__, errfinish(__FILE__, __LINE__, PG_FUNCNAME_MACRO); \ if (elevel_ >= ERROR) \