PostgreSQL Source Code  git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
fe-cancel.c File Reference
#include "postgres_fe.h"
#include <unistd.h>
#include "libpq-fe.h"
#include "libpq-int.h"
#include "port/pg_bswap.h"
Include dependency graph for fe-cancel.c:

Go to the source code of this file.

Data Structures

struct  pg_cancel_conn
 
struct  pg_cancel
 

Functions

PGcancelConnPQcancelCreate (PGconn *conn)
 
int PQcancelBlocking (PGcancelConn *cancelConn)
 
int PQcancelStart (PGcancelConn *cancelConn)
 
PostgresPollingStatusType PQcancelPoll (PGcancelConn *cancelConn)
 
ConnStatusType PQcancelStatus (const PGcancelConn *cancelConn)
 
int PQcancelSocket (const PGcancelConn *cancelConn)
 
char * PQcancelErrorMessage (const PGcancelConn *cancelConn)
 
void PQcancelReset (PGcancelConn *cancelConn)
 
void PQcancelFinish (PGcancelConn *cancelConn)
 
PGcancelPQgetCancel (PGconn *conn)
 
void PQfreeCancel (PGcancel *cancel)
 
static bool optional_setsockopt (int fd, int protoid, int optid, int value)
 
int PQcancel (PGcancel *cancel, char *errbuf, int errbufsize)
 
int PQrequestCancel (PGconn *conn)
 

Function Documentation

◆ optional_setsockopt()

static bool optional_setsockopt ( int  fd,
int  protoid,
int  optid,
int  value 
)
static

Definition at line 431 of file fe-cancel.c.

432 {
433  if (value < 0)
434  return true;
435  if (setsockopt(fd, protoid, optid, (char *) &value, sizeof(value)) < 0)
436  return false;
437  return true;
438 }
static struct @160 value
static int fd(const char *x, int i)
Definition: preproc-init.c:105

References fd(), and value.

Referenced by PQcancel().

◆ PQcancel()

int PQcancel ( PGcancel cancel,
char *  errbuf,
int  errbufsize 
)

Definition at line 463 of file fe-cancel.c.

