1/*-------------------------------------------------------------------------
4 * functions related to query cancellation
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/interfaces/libpq/fe-cancel.c
13 *-------------------------------------------------------------------------
26 * pg_cancel_conn (backing struct for PGcancelConn) is a wrapper around a
27 * PGconn to send cancellations using PQcancelBlocking and PQcancelStart.
28 * This isn't just a typedef because we want the compiler to complain when a
29 * PGconn is passed to a function that expects a PGcancelConn, and vice versa.
37 * pg_cancel (backing struct for PGcancel) stores all data necessary to send a
43 int be_pid;
/* PID of to-be-canceled backend */
52 /* Pre-constructed cancel request packet starts here */
61 * Create and return a PGcancelConn, which can be used to securely cancel a
62 * query on the given connection.
64 * This requires either following the non-blocking flow through
65 * PQcancelStart() and PQcancelPoll(), or the blocking PQcancelBlocking().
76 /* Check we have an open connection */
89 /* Check that we have received a cancellation key */
97 * Indicate that this connection is used to send a cancellation
105 * Compute derived options
111 * Copy cancellation token data from the original connection
125 * Cancel requests should not iterate over all possible hosts. The request
126 * needs to be sent to the exact host and address that the original
127 * connection used. So we manually create the host and address arrays with
128 * a single element after freeing the host array that we generated from
129 * the connection options.
141 if (originalHost.
host)
153 if (originalHost.
port)
186 * Send a cancellation request in a blocking fashion.
187 * Returns 1 if successful 0 if not.
200 * Starts sending a cancellation request in a non-blocking fashion. Returns
201 * 1 if successful 0 if not.
212 "cancel request is already being sent on this connection");
223 * Poll a cancel connection. For usage details see PQconnectPoll.
232 * We leave most of the connection establishment to PQconnectPoll, since
233 * it's very similar to normal connection establishment. But once we get
234 * to the CONNECTION_AWAITING_RESPONSE we need to start doing our own
243 * At this point we are waiting on the server to close the connection,
244 * which is its way of communicating that the cancel has been handled.
255 * If we receive an error report it, but only if errno is non-zero.
256 * Otherwise we assume it's an EOF, which is what we expect from the
259 * We skip this for Windows, because Windows is a bit special in its EOF
260 * behaviour for TCP. Sometimes it will error with an ECONNRESET when
261 * there is a clean connection closure. See these threads for details:
262 * https://www.postgresql.org/message-id/flat/90b34057-4176-7bb0-0dbb-9822a5f6425b%40greiz-reinsdorf.de
264 * https://www.postgresql.org/message-id/flat/CA%2BhUKG%2BOeoETZQ%3DQw5Ub5h3tmwQhBmDA%3DnuNO3KG%3DzWfUypFAw%40mail.gmail.com
266 * PQcancel ignores such errors and reports success for the cancellation
267 * anyway, so even if this is not always correct we do the same here.
269 if (n < 0 && errno != 0)
277 * We don't expect any data, only connection closure. So if we strangely
278 * do receive some data we consider that an error.
288 * Getting here means that we received an EOF, which is what we were
289 * expecting -- the cancel request has completed.
299 * Get the status of a cancel connection.
310 * Get the socket of the cancel connection.
319 * PQcancelErrorMessage
321 * Returns the error message most recently generated by an operation on the
333 * Resets the cancel connection, so it can be reused to send a new cancel
350 * Closes and frees the cancel connection.
359 * PQgetCancel: get a PGcancel structure corresponding to a connection.
361 * A copy is needed to be able to cancel a running query from a different
362 * thread. If the same structure is used all structure members would have
363 * to be individually locked (if the entire structure was locked, it would
364 * be impossible to cancel a synchronous query because the structure would
365 * have to stay locked for the duration of the query).
380 /* Check that we have received a cancellation key */
384 * In case there is no cancel key, return an all-zero PGcancel object.
385 * Actually calling PQcancel on this will fail, but we allow creating
386 * the PGcancel object anyway. Arguably it would be better return NULL
387 * to indicate that cancellation is not possible, but there'd be no
388 * way for the caller to distinguish "out of memory" from "server did
389 * not send a cancel key". Also, this is how PGgetCancel() has always
390 * behaved, and if we changed it, some clients would stop working
391 * altogether with servers that don't support cancellation. (The
392 * modern PQcancelCreate() function returns a failed connection object
395 * The returned dummy object has cancel_pkt_len == 0; we check for
396 * that in PQcancel() to identify it as a dummy.
408 /* We use -1 to indicate an unset connection option */
418 conn,
"tcp_user_timeout"))
432 conn,
"keepalives_idle"))
439 conn,
"keepalives_interval"))
446 conn,
"keepalives_count"))
454 /* include the length field itself in the length */
465 * PQsendCancelRequest
466 * Submit a CancelRequest message, but don't wait for it to finish
468 * Returns: 1 if successfully submitted
469 * 0 if error (conn->errorMessage is set)
476 /* Start the message. */
480 /* Send the message body. */
489 /* Finish the message. */
493 /* Flush to ensure backend gets it. */
500/* PQfreeCancel: free a cancel structure */
509 * Sets an integer socket option on a TCP socket, if the provided value is
510 * not negative. Returns false if setsockopt fails for some reason.
512 * CAUTION: This needs to be signal safe, since it's used by PQcancel.
514#if defined(TCP_USER_TIMEOUT) || !defined(WIN32)
520 if (setsockopt(
fd, protoid, optid, (
char *) &
value,
sizeof(
value)) < 0)
528 * PQcancel: old, non-encrypted, but signal-safe way of requesting query cancel
530 * The return value is true if the cancel request was successfully
531 * dispatched, false if not (in which case an error message is available).
532 * Note: successful dispatch is no guarantee that there will be any effect at
533 * the backend. The application must read the operation result as usual.
535 * On failure, an error message is stored in *errbuf, which must be of size
536 * errbufsize (recommended size is 256 bytes). *errbuf is not changed on
539 * CAUTION: we want this routine to be safely callable from a signal handler
540 * (for example, an application might want to call it in a SIGINT handler).
541 * This means we cannot use any C library routine that might be non-reentrant.
542 * malloc/free are often non-reentrant, and anything that might call them is
543 * just as dangerous. We avoid sprintf here for that reason. Building up
544 * error messages with strcpy/strcat is tedious but should be quite safe.
545 * We also save/restore errno in case the signal handler support doesn't.
558 strlcpy(errbuf,
"PQcancel() -- no cancel object supplied", errbufsize);
559 /* strlcpy probably doesn't change errno, but be paranoid */
566 /* This is a dummy PGcancel object, see PQgetCancel */
567 strlcpy(errbuf,
"PQcancel() -- no cancellation key received", errbufsize);
568 /* strlcpy probably doesn't change errno, but be paranoid */
574 * We need to open a temporary connection to the postmaster. Do this with
579 strlcpy(errbuf,
"PQcancel() -- socket() failed: ", errbufsize);
580 goto cancel_errReturn;
584 * Since this connection will only be used to send a single packet of
585 * data, we don't need NODELAY. We also don't set the socket to
586 * nonblocking mode, because the API definition of PQcancel requires the
587 * cancel to be sent in a blocking way.
589 * We do set socket options related to keepalives and other TCP timeouts.
590 * This ensures that this function does not block indefinitely when
591 * reasonable keepalive and timeout settings have been provided.
593 if (cancel->
raddr.
addr.ss_family != AF_UNIX &&
599 strlcpy(errbuf,
"PQcancel() -- setsockopt(SO_KEEPALIVE) failed: ", errbufsize);
600 goto cancel_errReturn;
603#ifdef PG_TCP_KEEPALIVE_IDLE
607 strlcpy(errbuf,
"PQcancel() -- setsockopt(" PG_TCP_KEEPALIVE_IDLE_STR
") failed: ", errbufsize);
608 goto cancel_errReturn;
616 strlcpy(errbuf,
"PQcancel() -- setsockopt(TCP_KEEPINTVL) failed: ", errbufsize);
617 goto cancel_errReturn;
625 strlcpy(errbuf,
"PQcancel() -- setsockopt(TCP_KEEPCNT) failed: ", errbufsize);
626 goto cancel_errReturn;
632#ifdef SIO_KEEPALIVE_VALS
633 if (!pqSetKeepalivesWin32(tmpsock,
637 strlcpy(errbuf,
"PQcancel() -- WSAIoctl(SIO_KEEPALIVE_VALS) failed: ", errbufsize);
638 goto cancel_errReturn;
640#endif /* SIO_KEEPALIVE_VALS */
643 /* TCP_USER_TIMEOUT works the same way on Unix and Windows */
644#ifdef TCP_USER_TIMEOUT
648 strlcpy(errbuf,
"PQcancel() -- setsockopt(TCP_USER_TIMEOUT) failed: ", errbufsize);
649 goto cancel_errReturn;
659 /* Interrupted system call - we'll just try again */
661 strlcpy(errbuf,
"PQcancel() -- connect() failed: ", errbufsize);
662 goto cancel_errReturn;
670 * Send the cancel request packet. It starts with the message length at
671 * cancel_pkt_len, followed by the actual packet.
673 if (
send(tmpsock, (
char *) &cancel->
cancel_pkt_len, cancel_pkt_len, 0) != cancel_pkt_len)
676 /* Interrupted system call - we'll just try again */
678 strlcpy(errbuf,
"PQcancel() -- send() failed: ", errbufsize);
679 goto cancel_errReturn;
683 * Wait for the postmaster to close the connection, which indicates that
684 * it's processed the request. Without this delay, we might issue another
685 * command only to find that our cancel zaps that command instead of the
686 * one we thought we were canceling. Note we don't actually expect this
687 * read to obtain any data, we are just waiting for EOF to be signaled.
690 if (
recv(tmpsock, &recvbuf, 1, 0) < 0)
693 /* Interrupted system call - we'll just try again */
695 /* we ignore other error conditions */
706 * Make sure we don't overflow the error buffer. Leave space for the \n at
707 * the end, and for the terminating zero.
709 maxlen = errbufsize - strlen(errbuf) - 2;
713 * We can't invoke strerror here, since it's not signal-safe. Settle
714 * for printing the decimal value of errno. Even that has to be done
721 bufp =
buf +
sizeof(
buf) - 1;
725 *(--bufp) = (
val % 10) +
'0';
729 memcpy(bufp,
"error ", 6);
730 strncat(errbuf, bufp, maxlen);
731 strcat(errbuf,
"\n");
740 * PQrequestCancel: old, not thread-safe function for requesting query cancel
742 * Returns true if able to send the cancel request, false if not.
744 * On failure, the error message is saved in conn->errorMessage; this means
745 * that this can't be used when there might be other active operations on
746 * the connection object.
748 * NOTE: error messages will be cut off at the current size of the
749 * error message buffer, since we dare not try to expand conn->errorMessage!
757 /* Check we have an open connection */
764 "PQrequestCancel() -- connection is not open\n",
#define FLEXIBLE_ARRAY_MEMBER
static PGcancel *volatile cancelConn
PGcancel * PQgetCancel(PGconn *conn)
void PQcancelReset(PGcancelConn *cancelConn)
int PQsendCancelRequest(PGconn *cancelConn)
PGcancelConn * PQcancelCreate(PGconn *conn)
ConnStatusType PQcancelStatus(const PGcancelConn *cancelConn)
static bool optional_setsockopt(int fd, int protoid, int optid, int value)
int PQcancelBlocking(PGcancelConn *cancelConn)
int PQcancel(PGcancel *cancel, char *errbuf, int errbufsize)
PostgresPollingStatusType PQcancelPoll(PGcancelConn *cancelConn)
void PQcancelFinish(PGcancelConn *cancelConn)
int PQrequestCancel(PGconn *conn)
void PQfreeCancel(PGcancel *cancel)
int PQcancelSocket(const PGcancelConn *cancelConn)
char * PQcancelErrorMessage(const PGcancelConn *cancelConn)
int PQcancelStart(PGcancelConn *cancelConn)
bool pqConnectOptions2(PGconn *conn)
void pqClosePGconn(PGconn *conn)
PostgresPollingStatusType PQconnectPoll(PGconn *conn)
bool pqParseIntParam(const char *value, int *result, PGconn *conn, const char *context)
void pqReleaseConnHosts(PGconn *conn)
ConnStatusType PQstatus(const PGconn *conn)
void PQfinish(PGconn *conn)
PGconn * pqMakeEmptyPGconn(void)
int pqConnectDBStart(PGconn *conn)
bool pqCopyPGconn(PGconn *srcConn, PGconn *dstConn)
char * PQerrorMessage(const PGconn *conn)
int PQsocket(const PGconn *conn)
int pqConnectDBComplete(PGconn *conn)
int pqReadData(PGconn *conn)
int pqFlush(PGconn *conn)
int pqPutMsgStart(char msg_type, PGconn *conn)
int pqPutnchar(const void *s, size_t len, PGconn *conn)
int pqPutMsgEnd(PGconn *conn)
@ CONNECTION_AWAITING_RESPONSE
PostgresPollingStatusType
#define SOCK_ERRNO_SET(e)
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
size_t strlcpy(char *dst, const char *src, size_t siz)
#define CANCEL_REQUEST_CODE
void resetPQExpBuffer(PQExpBuffer str)
static int fd(const char *x, int i)
MsgType cancelRequestCode
uint8 cancelAuthCode[FLEXIBLE_ARRAY_MEMBER]
struct sockaddr_storage addr
char cancel_req[FLEXIBLE_ARRAY_MEMBER]
char * keepalives_interval
char * pgtcp_user_timeout
PQExpBufferData errorMessage
#define recv(s, buf, len, flags)
#define send(s, buf, len, flags)
#define socket(af, type, protocol)
#define connect(s, name, namelen)