PostgreSQL Source Code  git master
fe-cancel.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * fe-cancel.c
4  * functions related to setting up a connection to the backend
5  *
6  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/interfaces/libpq/fe-cancel.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 
16 #include "postgres_fe.h"
17 
18 #include <unistd.h>
19 
20 #include "libpq-fe.h"
21 #include "libpq-int.h"
22 #include "port/pg_bswap.h"
23 
24 
25 /*
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.
30  */
32 {
34 };
35 
36 /*
37  * pg_cancel (backing struct for PGcancel) stores all data necessary to send a
38  * cancel request.
39  */
40 struct pg_cancel
41 {
42  SockAddr raddr; /* Remote address */
43  int be_pid; /* PID of to-be-canceled backend */
44  int be_key; /* cancel key of to-be-canceled backend */
45  int pgtcp_user_timeout; /* tcp user timeout */
46  int keepalives; /* use TCP keepalives? */
47  int keepalives_idle; /* time between TCP keepalives */
48  int keepalives_interval; /* time between TCP keepalive
49  * retransmits */
50  int keepalives_count; /* maximum number of TCP keepalive
51  * retransmits */
52 };
53 
54 
55 /*
56  * PQcancelCreate
57  *
58  * Create and return a PGcancelConn, which can be used to securely cancel a
59  * query on the given connection.
60  *
61  * This requires either following the non-blocking flow through
62  * PQcancelStart() and PQcancelPoll(), or the blocking PQcancelBlocking().
63  */
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, "passed connection was NULL");
77  return (PGcancelConn *) cancelConn;
78  }
79 
80  if (conn->sock == PGINVALID_SOCKET)
81  {
82  libpq_append_conn_error(cancelConn, "passed connection is 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->connhost)
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:
159  libpq_append_conn_error(cancelConn, "out of memory");
160  return (PGcancelConn *) cancelConn;
161 }
162 
163 
164 /*
165  * PQcancelBlocking
166  *
167  * Send a cancellation request in a blocking fashion.
168  * Returns 1 if successful 0 if not.
169  */
170 int
172 {
174  return 0;
175  return pqConnectDBComplete(&cancelConn->conn);
176 }
177 
178 /*
179  * PQcancelStart
180  *
181  * Starts sending a cancellation request in a non-blocking fashion. Returns
182  * 1 if successful 0 if not.
183  */
184 int
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 }
200 
201 /*
202  * PQcancelPoll
203  *
204  * Poll a cancel connection. For usage details see PQconnectPoll.
205  */
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, "received 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 }
276 
277 /*
278  * PQcancelStatus
279  *
280  * Get the status of a cancel connection.
281  */
284 {
285  return PQstatus(&cancelConn->conn);
286 }
287 
288 /*
289  * PQcancelSocket
290  *
291  * Get the socket of the cancel connection.
292  */
293 int
295 {
296  return PQsocket(&cancelConn->conn);
297 }
298 
299 /*
300  * PQcancelErrorMessage
301  *
302  * Get the socket of the cancel connection.
303  */
304 char *
306 {
307  return PQerrorMessage(&cancelConn->conn);
308 }
309 
310 /*
311  * PQcancelReset
312  *
313  * Resets the cancel connection, so it can be reused to send a new cancel
314  * request.
315  */
316 void
318 {
319  pqClosePGconn(&cancelConn->conn);
320  cancelConn->conn.status = CONNECTION_ALLOCATED;
321  cancelConn->conn.whichhost = 0;
322  cancelConn->conn.whichaddr = 0;
323  cancelConn->conn.try_next_host = false;
324  cancelConn->conn.try_next_addr = false;
325 }
326 
327 /*
328  * PQcancelFinish
329  *
330  * Closes and frees the cancel connection.
331  */
332 void
334 {
335  PQfinish(&cancelConn->conn);
336 }
337 
338 /*
339  * PQgetCancel: get a PGcancel structure corresponding to a connection.
340  *
341  * A copy is needed to be able to cancel a running query from a different
342  * thread. If the same structure is used all structure members would have
343  * to be individually locked (if the entire structure was locked, it would
344  * be impossible to cancel a synchronous query because the structure would
345  * have to stay locked for the duration of the query).
346  */
347 PGcancel *
349 {
350  PGcancel *cancel;
351 
352  if (!conn)
353  return NULL;
354 
355  if (conn->sock == PGINVALID_SOCKET)
356  return NULL;
357 
358  cancel = malloc(sizeof(PGcancel));
359  if (cancel == NULL)
360  return NULL;
361 
362  memcpy(&cancel->raddr, &conn->raddr, sizeof(SockAddr));
363  cancel->be_pid = conn->be_pid;
364  cancel->be_key = conn->be_key;
365  /* We use -1 to indicate an unset connection option */
366  cancel->pgtcp_user_timeout = -1;
367  cancel->keepalives = -1;
368  cancel->keepalives_idle = -1;
369  cancel->keepalives_interval = -1;
370  cancel->keepalives_count = -1;
371  if (conn->pgtcp_user_timeout != NULL)
372  {
374  &cancel->pgtcp_user_timeout,
375  conn, "tcp_user_timeout"))
376  goto fail;
377  }
378  if (conn->keepalives != NULL)
379  {
381  &cancel->keepalives,
382  conn, "keepalives"))
383  goto fail;
384  }
385  if (conn->keepalives_idle != NULL)
386  {
388  &cancel->keepalives_idle,
389  conn, "keepalives_idle"))
390  goto fail;
391  }
392  if (conn->keepalives_interval != NULL)
393  {
395  &cancel->keepalives_interval,
396  conn, "keepalives_interval"))
397  goto fail;
398  }
399  if (conn->keepalives_count != NULL)
400  {
402  &cancel->keepalives_count,
403  conn, "keepalives_count"))
404  goto fail;
405  }
406 
407  return cancel;
408 
409 fail:
410  free(cancel);
411  return NULL;
412 }
413 
414 /* PQfreeCancel: free a cancel structure */
415 void
417 {
418  free(cancel);
419 }
420 
421 
422 /*
423  * Sets an integer socket option on a TCP socket, if the provided value is
424  * not negative. Returns false if setsockopt fails for some reason.
425  *
426  * CAUTION: This needs to be signal safe, since it's used by PQcancel.
427  */
428 #if defined(TCP_USER_TIMEOUT) || !defined(WIN32)
429 static bool
430 optional_setsockopt(int fd, int protoid, int optid, int value)
431 {
432  if (value < 0)
433  return true;
434  if (setsockopt(fd, protoid, optid, (char *) &value, sizeof(value)) < 0)
435  return false;
436  return true;
437 }
438 #endif
439 
440 
441 /*
442  * PQcancel: old, non-encrypted, but signal-safe way of requesting query cancel
443  *
444  * The return value is true if the cancel request was successfully
445  * dispatched, false if not (in which case an error message is available).
446  * Note: successful dispatch is no guarantee that there will be any effect at
447  * the backend. The application must read the operation result as usual.
448  *
449  * On failure, an error message is stored in *errbuf, which must be of size
450  * errbufsize (recommended size is 256 bytes). *errbuf is not changed on
451  * success return.
452  *
453  * CAUTION: we want this routine to be safely callable from a signal handler
454  * (for example, an application might want to call it in a SIGINT handler).
455  * This means we cannot use any C library routine that might be non-reentrant.
456  * malloc/free are often non-reentrant, and anything that might call them is
457  * just as dangerous. We avoid sprintf here for that reason. Building up
458  * error messages with strcpy/strcat is tedious but should be quite safe.
459  * We also save/restore errno in case the signal handler support doesn't.
460  */
461 int
462 PQcancel(PGcancel *cancel, char *errbuf, int errbufsize)
463 {
464  int save_errno = SOCK_ERRNO;
465  pgsocket tmpsock = PGINVALID_SOCKET;
466  int maxlen;
467  struct
468  {
469  uint32 packetlen;
471  } crp;
472 
473  if (!cancel)
474  {
475  strlcpy(errbuf, "PQcancel() -- no cancel object supplied", errbufsize);
476  /* strlcpy probably doesn't change errno, but be paranoid */
477  SOCK_ERRNO_SET(save_errno);
478  return false;
479  }
480 
481  /*
482  * We need to open a temporary connection to the postmaster. Do this with
483  * only kernel calls.
484  */
485  if ((tmpsock = socket(cancel->raddr.addr.ss_family, SOCK_STREAM, 0)) == PGINVALID_SOCKET)
486  {
487  strlcpy(errbuf, "PQcancel() -- socket() failed: ", errbufsize);
488  goto cancel_errReturn;
489  }
490 
491  /*
492  * Since this connection will only be used to send a single packet of
493  * data, we don't need NODELAY. We also don't set the socket to
494  * nonblocking mode, because the API definition of PQcancel requires the
495  * cancel to be sent in a blocking way.
496  *
497  * We do set socket options related to keepalives and other TCP timeouts.
498  * This ensures that this function does not block indefinitely when
499  * reasonable keepalive and timeout settings have been provided.
500  */
501  if (cancel->raddr.addr.ss_family != AF_UNIX &&
502  cancel->keepalives != 0)
503  {
504 #ifndef WIN32
505  if (!optional_setsockopt(tmpsock, SOL_SOCKET, SO_KEEPALIVE, 1))
506  {
507  strlcpy(errbuf, "PQcancel() -- setsockopt(SO_KEEPALIVE) failed: ", errbufsize);
508  goto cancel_errReturn;
509  }
510 
511 #ifdef PG_TCP_KEEPALIVE_IDLE
512  if (!optional_setsockopt(tmpsock, IPPROTO_TCP, PG_TCP_KEEPALIVE_IDLE,
513  cancel->keepalives_idle))
514  {
515  strlcpy(errbuf, "PQcancel() -- setsockopt(" PG_TCP_KEEPALIVE_IDLE_STR ") failed: ", errbufsize);
516  goto cancel_errReturn;
517  }
518 #endif
519 
520 #ifdef TCP_KEEPINTVL
521  if (!optional_setsockopt(tmpsock, IPPROTO_TCP, TCP_KEEPINTVL,
522  cancel->keepalives_interval))
523  {
524  strlcpy(errbuf, "PQcancel() -- setsockopt(TCP_KEEPINTVL) failed: ", errbufsize);
525  goto cancel_errReturn;
526  }
527 #endif
528 
529 #ifdef TCP_KEEPCNT
530  if (!optional_setsockopt(tmpsock, IPPROTO_TCP, TCP_KEEPCNT,
531  cancel->keepalives_count))
532  {
533  strlcpy(errbuf, "PQcancel() -- setsockopt(TCP_KEEPCNT) failed: ", errbufsize);
534  goto cancel_errReturn;
535  }
536 #endif
537 
538 #else /* WIN32 */
539 
540 #ifdef SIO_KEEPALIVE_VALS
541  if (!pqSetKeepalivesWin32(tmpsock,
542  cancel->keepalives_idle,
543  cancel->keepalives_interval))
544  {
545  strlcpy(errbuf, "PQcancel() -- WSAIoctl(SIO_KEEPALIVE_VALS) failed: ", errbufsize);
546  goto cancel_errReturn;
547  }
548 #endif /* SIO_KEEPALIVE_VALS */
549 #endif /* WIN32 */
550 
551  /* TCP_USER_TIMEOUT works the same way on Unix and Windows */
552 #ifdef TCP_USER_TIMEOUT
553  if (!optional_setsockopt(tmpsock, IPPROTO_TCP, TCP_USER_TIMEOUT,
554  cancel->pgtcp_user_timeout))
555  {
556  strlcpy(errbuf, "PQcancel() -- setsockopt(TCP_USER_TIMEOUT) failed: ", errbufsize);
557  goto cancel_errReturn;
558  }
559 #endif
560  }
561 
562 retry3:
563  if (connect(tmpsock, (struct sockaddr *) &cancel->raddr.addr,
564  cancel->raddr.salen) < 0)
565  {
566  if (SOCK_ERRNO == EINTR)
567  /* Interrupted system call - we'll just try again */
568  goto retry3;
569  strlcpy(errbuf, "PQcancel() -- connect() failed: ", errbufsize);
570  goto cancel_errReturn;
571  }
572 
573  /* Create and send the cancel request packet. */
574 
575  crp.packetlen = pg_hton32((uint32) sizeof(crp));
576  crp.cp.cancelRequestCode = (MsgType) pg_hton32(CANCEL_REQUEST_CODE);
577  crp.cp.backendPID = pg_hton32(cancel->be_pid);
578  crp.cp.cancelAuthCode = pg_hton32(cancel->be_key);
579 
580 retry4:
581  if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp))
582  {
583  if (SOCK_ERRNO == EINTR)
584  /* Interrupted system call - we'll just try again */
585  goto retry4;
586  strlcpy(errbuf, "PQcancel() -- send() failed: ", errbufsize);
587  goto cancel_errReturn;
588  }
589 
590  /*
591  * Wait for the postmaster to close the connection, which indicates that
592  * it's processed the request. Without this delay, we might issue another
593  * command only to find that our cancel zaps that command instead of the
594  * one we thought we were canceling. Note we don't actually expect this
595  * read to obtain any data, we are just waiting for EOF to be signaled.
596  */
597 retry5:
598  if (recv(tmpsock, (char *) &crp, 1, 0) < 0)
599  {
600  if (SOCK_ERRNO == EINTR)
601  /* Interrupted system call - we'll just try again */
602  goto retry5;
603  /* we ignore other error conditions */
604  }
605 
606  /* All done */
607  closesocket(tmpsock);
608  SOCK_ERRNO_SET(save_errno);
609  return true;
610 
611 cancel_errReturn:
612 
613  /*
614  * Make sure we don't overflow the error buffer. Leave space for the \n at
615  * the end, and for the terminating zero.
616  */
617  maxlen = errbufsize - strlen(errbuf) - 2;
618  if (maxlen >= 0)
619  {
620  /*
621  * We can't invoke strerror here, since it's not signal-safe. Settle
622  * for printing the decimal value of errno. Even that has to be done
623  * the hard way.
624  */
625  int val = SOCK_ERRNO;
626  char buf[32];
627  char *bufp;
628 
629  bufp = buf + sizeof(buf) - 1;
630  *bufp = '\0';
631  do
632  {
633  *(--bufp) = (val % 10) + '0';
634  val /= 10;
635  } while (val > 0);
636  bufp -= 6;
637  memcpy(bufp, "error ", 6);
638  strncat(errbuf, bufp, maxlen);
639  strcat(errbuf, "\n");
640  }
641  if (tmpsock != PGINVALID_SOCKET)
642  closesocket(tmpsock);
643  SOCK_ERRNO_SET(save_errno);
644  return false;
645 }
646 
647 /*
648  * PQrequestCancel: old, not thread-safe function for requesting query cancel
649  *
650  * Returns true if able to send the cancel request, false if not.
651  *
652  * On failure, the error message is saved in conn->errorMessage; this means
653  * that this can't be used when there might be other active operations on
654  * the connection object.
655  *
656  * NOTE: error messages will be cut off at the current size of the
657  * error message buffer, since we dare not try to expand conn->errorMessage!
658  */
659 int
661 {
662  int r;
663  PGcancel *cancel;
664 
665  /* Check we have an open connection */
666  if (!conn)
667  return false;
668 
669  if (conn->sock == PGINVALID_SOCKET)
670  {
672  "PQrequestCancel() -- connection is not open\n",
675  conn->errorReported = 0;
676 
677  return false;
678  }
679 
680  cancel = PQgetCancel(conn);
681  if (cancel)
682  {
683  r = PQcancel(cancel, conn->errorMessage.data,
685  PQfreeCancel(cancel);
686  }
687  else
688  {
689  strlcpy(conn->errorMessage.data, "out of memory",
691  r = false;
692  }
693 
694  if (!r)
695  {
697  conn->errorReported = 0;
698  }
699 
700  return r;
701 }
unsigned int uint32
Definition: c.h:506
static PGcancel *volatile cancelConn
Definition: cancel.c:43
PGcancel * PQgetCancel(PGconn *conn)
Definition: fe-cancel.c:348
void PQcancelReset(PGcancelConn *cancelConn)
Definition: fe-cancel.c:317
PGcancelConn * PQcancelCreate(PGconn *conn)
Definition: fe-cancel.c:65
ConnStatusType PQcancelStatus(const PGcancelConn *cancelConn)
Definition: fe-cancel.c:283
static bool optional_setsockopt(int fd, int protoid, int optid, int value)
Definition: fe-cancel.c:430
int PQcancelBlocking(PGcancelConn *cancelConn)
Definition: fe-cancel.c:171
int PQcancel(PGcancel *cancel, char *errbuf, int errbufsize)
Definition: fe-cancel.c:462
char * PQcancelErrorMessage(const PGcancelConn *cancelConn)
Definition: fe-cancel.c:305
PostgresPollingStatusType PQcancelPoll(PGcancelConn *cancelConn)
Definition: fe-cancel.c:207
void PQcancelFinish(PGcancelConn *cancelConn)
Definition: fe-cancel.c:333
int PQrequestCancel(PGconn *conn)
Definition: fe-cancel.c:660
void PQfreeCancel(PGcancel *cancel)
Definition: fe-cancel.c:416
int PQcancelSocket(const PGcancelConn *cancelConn)
Definition: fe-cancel.c:294
int PQcancelStart(PGcancelConn *cancelConn)
Definition: fe-cancel.c:185
bool pqConnectOptions2(PGconn *conn)
Definition: fe-connect.c:1120
void pqClosePGconn(PGconn *conn)
Definition: fe-connect.c:4822
PostgresPollingStatusType PQconnectPoll(PGconn *conn)
Definition: fe-connect.c:2591
bool pqParseIntParam(const char *value, int *result, PGconn *conn, const char *context)
Definition: fe-connect.c:7682
void pqReleaseConnHosts(PGconn *conn)
Definition: fe-connect.c:4706
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:7147
ConnStatusType PQstatus(const PGconn *conn)
Definition: fe-connect.c:7094
PGconn * pqMakeEmptyPGconn(void)
Definition: fe-connect.c:4525
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4868
int pqConnectDBStart(PGconn *conn)
Definition: fe-connect.c:2374
bool pqCopyPGconn(PGconn *srcConn, PGconn *dstConn)
Definition: fe-connect.c:956
int PQsocket(const PGconn *conn)
Definition: fe-connect.c:7173
int pqConnectDBComplete(PGconn *conn)
Definition: fe-connect.c:2452
int pqReadData(PGconn *conn)
Definition: fe-misc.c:565
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
Definition: fe-misc.c:1324
#define calloc(a, b)
Definition: header.h:55
#define free(a)
Definition: header.h:65
#define malloc(a)
Definition: header.h:50
long val
Definition: informix.c:670
static struct @155 value
ConnStatusType
Definition: libpq-fe.h:60
@ CONNECTION_AWAITING_RESPONSE
Definition: libpq-fe.h:71
@ CONNECTION_BAD
Definition: libpq-fe.h:62
@ CONNECTION_OK
Definition: libpq-fe.h:61
@ CONNECTION_ALLOCATED
Definition: libpq-fe.h:84
PostgresPollingStatusType
Definition: libpq-fe.h:89
@ PGRES_POLLING_OK
Definition: libpq-fe.h:93
@ PGRES_POLLING_READING
Definition: libpq-fe.h:91
@ PGRES_POLLING_FAILED
Definition: libpq-fe.h:90
#define SOCK_ERRNO
Definition: libpq-int.h:934
#define SOCK_ERRNO_SET(e)
Definition: libpq-int.h:936
#define pg_hton32(x)
Definition: pg_bswap.h:121
static char * buf
Definition: pg_test_fsync.c:73
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:132
ProtocolVersion MsgType
Definition: pqcomm.h:101
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:146
static int fd(const char *x, int i)
Definition: preproc-init.c:105
PGconn * conn
Definition: streamutil.c:55
struct sockaddr_storage addr
Definition: pqcomm.h:32
socklen_t salen
Definition: pqcomm.h:33
PGconn conn
Definition: fe-cancel.c: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
char * host
Definition: libpq-int.h:353
char * password
Definition: libpq-int.h:356
char * port
Definition: libpq-int.h:355
char * hostaddr
Definition: libpq-int.h:354
pgsocket sock
Definition: libpq-int.h:475
int errorReported
Definition: libpq-int.h:636
int be_pid
Definition: libpq-int.h:510
int be_key
Definition: libpq-int.h:511
char * keepalives_idle
Definition: libpq-int.h:392
char * keepalives
Definition: libpq-int.h:391
char * keepalives_interval
Definition: libpq-int.h:393
char * pgtcp_user_timeout
Definition: libpq-int.h:379
PQExpBufferData errorMessage
Definition: libpq-int.h:635
SockAddr raddr
Definition: libpq-int.h:478
int whichhost
Definition: libpq-int.h:457
char * keepalives_count
Definition: libpq-int.h:395
pg_conn_host * connhost
Definition: libpq-int.h:458
ConnStatusType status
Definition: libpq-int.h:438
#define EINTR
Definition: win32_port.h:374
#define recv(s, buf, len, flags)
Definition: win32_port.h:496
#define send(s, buf, len, flags)
Definition: win32_port.h:497
#define socket(af, type, protocol)
Definition: win32_port.h:490
#define connect(s, name, namelen)
Definition: win32_port.h:494