464 {
465  int save_errno = SOCK_ERRNO;
466  pgsocket tmpsock = PGINVALID_SOCKET;
467  int maxlen;
468  struct
469  {
470  uint32 packetlen;
472  } crp;
473 
474  if (!cancel)
475  {
476  strlcpy(errbuf, "PQcancel() -- no cancel object supplied", errbufsize);
477  /* strlcpy probably doesn't change errno, but be paranoid */
478  SOCK_ERRNO_SET(save_errno);
479  return false;
480  }
481 
482  /*
483  * We need to open a temporary connection to the postmaster. Do this with
484  * only kernel calls.
485  */
486  if ((tmpsock = socket(cancel->raddr.addr.ss_family, SOCK_STREAM, 0)) == PGINVALID_SOCKET)
487  {
488  strlcpy(errbuf, "PQcancel() -- socket() failed: ", errbufsize);
489  goto cancel_errReturn;
490  }
491 
492  /*
493  * Since this connection will only be used to send a single packet of
494  * data, we don't need NODELAY. We also don't set the socket to
495  * nonblocking mode, because the API definition of PQcancel requires the
496  * cancel to be sent in a blocking way.
497  *
498  * We do set socket options related to keepalives and other TCP timeouts.
499  * This ensures that this function does not block indefinitely when
500  * reasonable keepalive and timeout settings have been provided.
501  */
502  if (cancel->raddr.addr.ss_family != AF_UNIX &&
503  cancel->keepalives != 0)
504  {
505 #ifndef WIN32
506  if (!optional_setsockopt(tmpsock, SOL_SOCKET, SO_KEEPALIVE, 1))
507  {
508  strlcpy(errbuf, "PQcancel() -- setsockopt(SO_KEEPALIVE) failed: ", errbufsize);
509  goto cancel_errReturn;
510  }
511 
512 #ifdef PG_TCP_KEEPALIVE_IDLE
513  if (!optional_setsockopt(tmpsock, IPPROTO_TCP, PG_TCP_KEEPALIVE_IDLE,
514  cancel->keepalives_idle))
515  {
516  strlcpy(errbuf, "PQcancel() -- setsockopt(" PG_TCP_KEEPALIVE_IDLE_STR ") failed: ", errbufsize);
517  goto cancel_errReturn;
518  }
519 #endif
520 
521 #ifdef TCP_KEEPINTVL
522  if (!optional_setsockopt(tmpsock, IPPROTO_TCP, TCP_KEEPINTVL,
523  cancel->keepalives_interval))
524  {
525  strlcpy(errbuf, "PQcancel() -- setsockopt(TCP_KEEPINTVL) failed: ", errbufsize);
526  goto cancel_errReturn;
527  }
528 #endif
529 
530 #ifdef TCP_KEEPCNT
531  if (!optional_setsockopt(tmpsock, IPPROTO_TCP, TCP_KEEPCNT,
532  cancel->keepalives_count))
533  {
534  strlcpy(errbuf, "PQcancel() -- setsockopt(TCP_KEEPCNT) failed: ", errbufsize);
535  goto cancel_errReturn;
536  }
537 #endif
538 
539 #else /* WIN32 */
540 
541 #ifdef SIO_KEEPALIVE_VALS
542  if (!pqSetKeepalivesWin32(tmpsock,
543  cancel->keepalives_idle,
544  cancel->keepalives_interval))
545  {
546  strlcpy(errbuf, "PQcancel() -- WSAIoctl(SIO_KEEPALIVE_VALS) failed: ", errbufsize);
547  goto cancel_errReturn;
548  }
549 #endif /* SIO_KEEPALIVE_VALS */
550 #endif /* WIN32 */
551 
552  /* TCP_USER_TIMEOUT works the same way on Unix and Windows */
553 #ifdef TCP_USER_TIMEOUT
554  if (!optional_setsockopt(tmpsock, IPPROTO_TCP, TCP_USER_TIMEOUT,
555  cancel->pgtcp_user_timeout))
556  {
557  strlcpy(errbuf, "PQcancel() -- setsockopt(TCP_USER_TIMEOUT) failed: ", errbufsize);
558  goto cancel_errReturn;
559  }
560 #endif
561  }
562 
563 retry3:
564  if (connect(tmpsock, (struct sockaddr *) &cancel->raddr.addr,
565  cancel->raddr.salen) < 0)
566  {
567  if (SOCK_ERRNO == EINTR)
568  /* Interrupted system call - we'll just try again */
569  goto retry3;
570  strlcpy(errbuf, "PQcancel() -- connect() failed: ", errbufsize);
571  goto cancel_errReturn;
572  }
573 
574  /* Create and send the cancel request packet. */
575 
576  crp.packetlen = pg_hton32((uint32) sizeof(crp));
577  crp.cp.cancelRequestCode = (MsgType) pg_hton32(CANCEL_REQUEST_CODE);
578  crp.cp.backendPID = pg_hton32(cancel->be_pid);
579  crp.cp.cancelAuthCode = pg_hton32(cancel->be_key);
580 
581 retry4:
582  if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp))
583  {
584  if (SOCK_ERRNO == EINTR)
585  /* Interrupted system call - we'll just try again */
586  goto retry4;
587  strlcpy(errbuf, "PQcancel() -- send() failed: ", errbufsize);
588  goto cancel_errReturn;
589  }
590 
591  /*
592  * Wait for the postmaster to close the connection, which indicates that
593  * it's processed the request. Without this delay, we might issue another
594  * command only to find that our cancel zaps that command instead of the
595  * one we thought we were canceling. Note we don't actually expect this
596  * read to obtain any data, we are just waiting for EOF to be signaled.
597  */
598 retry5:
599  if (recv(tmpsock, (char *) &crp, 1, 0) < 0)
600  {
601  if (SOCK_ERRNO == EINTR)
602  /* Interrupted system call - we'll just try again */
603  goto retry5;
604  /* we ignore other error conditions */
605  }
606 
607  /* All done */
608  closesocket(tmpsock);
609  SOCK_ERRNO_SET(save_errno);
610  return true;
611 
612 cancel_errReturn:
613 
614  /*
615  * Make sure we don't overflow the error buffer. Leave space for the \n at
616  * the end, and for the terminating zero.
617  */
618  maxlen = errbufsize - strlen(errbuf) - 2;
619  if (maxlen >= 0)
620  {
621  /*
622  * We can't invoke strerror here, since it's not signal-safe. Settle
623  * for printing the decimal value of errno. Even that has to be done
624  * the hard way.
625  */
626  int val = SOCK_ERRNO;
627  char buf[32];
628  char *bufp;
629 
630  bufp = buf + sizeof(buf) - 1;
631  *bufp = '\0';
632  do
633  {
634  *(--bufp) = (val % 10) + '0';
635  val /= 10;
636  } while (val > 0);
637  bufp -= 6;
638  memcpy(bufp, "error ", 6);
639  strncat(errbuf, bufp, maxlen);
640  strcat(errbuf, "\n");
641  }
642  if (tmpsock != PGINVALID_SOCKET)
643  closesocket(tmpsock);
644  SOCK_ERRNO_SET(save_errno);
645  return false;
646 }
unsigned int uint32
Definition: c.h:518
static bool optional_setsockopt(int fd, int protoid, int optid, int value)
Definition: fe-cancel.c:431
long val
Definition: informix.c:689
#define SOCK_ERRNO
Definition: libpq-int.h:927
#define SOCK_ERRNO_SET(e)
Definition: libpq-int.h:929
#define pg_hton32(x)
Definition: pg_bswap.h:121
static char * buf
Definition: pg_test_fsync.c:72
int pgsocket
Definition: port.h:29
#define PGINVALID_SOCKET
Definition: port.h:31
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define closesocket
Definition: port.h:349
#define CANCEL_REQUEST_CODE
Definition: pqcomm.h:133
ProtocolVersion MsgType
Definition: pqcomm.h:102
struct sockaddr_storage addr
Definition: pqcomm.h:32
socklen_t salen
Definition: pqcomm.h:33
int pgtcp_user_timeout
Definition: fe-cancel.c:45
int keepalives_interval
Definition: fe-cancel.c:48
int keepalives_idle
Definition: fe-cancel.c:47
int keepalives_count
Definition: fe-cancel.c:50
SockAddr raddr
Definition: fe-cancel.c:42
int be_pid
Definition: fe-cancel.c:43
int keepalives
Definition: fe-cancel.c:46
int be_key
Definition: fe-cancel.c:44
#define EINTR
Definition: win32_port.h:374
#define recv(s, buf, len, flags)
Definition: win32_port.h:514
#define send(s, buf, len, flags)
Definition: win32_port.h:515
#define socket(af, type, protocol)
Definition: win32_port.h:508
#define connect(s, name, namelen)
Definition: win32_port.h:512

