Re: [EXTERNAL] Re: Add non-blocking version of PQcancel
Jelte Fennema-Nio <jelte.fennema@microsoft.com>
Thanks for all the feedback everyone. I'll try to send a new patch
later this week that includes user facing docs and a simplified API.
For now a few responses:
> Yeah. We need to choose a name for these new function(s) that is
> sufficiently different from "PQcancel" that people won't expect them
> to behave exactly the same as that does. I lack any good ideas about
> that, how about you?
So I guess the names I proposed were not great, since everyone seems to be falling over them.
But I'd like to make my intention clear with the current naming. After this patch there would be
four different APIs for starting a cancelation:
1. PQrequestCancel: deprecated+old, not signal-safe function for requesting query cancellation, only uses a specific set of connection options
2. PQcancel: Cancel queries in a signal safe way, to be signal-safe it only uses a limited set of connection options
3. PQcancelConnect: Cancel queries in a non-signal safe way that uses all connection options
4. PQcancelConnectStart: Cancel queries in a non-signal safe and non-blocking way that uses all connection options
So the idea was that you should not look at PQcancelConnectStart as the non-blocking
version of PQcancel, but as the non-blocking version of PQcancelConnect. I'll try to
think of some different names too, but IMHO these names could be acceptable
when their differences are addressed sufficiently in the documentation.
One other approach to naming that comes to mind now is repurposing PQrequestCancel:
1. PQrequestCancel: Cancel queries in a non-signal safe way that uses all connection options
2. PQrequestCancelStart: Cancel queries in a non-signal safe and non-blocking way that uses all connection options
3. PQcancel: Cancel queries in a signal safe way, to be signal-safe it only uses a limited set of connection options
> I think it's probably a
> bad sign that this function is tinkering with logic in this sort of
> low-level function anyway. pqReadData() is a really general function
> that manages to work with non-blocking I/O already, so why does
> non-blocking query cancellation need to change its return values, or
> whether or not it drops data in certain cases?
The reason for this low level change is that the cancellation part of the
Postgres protocol is following a different, much more simplistic design
than all the other parts. The client does not expect a response message back
from the server after sending the cancellation request. The expectation
is that the server signals completion by closing the connection, i.e. sending EOF.
For all other parts of the protocol, connection termination should be initiated
client side by sending a Terminate message. So the server closing (sending
EOF) is always unexpected and is thus currently considered an error by pqReadData.
But since this is not the case for the cancellation protocol, the result is
changed to -2 in case of EOF to make it possible to distinguish between
an EOF and an actual error.
> And it updates that function to return -2 when the is
> ECONNRESET, which seems to fly in the face of the comment's idea that
> this is the "clean connection closure" case.
The diff sadly does not include the very relevant comment right above these
lines. Pasting the whole case statement here to clear up this confusion:
case SSL_ERROR_ZERO_RETURN:
/*
* Per OpenSSL documentation, this error code is only returned for
* a clean connection closure, so we should not report it as a
* server crash.
*/
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("SSL connection has been closed unexpectedly\n"));
result_errno = ECONNRESET;
n = -2;
break;
> For example, it updates the
> comment for pqsecure_read() to say "Returns -1 in case of failures,
> except in the case of clean connection closure then it returns -2."
> But that function calls any of three different implementation
> functions depending on the situation and the patch only updates one of
> them.
That comment is indeed not describing what is happening correctly and I'll
try to make it clearer. The main reason for it being incorrect is coming from
the fact that receiving EOFs is handled in different places based on the
encryption method:
1. Unencrypted TCP: EOF is not returned as an error by pqsecure_read, but detected by pqReadData (see comments related to definitelyEOF)
2. OpenSSL: EOF is returned as an error by pqsecure_read (see copied case statement above)
3. GSS: When writing the patch I was not sure how EOF handling worked here, but given that the tests passed for Jacob on GSS, I'm guessing it works the same as unencrypted TCP.
Commits
-
postgres_fdw: re-issue cancel requests a few times if necessary.
- c431986de16c 18.0 landed
- 89962bfef624 17.3 landed
-
Make postgres_fdw's query_cancel test less flaky.
- 8749d850f962 17.0 landed
- 0e5c823806a3 18.0 landed
-
postgres_fdw: Split out the query_cancel test to its own file
- d329a515f490 17.0 landed
- 90c1ba52e06d 18.0 landed
-
Fix copy-paste mistake in PQcancelCreate
- 6d2ac554911d 17.0 landed
- 3497c87b05a6 18.0 landed
-
Make libpqsrv_cancel's return const char *, not char *
- b8b37e41ba4a 17.0 landed
-
Stabilize postgres_fdw test
- ecf741cfae06 17.0 landed
-
libpq-be-fe-helpers.h: wrap new cancel APIs
- 2466d6654f85 17.0 landed
-
dblink/isolationtester/fe_utils: Use new cancel API
- 66ab9371a233 17.0 landed
-
Put libpq_pipeline cancel test back
- 6b3678d3474f 17.0 landed
-
Hopefully make libpq_pipeline's new cancel test more reliable
- 1ee910ce4371 17.0 landed
-
libpq: Add encrypted and non-blocking query cancellation routines
- 61461a300c1c 17.0 landed
-
libpq: Move pg_cancel to fe-cancel.c
- 4dec98c2af64 17.0 landed
-
Add tests for libpq query cancellation APIs
- 319e9e53f379 17.0 landed
-
Add missing connection statuses to docs
- 095493a3771a 17.0 landed
-
libpq: Change some static functions to extern
- 774bcffe4a98 17.0 landed
-
libpq: Add pqReleaseConnHosts function
- 53747f722228 17.0 landed
-
libpq: Move cancellation related functions to fe-cancel.c
- 6d4565a05f3f 17.0 landed
-
Make spelling of cancelled/cancellation consistent
- 8c9da1441df1 17.0 landed
-
Be more wary about OpenSSL not setting errno on error.
- 0a5c46a7a488 17.0 cited
-
libpq: Use modern socket flags, if available.
- bfc9497ece01 16.0 cited
-
Drop test view when done with it.
- 71a75626d527 16.0 cited
-
Doc: add some doco about using the libpq_pipeline test module.
- f40346ff0bae 16.0 landed
-
postgres_fdw: Allow cancellation of transaction control commands.
- ae9bfc5d6512 10.0 cited