In MacOS, psql reacts on SIGINT in a strange fashion (Linux is fine)

From: Dmitry Koterov <dmitry(dot)koterov(at)gmail(dot)com>
To: "pgsql-hackers(at)postgresql(dot)org" <pgsql-hackers(at)postgresql(dot)org>
Subject: In MacOS, psql reacts on SIGINT in a strange fashion (Linux is fine)
Date: 2024-04-13 08:21:21
Message-ID: CA+CZih49+SuZi-ykCc53ondJeNe6ATQrd18KvGOt5KUW=Py2QQ@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi.

Preamble: this happens in MacOS only (in built-in Terminal and in iTerm2 at
least). In Linux, everything is as expected.

I almost lost my mind today trying to figure out why sending a SIGINT
precisely to a psql interactive process delivers this SIGINT not only to
that psql, but also to its parents.

Notice that it is NOT about Ctrl-C at all (which would've been delivered to
the whole process group; but again, it's not about it, there is no Ctrl-C;
I even used pliers to remove "Ctrl" and "C" keys from my keyboard). It is
about a plain old "kill -SIGINT psql_pid" executed manually in a separate
shell.

I tried to find a place in psql source code where it fans out SIGINT to its
parent pids upon receiving. But I did not find any. There is also no shell
involved in all these (see logs below).

Any ideas, who is doing this on MacOS? Who is sending 2 extra SIGINTs to 2
parents when a SIGINT is delivered to psql?

I also tried to use any other signal-trapping program instead of psql (like
vim or an artificial Perl script which ignores signals) and did not observe
the same behavior. It looks like something very specific to psql.

Steps to reproduce:

===========================

*Terminal 1:*

% psql --version
psql (PostgreSQL) 16.0

% cat /tmp/my1.pl
#!/usr/bin/perl -w
if (fork()) {
$SIG{INT} = sub { print("int in my1\n") };
while (1) { wait() and exit(1); }
} else {
exec("/tmp/my2.pl");
}

% cat /tmp/my2.pl
#!/usr/bin/perl -w
if (fork()) {
$SIG{INT} = sub { print("int in my2\n") };
while (1) { wait() and exit(1); }
} else {
exec("psql");
}

# PostgreSQL server is running in Docker, localhost remapped port 15432
% PGHOST=127.0.0.1 PGPORT=15432 PGUSER=postgres PGPASSWORD=postgres
PGDATABASE=postgres /tmp/my1.pl
psql (16.0, server 13.5 (Debian 13.5-1.pgdg110+1))
Type "help" for help.
postgres=#

*Terminal 2:*

% pstree | grep -E "bash |yarn|psql|vim|sleep|lldb|my.pl|perl" | grep
dmitry | grep -v grep

| | \-+= 24550 dmitry /usr/bin/perl -w /tmp/my1.pl
| | \-+- 24551 dmitry /usr/bin/perl -w /tmp/my2.pl
| | \--- 24552 dmitry psql

% pgrep psql
24552
% kill -SIGINT 24552

*And I see this in Terminal 1:*

postgres=#
int in my2
int in my1
postgres=#

===========================

I.e. we can see that not only psql got the SIGINT received, but also its
parents (two artificial Perl processes).

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Heikki Linnakangas 2024-04-13 08:25:15 Re: some LLVM function checks missing in meson
Previous Message Heikki Linnakangas 2024-04-13 07:16:11 Re: Fix possible dereference null pointer (src/backend/replication/logical/reorderbuffer.c)