References SockAddr::addr, pg_cancel::be_key, pg_cancel::be_pid, buf, CANCEL_REQUEST_CODE, closesocket, connect, EINTR, pg_cancel::keepalives, pg_cancel::keepalives_count, pg_cancel::keepalives_idle, pg_cancel::keepalives_interval, optional_setsockopt(), pg_hton32, PGINVALID_SOCKET, pg_cancel::pgtcp_user_timeout, pg_cancel::raddr, recv, SockAddr::salen, send, SOCK_ERRNO, SOCK_ERRNO_SET, socket, strlcpy(), and val.

Referenced by DisconnectDatabase(), handle_sigint(), PQrequestCancel(), ShutdownWorkersHard(), sigTermHandler(), and test_cancel().

◆ PQcancelBlocking()

int PQcancelBlocking ( PGcancelConn cancelConn)

Definition at line 171 of file fe-cancel.c.

172 {
174  return 0;
175  return pqConnectDBComplete(&cancelConn->conn);
176 }
static PGcancel *volatile cancelConn
Definition: cancel.c:43
int PQcancelStart(PGcancelConn *cancelConn)
Definition: fe-cancel.c:185
int pqConnectDBComplete(PGconn *conn)
Definition: fe-connect.c:2471

References cancelConn, PQcancelStart(), and pqConnectDBComplete().

Referenced by disconnectDatabase(), test_cancel(), and try_complete_step().

◆ PQcancelCreate()

PGcancelConn* PQcancelCreate ( PGconn conn)

