diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c index 3668d16161078388009a95ad98c9a82778f366e5..977fc66418cb48583dd16fa3fc82535a8c8abeb8 100644 --- a/src/backend/utils/error/elog.c +++ b/src/backend/utils/error/elog.c @@ -410,6 +410,7 @@ errfinish(int dummy,...) { ErrorData *edata = &errordata[errordata_stack_depth]; int elevel; + bool save_ImmediateInterruptOK; MemoryContext oldcontext; ErrorContextCallback *econtext; @@ -417,6 +418,18 @@ errfinish(int dummy,...) CHECK_STACK_DEPTH(); elevel = edata->elevel; + /* + * Ensure we can't get interrupted while performing error reporting. This + * is needed to prevent recursive entry to functions like syslog(), which + * may not be re-entrant. + * + * Note: other places that save-and-clear ImmediateInterruptOK also do + * HOLD_INTERRUPTS(), but that should not be necessary here since we + * don't call anything that could turn on ImmediateInterruptOK. + */ + save_ImmediateInterruptOK = ImmediateInterruptOK; + ImmediateInterruptOK = false; + /* * Do processing in ErrorContext, which we hope has enough reserved space * to report an error. @@ -442,17 +455,16 @@ errfinish(int dummy,...) /* * We do some minimal cleanup before longjmp'ing so that handlers can * execute in a reasonably sane state. - */ - - /* This is just in case the error came while waiting for input */ - ImmediateInterruptOK = false; - - /* + * * Reset InterruptHoldoffCount in case we ereport'd from inside an * interrupt holdoff section. (We assume here that no handler will * itself be inside a holdoff section. If necessary, such a handler * could save and restore InterruptHoldoffCount for itself, but this * should make life easier for most.) + * + * Note that we intentionally don't restore ImmediateInterruptOK here, + * even if it was set at entry. We definitely don't want that on + * while doing error cleanup. */ InterruptHoldoffCount = 0; @@ -519,10 +531,7 @@ errfinish(int dummy,...) { /* * For a FATAL error, we let proc_exit clean up and exit. - */ - ImmediateInterruptOK = false; - - /* + * * If we just reported a startup failure, the client will disconnect * on receiving it, so don't send any more to the client. */ @@ -555,15 +564,18 @@ errfinish(int dummy,...) * XXX: what if we are *in* the postmaster? abort() won't kill our * children... */ - ImmediateInterruptOK = false; fflush(stdout); fflush(stderr); abort(); } /* - * We reach here if elevel <= WARNING. OK to return to caller. - * + * We reach here if elevel <= WARNING. OK to return to caller, so restore + * caller's setting of ImmediateInterruptOK. + */ + ImmediateInterruptOK = save_ImmediateInterruptOK; + + /* * But check for cancel/die interrupt first --- this is so that the user * can stop a query emitting tons of notice or warning messages, even if * it's in a loop that otherwise fails to check for interrupts.