Re: Interrupts vs signals

From: Heikki Linnakangas <hlinnaka(at)iki(dot)fi>
To: Thomas Munro <thomas(dot)munro(at)gmail(dot)com>
Cc: pgsql-hackers <pgsql-hackers(at)postgresql(dot)org>, Andres Freund <andres(at)anarazel(dot)de>, Robert Haas <robertmhaas(at)gmail(dot)com>
Subject: Re: Interrupts vs signals
Date: 2024-08-07 14:59:23
Message-ID: 46f047a1-bfd5-406a-a0f3-97205d9529ad@iki.fi
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On 10/07/2024 09:48, Thomas Munro wrote:
> The next problems to remove are, I think, the various SIGUSR2, SIGINT,
> SIGTERM signals sent by the postmaster. These should clearly become
> SendInterrupt() or ProcSetLatch(). The problem here is that the
> postmaster doesn't have the proc numbers yet. One idea is to teach
> the postmaster to assign them! Not explored yet.

With my latest patches on the "Refactoring postmaster's code to cleanup
after child exit" thread [1], every postmaster child process is assigned
a slot in the pmsignal.c array, including all the aux processes. If we
moved 'pending_interrupts' and the process Latch to the pmsignal.c
array, then you could send an interrupt also to a process that doesn't
have a PGPROC entry. That includes dead-end backends, backends that are
still in authentication, and the syslogger.

That would also make it so that the postmaster would never need to poke
into the procarray. pmsignal.c is already designated as the limited
piece of shared memory that is accessed by the postmaster
(BackgroundWorkerSlots is the other exception), so it would be kind of
nice if all the information that the postmaster needs to send an
interrupt was there. That would mean that where you currently use a
ProcNumber to identify a process, you'd use an index into the
PMSignalState array instead.

I don't insist on changing that right now, I think this patch is OK as
it is, but that might be a good next step later.

[1]
https://www.postgresql.org/message-id/8f2118b9-79e3-4af7-b2c9-bd5818193ca4%40iki.fi

I'm also wondering about the relationship between interrupts and
latches. Currently, SendInterrupt sets a latch to wake up the target
process. I wonder if it should be the other way 'round? Move all the
wakeup code, with the signalfd, the self-pipe etc to interrupt.c, and in
SetLatch, call SendInterrupt to wake up the target process? Somehow that
feels more natural to me, I think.

> This version is passing on Windows. I'll create a CF entry. Still
> work in progress!

Some comments on the patch details:

> ereport(WARNING,
> (errmsg("NOTIFY queue is %.0f%% full", fillDegree * 100),
> - (minPid != InvalidPid ?
> - errdetail("The server process with PID %d is among those with
the oldest transactions.", minPid)
> + (minPgprocno != INVALID_PROC_NUMBER ?
> + errdetail("The server process with pgprocno %d is among those
with the oldest transactions.", minPgprocno)
> : 0),
> - (minPid != InvalidPid ?
> + (minPgprocno != INVALID_PROC_NUMBER ?
> errhint("The NOTIFY queue cannot be emptied until that process
ends its current transaction.")
> : 0)));

This makes the message less useful to the user, as the ProcNumber isn't
exposed to users. With the PID, you can do "pg_terminate_backend(pid)"

> diff --git a/src/backend/optimizer/util/pathnode.c
b/src/backend/optimizer/util/pathnode.c
> index c42742d2c7b..bfb89049020 100644
> --- a/src/backend/optimizer/util/pathnode.c
> +++ b/src/backend/optimizer/util/pathnode.c
> @@ -18,6 +18,7 @@
>
> #include "foreign/fdwapi.h"
> #include "miscadmin.h"
> +#include "postmaster/interrupt.h"
> #include "nodes/extensible.h"
> #include "optimizer/appendinfo.h"
> #include "optimizer/clauses.h"

misordered

> + * duplicated interrupts later if we switch backx.

typo: backx -> back

> - if (IdleInTransactionSessionTimeoutPending)
> + if (ConsumeInterrupt(INTERRUPT_IDLE_TRANSACTION_TIMEOUT))
> {
> /*
> * If the GUC has been reset to zero, ignore the signal. This is
> @@ -3412,7 +3361,6 @@ ProcessInterrupts(void)
> * interrupt. We need to unset the flag before the injection point,
> * otherwise we could loop in interrupts checking.
> */
> - IdleInTransactionSessionTimeoutPending = false;
> if (IdleInTransactionSessionTimeout > 0)
> {
> INJECTION_POINT("idle-in-transaction-session-timeout");

The "We need to unset the flag.." comment is a bit out of place now,
since the flag was already cleared by ConsumeInterrupt(). Same in the
INTERRUPT_TRANSACTION_TIMEOUT and INTERRUPT_IDLE_SESSION_TIMEOUT
handling after this.

--
Heikki Linnakangas
Neon (https://neon.tech)

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Aleksander Alekseev 2024-08-07 15:00:45 Re: Fsync (flush) all inserted WAL records
Previous Message Peter Geoghegan 2024-08-07 14:59:11 Re: Optimizing nbtree ScalarArrayOp execution, allowing multi-column ordered scans, skip scan