Definition at line 65 of file fe-cancel.c.

66 {
68  pg_conn_host originalHost;
69 
70  if (cancelConn == NULL)
71  return NULL;
72 
73  /* Check we have an open connection */
74  if (!conn)
75  {
76  libpq_append_conn_error(cancelConn, "connection pointer is NULL");
77  return (PGcancelConn *) cancelConn;
78  }
79 
80  if (conn->sock == PGINVALID_SOCKET)
81  {
82  libpq_append_conn_error(cancelConn, "connection not open");
83  return (PGcancelConn *) cancelConn;
84  }
85 
86  /*
87  * Indicate that this connection is used to send a cancellation
88  */
89  cancelConn->cancelRequest = true;
90 
92  return (PGcancelConn *) cancelConn;
93 
94  /*
95  * Compute derived options
96  */
98  return (PGcancelConn *) cancelConn;
99 
100  /*
101  * Copy cancellation token data from the original connection
102  */
105 
106  /*
107  * Cancel requests should not iterate over all possible hosts. The request
108  * needs to be sent to the exact host and address that the original
109  * connection used. So we manually create the host and address arrays with
110  * a single element after freeing the host array that we generated from
111  * the connection options.
112  */
114  cancelConn->nconnhost = 1;
115  cancelConn->naddr = 1;
116 
117  cancelConn->connhost = calloc(cancelConn->nconnhost, sizeof(pg_conn_host));
118  if (!cancelConn->connhost)
119  goto oom_error;
120 
121  originalHost = conn->connhost[conn->whichhost];
122  if (originalHost.host)
123  {
124  cancelConn->connhost[0].host = strdup(originalHost.host);
125  if (!cancelConn->connhost[0].host)
126  goto oom_error;
127  }
128  if (originalHost.hostaddr)
129  {
130  cancelConn->connhost[0].hostaddr = strdup(originalHost.hostaddr);
131  if (!cancelConn->connhost[0].hostaddr)
132  goto oom_error;
133  }
134  if (originalHost.port)
135  {
136  cancelConn->connhost[0].port = strdup(originalHost.port);
137  if (!cancelConn->connhost[0].port)
138  goto oom_error;
139  }
140  if (originalHost.password)
141  {
142  cancelConn->connhost[0].password = strdup(originalHost.password);
143  if (!cancelConn->connhost[0].password)
144  goto oom_error;
145  }
146 
147  cancelConn->addr = calloc(cancelConn->naddr, sizeof(AddrInfo));
148  if (!cancelConn->addr)
149  goto oom_error;
150 
151  cancelConn->addr[0].addr = conn->raddr;
152  cancelConn->addr[0].family = conn->raddr.addr.ss_family;
153 
155  return (PGcancelConn *) cancelConn;
156 
157 oom_error:
158  cancelConn->status = CONNECTION_BAD;
159  libpq_append_conn_error(cancelConn, "out of memory");
160  return (PGcancelConn *) cancelConn;
161 }
bool pqConnectOptions2(PGconn *conn)
Definition: fe-connect.c:1121
void pqReleaseConnHosts(PGconn *conn)
Definition: fe-connect.c:4717
PGconn * pqMakeEmptyPGconn(void)
Definition: fe-connect.c:4536
bool pqCopyPGconn(PGconn *srcConn, PGconn *dstConn)
Definition: fe-connect.c:957
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
Definition: fe-misc.c:1372
#define calloc(a, b)
Definition: header.h:55
@ CONNECTION_BAD
Definition: libpq-fe.h:82
@ CONNECTION_ALLOCATED
Definition: libpq-fe.h:104
PGconn * conn
Definition: streamutil.c:53
char * host
Definition: libpq-int.h:364
char * password
Definition: libpq-int.h:367
char * port
Definition: libpq-int.h:366
char * hostaddr
Definition: libpq-int.h:365
pgsocket sock
Definition: libpq-int.h:485
int be_pid
Definition: libpq-int.h:522
int be_key
Definition: libpq-int.h:523
SockAddr raddr
Definition: libpq-int.h:488
int whichhost
Definition: libpq-int.h:467
pg_conn_host * connhost
Definition: libpq-int.h:468

