On 19/02/2026 11:25, Heikki Linnakangas wrote:
On 19/02/2026 09:21, Kirill Reshke wrote:
On Thu, 19 Feb 2026 at 02:50, Andres Freund <[email protected]> wrote:
I don't think die() should call ereport() without being in single
user mode. I
guess there's a corner case though, which is that the signal handler is
executed during exit processing, when we already reset
whereToSendOutput. I
think we probably should make sure this stuff is only reached in
actual single
user mode.
+1
Attached is a quick patch for that.
At first I considered replacing the "if (DoingCommandRead &&
whereToSendOutput != DestRemote)" check with "if (DoingCommandRead &&
whereToSendOutput == DestDebug)". That would be the minimal change to
fix the confusion when a regular backend is exiting. But I think it's
better to make this exception as narrow as possible in general. We only
need the exit from the signal handler while we're in the middle of the
uninterruptible getc(), not for any longer.
So that is pretty well-defined, and we could use poll() on stdin too.
That said, WaitLatchOrSocket() et al. currently assume that the fd is a
socket rather than a pipe or a file. It might work the same on most
platforms, but I wonder about Windows. So it could be done, but it might
require changes to waiteventset.c, which might not be worth the trouble
just for single-user mode.
Hmm, how do we do this for pipes in COPY? If waiteventset supported
pipes, would it be useful for COPY too ?
- Heikki
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 21de158adbb..c10667d32e5 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -137,6 +137,11 @@ static bool xact_started = false;
*/
static bool DoingCommandRead = false;
+/*
+ * Flag to indicate that we're reading from stdin, in single-user mode.
+ */
+static bool DoingInteractiveRead = false;
+
/*
* Flags to implement skip-till-Sync-after-error behavior for messages of
* the extended query protocol.
@@ -333,7 +338,9 @@ interactive_getc(void)
*/
CHECK_FOR_INTERRUPTS();
+ DoingInteractiveRead = true;
c = getc(stdin);
+ DoingInteractiveRead = false;
ProcessClientReadInterrupt(false);
@@ -3029,7 +3036,7 @@ die(SIGNAL_ARGS)
* Rather ugly, but it's unlikely to be worthwhile to invest much more
* effort just for the benefit of single user mode.
*/
- if (DoingCommandRead && whereToSendOutput != DestRemote)
+ if (DoingInteractiveRead)
ProcessInterrupts();
}