Re: Don't use the deprecated and insecure PQcancel in our frontend tools anymore
Heikki Linnakangas <hlinnaka@iki.fi>
From: Heikki Linnakangas <hlinnaka@iki.fi>
To: Jelte Fennema-Nio <postgres@jeltef.nl>,
PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>,
Alvaro Herrera <alvherre@alvh.no-ip.org>,
Jacob Champion <jacob.champion@enterprisedb.com>
Date: 2026-03-05T18:30:29Z
Lists: pgsql-hackers
On 08/02/2026 21:05, Jelte Fennema-Nio wrote: > On Sun Dec 14, 2025 at 3:40 PM CET, Jelte Fennema-Nio wrote: >> A bunch of frontend tools, including psql, still used PQcancel to send >> cancel requests to the server. That function is insecure, because it >> does not use encryption to send the cancel request. This starts using >> the new cancellation APIs (introduced in 61461a300) for all these >> frontend tools. > > Small update. Split up the fe_utils and pg_dump changes into separate > commits, to make patches easier to review. Also use non-blocking writes > to the self-pipe from the signal handler to avoid potential deadlocks > (extremely unlikely for such blocks to occur, but better safe than sorry). Had a brief look at this: It took me a while to get the big picture of how this works. cancel.c could use some high-level comments explaining how to use the facility; it's a real mixed bag right now. The SIGINT handler now does three things: - Set CancelRequested global variable, - call callback if set, and - wake up the cancel thread to send the cancel message, if cancel connection is set. There's no high-level overview documentation or comments on how those three mechanism work or interact. It took me a while to understand that they are really separate, alternative ways to handle SIGINT, all mashed into the same signal handler function. At first read, I thought they're somehow part of the one same mechanism. The cancelConn mechanism is a global variable, which means that it can only be used with one connection in the process. That's OK with the current callers, but seems short-sighted. What if we wanted to use it for pgbench, for example, which uses multiple threads and connections? Or if we changed pg_dump to use multiple threads, like you also suggested as a possible follow-up. The "self-pipe trick" usually refers to interrupting the main thread from select(); this uses it to wake up the other, separate cancellation thread. That's fine, but again it took me a while to understand that that's what it does. Comments! This is racy, if the cancellation thread doesn't immediately process the wakeup. For example, because it's still busy processing a previous wakeup, because there's a network hiccup or something. By the time the cancellation thread runs, the main thread might already be running a different query than it was when the user hit CTRL-C. - Heikki