References SockAddr::addr, pg_cancel::be_key, pg_conn::be_key, pg_cancel::be_pid, pg_conn::be_pid, calloc, cancelConn, conn, CONNECTION_ALLOCATED, CONNECTION_BAD, pg_conn::connhost, pg_conn_host::host, pg_conn_host::hostaddr, libpq_append_conn_error(), pg_conn_host::password, PGINVALID_SOCKET, pg_conn_host::port, pqConnectOptions2(), pqCopyPGconn(), pqMakeEmptyPGconn(), pqReleaseConnHosts(), pg_conn::raddr, pg_conn::sock, and pg_conn::whichhost.

Referenced by disconnectDatabase(), libpqsrv_cancel(), test_cancel(), and try_complete_step().

◆ PQcancelErrorMessage()

char* PQcancelErrorMessage ( const PGcancelConn cancelConn)

Definition at line 306 of file fe-cancel.c.

307 {
308  return PQerrorMessage(&cancelConn->conn);
309 }
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:7200

References cancelConn, and PQerrorMessage().

Referenced by libpqsrv_cancel(), test_cancel(), and try_complete_step().

◆ PQcancelFinish()

void PQcancelFinish ( PGcancelConn cancelConn)

Definition at line 334 of file fe-cancel.c.

335 {
336  PQfinish(&cancelConn->conn);
337 }
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4879

References cancelConn, and PQfinish().

Referenced by disconnectDatabase(), libpqsrv_cancel(), test_cancel(), and try_complete_step().

◆ PQcancelPoll()

PostgresPollingStatusType PQcancelPoll ( PGcancelConn cancelConn)

Definition at line 207 of file fe-cancel.c.

208 {
209  PGconn *conn = &cancelConn->conn;
210  int n;
211 
212  /*
213  * We leave most of the connection establishment to PQconnectPoll, since
214  * it's very similar to normal connection establishment. But once we get
215  * to the CONNECTION_AWAITING_RESPONSE we need to start doing our own
216  * thing.
217  */
219  {
220  return PQconnectPoll(conn);
221  }
222 
223  /*
224  * At this point we are waiting on the server to close the connection,
225  * which is its way of communicating that the cancel has been handled.
226  */
227 
228  n = pqReadData(conn);
229 
230  if (n == 0)
231  return PGRES_POLLING_READING;
232 
233 #ifndef WIN32
234 
235  /*
236  * If we receive an error report it, but only if errno is non-zero.
237  * Otherwise we assume it's an EOF, which is what we expect from the
238  * server.
239  *
240  * We skip this for Windows, because Windows is a bit special in its EOF
241  * behaviour for TCP. Sometimes it will error with an ECONNRESET when
242  * there is a clean connection closure. See these threads for details:
243  * https://www.postgresql.org/message-id/flat/90b34057-4176-7bb0-0dbb-9822a5f6425b%40greiz-reinsdorf.de
244  *
245  * https://www.postgresql.org/message-id/flat/CA%2BhUKG%2BOeoETZQ%3DQw5Ub5h3tmwQhBmDA%3DnuNO3KG%3DzWfUypFAw%40mail.gmail.com
246  *
247  * PQcancel ignores such errors and reports success for the cancellation
248  * anyway, so even if this is not always correct we do the same here.
249  */
250  if (n < 0 && errno != 0)
251  {
253  return PGRES_POLLING_FAILED;
254  }
255 #endif
256 
257  /*
258  * We don't expect any data, only connection closure. So if we strangely
259  * do receive some data we consider that an error.
260  */
261  if (n > 0)
262  {
263  libpq_append_conn_error(conn, "unexpected response from server");
265  return PGRES_POLLING_FAILED;
266  }
267 
268  /*
269  * Getting here means that we received an EOF, which is what we were
270  * expecting -- the cancel request has completed.
271  */
272  cancelConn->conn.status = CONNECTION_OK;
274  return PGRES_POLLING_OK;
275 }
PostgresPollingStatusType PQconnectPoll(PGconn *conn)
Definition: fe-connect.c:2597
int pqReadData(PGconn *conn)
Definition: fe-misc.c:580
@ CONNECTION_AWAITING_RESPONSE
Definition: libpq-fe.h:91
@ CONNECTION_OK
Definition: libpq-fe.h:81
@ PGRES_POLLING_OK
Definition: libpq-fe.h:113
@ PGRES_POLLING_READING
Definition: libpq-fe.h:111
@ PGRES_POLLING_FAILED
Definition: libpq-fe.h:110
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:146
PQExpBufferData errorMessage
Definition: libpq-int.h:643
ConnStatusType status
Definition: libpq-int.h:448

