On 30/07/2025 00:20, Jelte Fennema-Nio wrote:
> On Tue, 29 Jul 2025 at 22:42, Heikki Linnakangas <hlinnaka@iki.fi> wrote:
>> I'm not quite sold on the change to PQcancelCreate(). The current
>> behavior seems nicer: if cancellation is not available because the
>> server didn't send a cancellation key, PQcancelCreate() returns a
>> (cancel) connection object that's in a failed state with an error
>> message explaining what's wrong. The client can choose to continue
>> without cancellation capability, or bail out.
>>
>> Are there any known drivers that require the change to PQcancelCreate()?
>
> I scoured github search[1] and it seems that (sadly) the only two
> libraries (on github) that actually use PQcancelCreate are psycopg3
> and ruby-pg. Both of those only create the object when they actually
> want to cancel something (not when they use it). So I agree that the
> change in bahaviour in PG18 for this function seems fine, and probably
> is desirable. So feel free to commit my previous patch without the
> changes to PQcancelCreate.
Ok, thanks for checking! Committed the PGgetCancel() part.
I felt that explaining historical libpq behavior was a bit too much
detail in the protocol docs, so I cut it down to just this:
> The PostgreSQL server will always send this message, but some third
party backend implementations of the protocol that don't support query
cancellation are known not to.
Perhaps it would indeed be good to specify more strictly that no
cancellation key means that the server doesn't support cancellation, but
it feels like a separate change. And if we do that, perhaps we should
document that retroactively for protocol version 3.0 too. And if it's
not too invasive, even backpatch something for older libpq versions.
Arguably it's a bug to send an all-zeros CancelRequest.
If we wanted to truly support the missing cancel key, here's something
else to consider: psql's error message isn't very nice when you hit
CTRL-C and there's no cancel key:
postgres=# select pg_sleep(10);
^CCould not send cancel request: PQcancel() -- no cancellation key received
That's pretty low level. And there's no newline, so if you hit CTRL-C
again, it looks like this:
postgres=# select pg_sleep(10);
^CCould not send cancel request: PQcancel() -- no cancellation key
received^CCould not send cancel request: PQcancel() -- no cancellation
key received
It would be nice to improve all that, but it needs more work.
(I will now start looking at your second patch,
v3-0002-libpq-Be-strict-about-accept-cancel-key-lengths.patch)
- Heikki