Re: more signals (was: Function to kill backend)

From: "Magnus Hagander" <mha(at)sollentuna(dot)net>
To: "Tom Lane" <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: "Bruce Momjian" <pgman(at)candle(dot)pha(dot)pa(dot)us>, <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: more signals (was: Function to kill backend)
Date: 2004-07-29 09:24:33
Message-ID: 6BCB9D8A16AC4241919521715F4D8BCE4569B5@algol.sollentuna.se
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers


> >> So what you'd basically need is a separate signal to trigger that
> >> sort of exit, which would be easy ... if we had any spare
> signal numbers.
>
> > What about multiplexing it onto an existing signal? e.g. set a
> > shared-mem flag saying "exit after cancel" then send SIGINT?
>
> Possible, but then the *only* way to get the behavior is by
> using the backend function --- you couldn't use dear old
> kill(1) to do it manually. It'd be better if it mapped to a signal.

Okay, how is this for a proposed way of fixing this. Because as I see
it, the problem is that there just aren't enough signals to go around.

We invent something we could call "extended signals" that are valid only
in pgsql. To do this, we steal one signal (durign the argument, let's
say SIGUSR2 - can be another one, but that one seems like as good a
choice as any).
On top of this, we create a SystemV message queue used to pass down
extended signals (should be supported on all systems that support sysv
shared mem, and we require that..). We'd use the PID of the receiving
backend as the message type, and pass the signal number as message
contents.

Now, in pqsignal() we change it into something along the line of:

pqsignal() {
if (signal > 256 || signal == SIGUSR2) {
set_extended_signal_handler();
}
else {
set_normal_signal_handler();
}
}

and we create a sigusr2 handler like such:
sigusr2handler() {
while (read_signal_number_from_ipc()) {
dispatch_extended_signal_handler();
}
}

and then we'd need to change the kill calls into being
pqkill() {
if (signal > 256 || signal==SIGUSR2) {
send_signal_number_down_ipc_to_correct_backend();
native_kill(backend, SIGUSR2);
}
}

I'm assuming that a normal signal number is never > 256. I'm not sure
how safe that is, then we could just change the limit to something else
(say 65536?)

Doing it this way would mean that the actuall code using pqsignal()
would never have to change - it wouldn't know if the signal was "normal"
or "extended". And we could add thousands of signals if we ever wanted
(ok, let's keep it real, but I'm assuming int he future we might want >1
at least).

In this case, we would add XSIG_TERMONIDLE or something like that, which
would tell the backend to exist as soon as it hits idle state. And the
pg_term_backend() function could send a cancel-request followed by a
termonindle-request to have the backnend abort the current
statement/transaction and then exit.

To the user it would be exposed using "pg_ctl kill" (that we already
have). Which can of course also send normal signals. So we'd say
"*never* use kill -<antyhing> on a pg backend, always use 'pg_kill
kill', oh, and never -9 anything".

This is more or less how it's done on win32 today (only there we do it
for all signals - and this can and shuold definitly not be used to
change the behaviour of things like SIGTERM that you'd normally see
happen in a unix environment, that would just be dangerous). The current
win32 implementatino could just be extended to send a int32 instead of a
byte across the IPC channel already established.

Does this sound like a reasonable way to extend the available signals?
Or is it adding unnecessary stuff?
And finally, if this sounds like a decent idea, is it too big to slip in
as a bugfix for the term_backend() stuff into 7.5?

//Magnus

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Mark Kirkwood 2004-07-29 09:34:14 Re: Point in Time Recovery
Previous Message Magnus Hagander 2004-07-29 08:48:41 Re: 7.5 devel initdb failure