References cancelConn, conn, CONNECTION_AWAITING_RESPONSE, CONNECTION_BAD, CONNECTION_OK, pg_conn::errorMessage, libpq_append_conn_error(), PGRES_POLLING_FAILED, PGRES_POLLING_OK, PGRES_POLLING_READING, PQconnectPoll(), pqReadData(), resetPQExpBuffer(), and pg_conn::status.

Referenced by libpqsrv_cancel(), pqConnectDBComplete(), and test_cancel().

◆ PQcancelReset()

void PQcancelReset ( PGcancelConn cancelConn)

Definition at line 318 of file fe-cancel.c.

319 {
320  pqClosePGconn(&cancelConn->conn);
321  cancelConn->conn.status = CONNECTION_ALLOCATED;
322  cancelConn->conn.whichhost = 0;
323  cancelConn->conn.whichaddr = 0;
324  cancelConn->conn.try_next_host = false;
325  cancelConn->conn.try_next_addr = false;
326 }
void pqClosePGconn(PGconn *conn)
Definition: fe-connect.c:4833

References cancelConn, CONNECTION_ALLOCATED, and pqClosePGconn().

Referenced by test_cancel().

◆ PQcancelSocket()

int PQcancelSocket ( const PGcancelConn cancelConn)

Definition at line 294 of file fe-cancel.c.

295 {
296  return PQsocket(&cancelConn->conn);
297 }
int PQsocket(const PGconn *conn)
Definition: fe-connect.c:7226

References cancelConn, and PQsocket().

Referenced by libpqsrv_cancel(), and test_cancel().

◆ PQcancelStart()

int PQcancelStart ( PGcancelConn cancelConn)

Definition at line 185 of file fe-cancel.c.

186 {
187  if (!cancelConn || cancelConn->conn.status == CONNECTION_BAD)
188  return 0;
189 
190  if (cancelConn->conn.status != CONNECTION_ALLOCATED)
191  {
193  "cancel request is already being sent on this connection");
194  cancelConn->conn.status = CONNECTION_BAD;
195  return 0;
196  }
197 
198  return pqConnectDBStart(&cancelConn->conn);
199 }
int pqConnectDBStart(PGconn *conn)
Definition: fe-connect.c:2393

References cancelConn, CONNECTION_ALLOCATED, CONNECTION_BAD, libpq_append_conn_error(), and pqConnectDBStart().

Referenced by libpqsrv_cancel(), PQcancelBlocking(), and test_cancel().

◆ PQcancelStatus()

ConnStatusType PQcancelStatus ( const PGcancelConn cancelConn)

Definition at line 283 of file fe-cancel.c.

284 {
285  return PQstatus(&cancelConn->conn);
286 }
ConnStatusType PQstatus(const PGconn *conn)
Definition: fe-connect.c:7137

References cancelConn, and PQstatus().

Referenced by test_cancel().

◆ PQfreeCancel()

void PQfreeCancel ( PGcancel cancel)

Definition at line 417 of file fe-cancel.c.

418 {
419  free(cancel);
420 }
#define free(a)
Definition: header.h:65

References free.

Referenced by PQrequestCancel(), ResetCancelConn(), set_archive_cancel_info(), SetCancelConn(), and test_cancel().

◆ PQgetCancel()

PGcancel* PQgetCancel ( PGconn conn)

Definition at line 349 of file fe-cancel.c.

350 {
351  PGcancel *cancel;
352 
353  if (!conn)
354  return NULL;
355 
356  if (conn->sock == PGINVALID_SOCKET)
357  return NULL;
358 
359  cancel = malloc(sizeof(PGcancel));
360  if (cancel == NULL)
361  return NULL;
362 
363  memcpy(&cancel->raddr, &conn->raddr, sizeof(SockAddr));
364  cancel->be_pid = conn->be_pid;
365  cancel->be_key = conn->be_key;
366  /* We use -1 to indicate an unset connection option */
367  cancel->pgtcp_user_timeout = -1;
368  cancel->keepalives = -1;
369  cancel->keepalives_idle = -1;
370  cancel->keepalives_interval = -1;
371  cancel->keepalives_count = -1;
372  if (conn->pgtcp_user_timeout != NULL)
373  {
375  &cancel->pgtcp_user_timeout,
376  conn, "tcp_user_timeout"))
377  goto fail;
378  }
379  if (conn->keepalives != NULL)
380  {
382  &cancel->keepalives,
383  conn, "keepalives"))
384  goto fail;
385  }
386  if (conn->keepalives_idle != NULL)
387  {
389  &cancel->keepalives_idle,
390  conn, "keepalives_idle"))
391  goto fail;
392  }
393  if (conn->keepalives_interval != NULL)
394  {
396  &cancel->keepalives_interval,
397  conn, "keepalives_interval"))
398  goto fail;
399  }
400  if (conn->keepalives_count != NULL)
401  {
403  &cancel->keepalives_count,
404  conn, "keepalives_count"))
405  goto fail;
406  }
407 
408  return cancel;
409 
410 fail:
411  free(cancel);
412  return NULL;
413 }
bool pqParseIntParam(const char *value, int *result, PGconn *conn, const char *context)
Definition: fe-connect.c:7756
#define malloc(a)
Definition: header.h:50
char * keepalives_idle
Definition: libpq-int.h:403
char * keepalives
Definition: libpq-int.h:402
char * keepalives_interval
Definition: libpq-int.h:404
char * pgtcp_user_timeout
Definition: libpq-int.h:390
char * keepalives_count
Definition: libpq-int.h:406

References pg_cancel::be_key, pg_conn::be_key, pg_cancel::be_pid, pg_conn::be_pid, conn, free, pg_cancel::keepalives, pg_conn::keepalives, pg_cancel::keepalives_count, pg_conn::keepalives_count, pg_cancel::keepalives_idle, pg_conn::keepalives_idle, pg_cancel::keepalives_interval, pg_conn::keepalives_interval, malloc, PGINVALID_SOCKET, pg_cancel::pgtcp_user_timeout, pg_conn::pgtcp_user_timeout, pqParseIntParam(), pg_cancel::raddr, pg_conn::raddr, and pg_conn::sock.

Referenced by PQrequestCancel(), set_archive_cancel_info(), SetCancelConn(), and test_cancel().

◆ PQrequestCancel()

int PQrequestCancel ( PGconn conn)

Definition at line 661 of file fe-cancel.c.

662 {
663  int r;
664  PGcancel *cancel;
665 
666  /* Check we have an open connection */
667  if (!conn)
668  return false;
669 
670  if (conn->sock == PGINVALID_SOCKET)
671  {
673  "PQrequestCancel() -- connection is not open\n",
676  conn->errorReported = 0;
677 
678  return false;
679  }
680 
681  cancel = PQgetCancel(conn);
682  if (cancel)
683  {
684  r = PQcancel(cancel, conn->errorMessage.data,
686  PQfreeCancel(cancel);
687  }
688  else
689  {
690  strlcpy(conn->errorMessage.data, "out of memory",
692  r = false;
693  }
694 
695  if (!r)
696  {
698  conn->errorReported = 0;
699  }
700 
701  return r;
702 }
PGcancel * PQgetCancel(PGconn *conn)
Definition: fe-cancel.c:349
int PQcancel(PGcancel *cancel, char *errbuf, int errbufsize)
Definition: fe-cancel.c:463
void PQfreeCancel(PGcancel *cancel)
Definition: fe-cancel.c:417
int errorReported
Definition: libpq-int.h:644

References conn, PQExpBufferData::data, pg_conn::errorMessage, pg_conn::errorReported, PQExpBufferData::len, PQExpBufferData::maxlen, PGINVALID_SOCKET, PQcancel(), PQfreeCancel(), PQgetCancel(), pg_conn::sock, and strlcpy().

Referenced by test_cancel().