PostgreSQL Source Code  git master
fe-misc.c File Reference
#include "postgres_fe.h"
#include <signal.h>
#include <time.h>
#include <unistd.h>
#include <sys/select.h>
#include <poll.h>
#include "libpq-fe.h"
#include "libpq-int.h"
#include "mb/pg_wchar.h"
#include "pg_config_paths.h"
#include "port/pg_bswap.h"
Include dependency graph for fe-misc.c:

Go to the source code of this file.

Functions

static int pqPutMsgBytes (const void *buf, size_t len, PGconn *conn)
 
static int pqSendSome (PGconn *conn, int len)
 
static int pqSocketCheck (PGconn *conn, int forRead, int forWrite, time_t end_time)
 
static int pqSocketPoll (int sock, int forRead, int forWrite, time_t end_time)
 
int PQlibVersion (void)
 
int pqGetc (char *result, PGconn *conn)
 
int pqPutc (char c, PGconn *conn)
 
static int pqGets_internal (PQExpBuffer buf, PGconn *conn, bool resetbuffer)
 
int pqGets (PQExpBuffer buf, PGconn *conn)
 
int pqGets_append (PQExpBuffer buf, PGconn *conn)
 
int pqPuts (const char *s, PGconn *conn)
 
int pqGetnchar (char *s, size_t len, PGconn *conn)
 
int pqSkipnchar (size_t len, PGconn *conn)
 
int pqPutnchar (const char *s, size_t len, PGconn *conn)
 
int pqGetInt (int *result, size_t bytes, PGconn *conn)
 
int pqPutInt (int value, size_t bytes, PGconn *conn)
 
int pqCheckOutBufferSpace (size_t bytes_needed, PGconn *conn)
 
int pqCheckInBufferSpace (size_t bytes_needed, PGconn *conn)
 
int pqPutMsgStart (char msg_type, PGconn *conn)
 
int pqPutMsgEnd (PGconn *conn)
 
int pqReadData (PGconn *conn)
 
int pqFlush (PGconn *conn)
 
int pqWait (int forRead, int forWrite, PGconn *conn)
 
int pqWaitTimed (int forRead, int forWrite, PGconn *conn, time_t finish_time)
 
int pqReadReady (PGconn *conn)
 
int pqWriteReady (PGconn *conn)
 
int PQmblen (const char *s, int encoding)
 
int PQmblenBounded (const char *s, int encoding)
 
int PQdsplen (const char *s, int encoding)
 
int PQenv2encoding (void)
 
void libpq_append_error (PQExpBuffer errorMessage, const char *fmt,...)
 
void libpq_append_conn_error (PGconn *conn, const char *fmt,...)
 

Function Documentation

◆ libpq_append_conn_error()

void libpq_append_conn_error ( PGconn conn,
const char *  fmt,
  ... 
)

Definition at line 1312 of file fe-misc.c.

1313 {
1314  int save_errno = errno;
1315  bool done;
1316  va_list args;
1317 
1318  Assert(fmt[strlen(fmt) - 1] != '\n');
1319 
1321  return; /* already failed */
1322 
1323  /* Loop in case we have to retry after enlarging the buffer. */
1324  do
1325  {
1326  errno = save_errno;
1327  va_start(args, fmt);
1329  va_end(args);
1330  } while (!done);
1331 
1333 }
#define libpq_gettext(x)
Definition: libpq-int.h:900
static void const char * fmt
va_end(args)
Assert(fmt[strlen(fmt) - 1] !='\n')
va_start(args, fmt)
bool appendPQExpBufferVA(PQExpBuffer str, const char *fmt, va_list args)
Definition: pqexpbuffer.c:294
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:378
#define PQExpBufferBroken(str)
Definition: pqexpbuffer.h:59
PGconn * conn
Definition: streamutil.c:54
PQExpBufferData errorMessage
Definition: libpq-int.h:617

References appendPQExpBufferChar(), appendPQExpBufferVA(), generate_unaccent_rules::args, Assert(), conn, pg_conn::errorMessage, fmt, libpq_gettext, PQExpBufferBroken, va_end(), and va_start().

Referenced by build_client_final_message(), build_client_first_message(), check_expected_areq(), connectFailureMessage(), connectNoDelay(), connectOptions2(), fillPGconn(), handleSyncLoss(), initialize_SSL(), lo_create(), lo_export(), lo_import_internal(), lo_initialize(), lo_lseek64(), lo_read(), lo_tell64(), lo_truncate(), lo_truncate64(), lo_write(), open_client_SSL(), openssl_verify_peer_name_matches_certificate_ip(), openssl_verify_peer_name_matches_certificate_name(), parse_int_param(), pg_fe_sendauth(), pg_GSS_load_servicename(), pg_GSS_read(), pg_GSS_write(), pg_password_sendauth(), pg_SASL_continue(), pg_SASL_init(), pgpassfileWarning(), pgtls_get_peer_certificate_hash(), pgtls_read(), pgtls_write(), pq_verify_peer_name_matches_certificate(), pq_verify_peer_name_matches_certificate_ip(), pq_verify_peer_name_matches_certificate_name(), pqAllocCmdQueueEntry(), PQconnectPoll(), PQencryptPasswordConn(), pqEndcopy3(), PQenterPipelineMode(), PQescapeByteaInternal(), PQescapeInternal(), PQescapeStringInternal(), PQexecStart(), PQexitPipelineMode(), PQfn(), pqFunctionCall3(), PQgetCopyData(), pqGetCopyData3(), pqGetErrorNotice3(), pqGetline3(), pqGetNegotiateProtocolVersion3(), PQgetResult(), pqParseInput3(), pqPipelineProcessQueue(), PQpipelineSync(), pqPrepareAsyncResult(), PQputCopyData(), PQputCopyEnd(), pqReadData(), pqSaveWriteError(), pqsecure_open_gss(), pqsecure_raw_read(), PQsendFlushRequest(), PQsendPrepare(), PQsendQueryGuts(), PQsendQueryInternal(), PQsendQueryParams(), PQsendQueryPrepared(), PQsendQueryStart(), PQsendTypedCommand(), PQsetdbLogin(), pqSocketCheck(), pqWaitTimed(), read_server_final_message(), read_server_first_message(), scram_exchange(), setKeepalivesCount(), setKeepalivesIdle(), setKeepalivesInterval(), setTCPUserTimeout(), and store_conn_addrinfo().

◆ libpq_append_error()

void libpq_append_error ( PQExpBuffer  errorMessage,
const char *  fmt,
  ... 
)

Definition at line 1283 of file fe-misc.c.

1284 {
1285  int save_errno = errno;
1286  bool done;
1287  va_list args;
1288 
1289  Assert(fmt[strlen(fmt) - 1] != '\n');
1290 
1291  if (PQExpBufferBroken(errorMessage))
1292  return; /* already failed */
1293 
1294  /* Loop in case we have to retry after enlarging the buffer. */
1295  do
1296  {
1297  errno = save_errno;
1298  va_start(args, fmt);
1299  done = appendPQExpBufferVA(errorMessage, libpq_gettext(fmt), args);
1300  va_end(args);
1301  } while (!done);
1302 
1303  appendPQExpBufferChar(errorMessage, '\n');
1304 }

References appendPQExpBufferChar(), appendPQExpBufferVA(), generate_unaccent_rules::args, Assert(), fmt, libpq_gettext, PQExpBufferBroken, va_end(), and va_start().

Referenced by conninfo_add_defaults(), conninfo_array_parse(), conninfo_init(), conninfo_parse(), conninfo_storeval(), conninfo_uri_decode(), conninfo_uri_parse_options(), conninfo_uri_parse_params(), parseServiceFile(), parseServiceInfo(), pg_fe_getusername(), and read_attr_value().

◆ pqCheckInBufferSpace()

int pqCheckInBufferSpace ( size_t  bytes_needed,
PGconn conn 
)

Definition at line 352 of file fe-misc.c.

353 {
354  int newsize = conn->inBufSize;
355  char *newbuf;
356 
357  /* Quick exit if we have enough space */
358  if (bytes_needed <= (size_t) newsize)
359  return 0;
360 
361  /*
362  * Before concluding that we need to enlarge the buffer, left-justify
363  * whatever is in it and recheck. The caller's value of bytes_needed
364  * includes any data to the left of inStart, but we can delete that in
365  * preference to enlarging the buffer. It's slightly ugly to have this
366  * function do this, but it's better than making callers worry about it.
367  */
368  bytes_needed -= conn->inStart;
369 
370  if (conn->inStart < conn->inEnd)
371  {
372  if (conn->inStart > 0)
373  {
374  memmove(conn->inBuffer, conn->inBuffer + conn->inStart,
375  conn->inEnd - conn->inStart);
376  conn->inEnd -= conn->inStart;
377  conn->inCursor -= conn->inStart;
378  conn->inStart = 0;
379  }
380  }
381  else
382  {
383  /* buffer is logically empty, reset it */
384  conn->inStart = conn->inCursor = conn->inEnd = 0;
385  }
386 
387  /* Recheck whether we have enough space */
388  if (bytes_needed <= (size_t) newsize)
389  return 0;
390 
391  /*
392  * If we need to enlarge the buffer, we first try to double it in size; if
393  * that doesn't work, enlarge in multiples of 8K. This avoids thrashing
394  * the malloc pool by repeated small enlargements.
395  *
396  * Note: tests for newsize > 0 are to catch integer overflow.
397  */
398  do
399  {
400  newsize *= 2;
401  } while (newsize > 0 && bytes_needed > (size_t) newsize);
402 
403  if (newsize > 0 && bytes_needed <= (size_t) newsize)
404  {
405  newbuf = realloc(conn->inBuffer, newsize);
406  if (newbuf)
407  {
408  /* realloc succeeded */
409  conn->inBuffer = newbuf;
410  conn->inBufSize = newsize;
411  return 0;
412  }
413  }
414 
415  newsize = conn->inBufSize;
416  do
417  {
418  newsize += 8192;
419  } while (newsize > 0 && bytes_needed > (size_t) newsize);
420 
421  if (newsize > 0 && bytes_needed <= (size_t) newsize)
422  {
423  newbuf = realloc(conn->inBuffer, newsize);
424  if (newbuf)
425  {
426  /* realloc succeeded */
427  conn->inBuffer = newbuf;
428  conn->inBufSize = newsize;
429  return 0;
430  }
431  }
432 
433  /* realloc failed. Probably out of memory */
435  "cannot allocate memory for input buffer\n");
436  return EOF;
437 }
#define realloc(a, b)
Definition: header.h:60
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:367
char * inBuffer
Definition: libpq-int.h:508
int inCursor
Definition: libpq-int.h:511
int inEnd
Definition: libpq-int.h:512
int inBufSize
Definition: libpq-int.h:509
int inStart
Definition: libpq-int.h:510

References appendPQExpBufferStr(), conn, pg_conn::errorMessage, pg_conn::inBuffer, pg_conn::inBufSize, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, and realloc.

Referenced by getCopyDataMessage(), PQconnectPoll(), pqFunctionCall3(), pqParseInput3(), and pqReadData().

◆ pqCheckOutBufferSpace()

int pqCheckOutBufferSpace ( size_t  bytes_needed,
PGconn conn 
)

Definition at line 288 of file fe-misc.c.

289 {
290  int newsize = conn->outBufSize;
291  char *newbuf;
292 
293  /* Quick exit if we have enough space */
294  if (bytes_needed <= (size_t) newsize)
295  return 0;
296 
297  /*
298  * If we need to enlarge the buffer, we first try to double it in size; if
299  * that doesn't work, enlarge in multiples of 8K. This avoids thrashing
300  * the malloc pool by repeated small enlargements.
301  *
302  * Note: tests for newsize > 0 are to catch integer overflow.
303  */
304  do
305  {
306  newsize *= 2;
307  } while (newsize > 0 && bytes_needed > (size_t) newsize);
308 
309  if (newsize > 0 && bytes_needed <= (size_t) newsize)
310  {
311  newbuf = realloc(conn->outBuffer, newsize);
312  if (newbuf)
313  {
314  /* realloc succeeded */
315  conn->outBuffer = newbuf;
316  conn->outBufSize = newsize;
317  return 0;
318  }
319  }
320 
321  newsize = conn->outBufSize;
322  do
323  {
324  newsize += 8192;
325  } while (newsize > 0 && bytes_needed > (size_t) newsize);
326 
327  if (newsize > 0 && bytes_needed <= (size_t) newsize)
328  {
329  newbuf = realloc(conn->outBuffer, newsize);
330  if (newbuf)
331  {
332  /* realloc succeeded */
333  conn->outBuffer = newbuf;
334  conn->outBufSize = newsize;
335  return 0;
336  }
337  }
338 
339  /* realloc failed. Probably out of memory */
341  "cannot allocate memory for output buffer\n");
342  return EOF;
343 }
int outBufSize
Definition: libpq-int.h:516
char * outBuffer
Definition: libpq-int.h:515

References appendPQExpBufferStr(), conn, pg_conn::errorMessage, pg_conn::outBuffer, pg_conn::outBufSize, and realloc.

Referenced by PQputCopyData(), pqPutMsgBytes(), and pqPutMsgStart().

◆ PQdsplen()

int PQdsplen ( const char *  s,
int  encoding 
)

Definition at line 1197 of file fe-misc.c.

1198 {
1199  return pg_encoding_dsplen(encoding, s);
1200 }
int32 encoding
Definition: pg_database.h:41
int pg_encoding_dsplen(int encoding, const char *mbstr)
Definition: wchar.c:2151

References encoding, and pg_encoding_dsplen().

Referenced by get_prompt(), pg_wcsformat(), pg_wcssize(), pg_wcswidth(), and strlen_max_width().

◆ PQenv2encoding()

int PQenv2encoding ( void  )

Definition at line 1206 of file fe-misc.c.

1207 {
1208  char *str;
1209  int encoding = PG_SQL_ASCII;
1210 
1211  str = getenv("PGCLIENTENCODING");
1212  if (str && *str != '\0')
1213  {
1215  if (encoding < 0)
1217  }
1218  return encoding;
1219 }
int pg_char_to_encoding(const char *name)
Definition: encnames.c:550
@ PG_SQL_ASCII
Definition: pg_wchar.h:226

References encoding, pg_char_to_encoding(), PG_SQL_ASCII, and generate_unaccent_rules::str.

Referenced by main().

◆ pqFlush()

int pqFlush ( PGconn conn)

Definition at line 954 of file fe-misc.c.

955 {
956  if (conn->outCount > 0)
957  {
958  if (conn->Pfdebug)
959  fflush(conn->Pfdebug);
960 
961  return pqSendSome(conn, conn->outCount);
962  }
963 
964  return 0;
965 }
static int pqSendSome(PGconn *conn, int len)
Definition: fe-misc.c:785
static void const char fflush(stdout)
FILE * Pfdebug
Definition: libpq-int.h:413
int outCount
Definition: libpq-int.h:517

References conn, fflush(), pg_conn::outCount, pg_conn::Pfdebug, and pqSendSome().

Referenced by pg_SASL_init(), PQconnectPoll(), PQconsumeInput(), pqEndcopy3(), PQexitPipelineMode(), PQflush(), pqFunctionCall3(), PQgetResult(), pqPacketSend(), pqPipelineFlush(), PQputCopyData(), PQputCopyEnd(), PQsendQueryInternal(), PQsetnonblocking(), and sendTerminateConn().

◆ pqGetc()

int pqGetc ( char *  result,
PGconn conn 
)

Definition at line 78 of file fe-misc.c.

79 {
80  if (conn->inCursor >= conn->inEnd)
81  return EOF;
82 
83  *result = conn->inBuffer[conn->inCursor++];
84 
85  return 0;
86 }

References conn, pg_conn::inBuffer, pg_conn::inCursor, and pg_conn::inEnd.

Referenced by getCopyDataMessage(), getCopyStart(), getReadyForQuery(), PQconnectPoll(), pqFunctionCall3(), pqGetErrorNotice3(), and pqParseInput3().

◆ pqGetInt()

int pqGetInt ( int *  result,
size_t  bytes,
PGconn conn 
)

Definition at line 217 of file fe-misc.c.

218 {
219  uint16 tmp2;
220  uint32 tmp4;
221 
222  switch (bytes)
223  {
224  case 2:
225  if (conn->inCursor + 2 > conn->inEnd)
226  return EOF;
227  memcpy(&tmp2, conn->inBuffer + conn->inCursor, 2);
228  conn->inCursor += 2;
229  *result = (int) pg_ntoh16(tmp2);
230  break;
231  case 4:
232  if (conn->inCursor + 4 > conn->inEnd)
233  return EOF;
234  memcpy(&tmp4, conn->inBuffer + conn->inCursor, 4);
235  conn->inCursor += 4;
236  *result = (int) pg_ntoh32(tmp4);
237  break;
238  default:
240  "integer of size %lu not supported by pqGetInt",
241  (unsigned long) bytes);
242  return EOF;
243  }
244 
245  return 0;
246 }
unsigned short uint16
Definition: c.h:494
unsigned int uint32
Definition: c.h:495
void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
Definition: fe-exec.c:933
#define pg_ntoh32(x)
Definition: pg_bswap.h:125
#define pg_ntoh16(x)
Definition: pg_bswap.h:124
PGNoticeHooks noticeHooks
Definition: libpq-int.h:417

References conn, pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inEnd, pg_conn::noticeHooks, pg_ntoh16, pg_ntoh32, and pqInternalNotice().

Referenced by getAnotherTuple(), getCopyDataMessage(), getCopyStart(), getNotify(), getParamDescriptions(), getRowDescriptions(), PQconnectPoll(), pqFunctionCall3(), pqGetNegotiateProtocolVersion3(), and pqParseInput3().

◆ pqGetnchar()

int pqGetnchar ( char *  s,
size_t  len,
PGconn conn 
)

Definition at line 166 of file fe-misc.c.

167 {
168  if (len > (size_t) (conn->inEnd - conn->inCursor))
169  return EOF;
170 
171  memcpy(s, conn->inBuffer + conn->inCursor, len);
172  /* no terminating null */
173 
174  conn->inCursor += len;
175 
176  return 0;
177 }
const void size_t len

References conn, pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inEnd, and len.

Referenced by pg_password_sendauth(), pg_SASL_continue(), and pqFunctionCall3().

◆ pqGets()

int pqGets ( PQExpBuffer  buf,
PGconn conn 
)

Definition at line 137 of file fe-misc.c.

138 {
139  return pqGets_internal(buf, conn, true);
140 }
static int pqGets_internal(PQExpBuffer buf, PGconn *conn, bool resetbuffer)
Definition: fe-misc.c:110
static char * buf
Definition: pg_test_fsync.c:67

References buf, conn, and pqGets_internal().

Referenced by getNotify(), getParameterStatus(), getRowDescriptions(), pg_SASL_init(), pqGetErrorNotice3(), pqGetNegotiateProtocolVersion3(), and pqParseInput3().

◆ pqGets_append()

int pqGets_append ( PQExpBuffer  buf,
PGconn conn 
)

Definition at line 143 of file fe-misc.c.

144 {
145  return pqGets_internal(buf, conn, false);
146 }

References buf, conn, and pqGets_internal().

Referenced by PQconnectPoll().

◆ pqGets_internal()

static int pqGets_internal ( PQExpBuffer  buf,
PGconn conn,
bool  resetbuffer 
)
static

Definition at line 110 of file fe-misc.c.

111 {
112  /* Copy conn data to locals for faster search loop */
113  char *inBuffer = conn->inBuffer;
114  int inCursor = conn->inCursor;
115  int inEnd = conn->inEnd;
116  int slen;
117 
118  while (inCursor < inEnd && inBuffer[inCursor])
119  inCursor++;
120 
121  if (inCursor >= inEnd)
122  return EOF;
123 
124  slen = inCursor - conn->inCursor;
125 
126  if (resetbuffer)
128 
129  appendBinaryPQExpBuffer(buf, inBuffer + conn->inCursor, slen);
130 
131  conn->inCursor = ++inCursor;
132 
133  return 0;
134 }
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:146
void appendBinaryPQExpBuffer(PQExpBuffer str, const char *data, size_t datalen)
Definition: pqexpbuffer.c:397

References appendBinaryPQExpBuffer(), buf, conn, pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inEnd, and resetPQExpBuffer().

Referenced by pqGets(), and pqGets_append().

◆ PQlibVersion()

int PQlibVersion ( void  )

Definition at line 64 of file fe-misc.c.

65 {
66  return PG_VERSION_NUM;
67 }

◆ PQmblen()

int PQmblen ( const char *  s,
int  encoding 
)

Definition at line 1177 of file fe-misc.c.

1178 {
1179  return pg_encoding_mblen(encoding, s);
1180 }
int pg_encoding_mblen(int encoding, const char *mbstr)
Definition: wchar.c:2130

References encoding, and pg_encoding_mblen().

Referenced by appendStringLiteral(), get_prompt(), pg_wcsformat(), pg_wcssize(), pg_wcswidth(), and strlen_max_width().

◆ PQmblenBounded()

int PQmblenBounded ( const char *  s,
int  encoding 
)

Definition at line 1187 of file fe-misc.c.

1188 {
1189  return strnlen(s, pg_encoding_mblen(encoding, s));
1190 }
size_t strnlen(const char *str, size_t maxlen)
Definition: strnlen.c:26

References encoding, pg_encoding_mblen(), and strnlen().

Referenced by command_no_begin(), do_field(), is_select_command(), patternToSQLRegex(), quote_if_needed(), reportErrorPosition(), skip_white_space(), splitTableColumnsSpec(), strip_quotes(), and strtokx().

◆ pqPutc()

int pqPutc ( char  c,
PGconn conn 
)

Definition at line 93 of file fe-misc.c.

94 {
95  if (pqPutMsgBytes(&c, 1, conn))
96  return EOF;
97 
98  return 0;
99 }
static int pqPutMsgBytes(const void *buf, size_t len, PGconn *conn)
Definition: fe-misc.c:495
char * c

References conn, and pqPutMsgBytes().

Referenced by PQsendQueryGuts(), and PQsendTypedCommand().

◆ pqPutInt()

int pqPutInt ( int  value,
size_t  bytes,
PGconn conn 
)

Definition at line 254 of file fe-misc.c.

255 {
256  uint16 tmp2;
257  uint32 tmp4;
258 
259  switch (bytes)
260  {
261  case 2:
262  tmp2 = pg_hton16((uint16) value);
263  if (pqPutMsgBytes((const char *) &tmp2, 2, conn))
264  return EOF;
265  break;
266  case 4:
267  tmp4 = pg_hton32((uint32) value);
268  if (pqPutMsgBytes((const char *) &tmp4, 4, conn))
269  return EOF;
270  break;
271  default:
273  "integer of size %lu not supported by pqPutInt",
274  (unsigned long) bytes);
275  return EOF;
276  }
277 
278  return 0;
279 }
static struct @148 value
#define pg_hton32(x)
Definition: pg_bswap.h:121
#define pg_hton16(x)
Definition: pg_bswap.h:120

References conn, pg_conn::noticeHooks, pg_hton16, pg_hton32, pqInternalNotice(), pqPutMsgBytes(), and value.

Referenced by pg_SASL_init(), pqFunctionCall3(), PQsendPrepare(), and PQsendQueryGuts().

◆ pqPutMsgBytes()

static int pqPutMsgBytes ( const void *  buf,
size_t  len,
PGconn conn 
)
static

Definition at line 495 of file fe-misc.c.

496 {
497  /* make sure there is room for it */
499  return EOF;
500  /* okay, save the data */
501  memcpy(conn->outBuffer + conn->outMsgEnd, buf, len);
502  conn->outMsgEnd += len;
503  /* no Pfdebug call here, caller should do it */
504  return 0;
505 }
int pqCheckOutBufferSpace(size_t bytes_needed, PGconn *conn)
Definition: fe-misc.c:288
int outMsgEnd
Definition: libpq-int.h:522

References buf, conn, len, pg_conn::outBuffer, pg_conn::outMsgEnd, and pqCheckOutBufferSpace().

Referenced by pqPutc(), pqPutInt(), pqPutnchar(), and pqPuts().

◆ pqPutMsgEnd()

int pqPutMsgEnd ( PGconn conn)

Definition at line 518 of file fe-misc.c.

519 {
520  /* Fill in length word if needed */
521  if (conn->outMsgStart >= 0)
522  {
523  uint32 msgLen = conn->outMsgEnd - conn->outMsgStart;
524 
525  msgLen = pg_hton32(msgLen);
526  memcpy(conn->outBuffer + conn->outMsgStart, &msgLen, 4);
527  }
528 
529  /* trace client-to-server message */
530  if (conn->Pfdebug)
531  {
532  if (conn->outCount < conn->outMsgStart)
534  else
537  }
538 
539  /* Make message eligible to send */
541 
542  if (conn->outCount >= 8192)
543  {
544  int toSend = conn->outCount - (conn->outCount % 8192);
545 
546  if (pqSendSome(conn, toSend) < 0)
547  return EOF;
548  /* in nonblock mode, don't complain if unable to send it all */
549  }
550 
551  return 0;
552 }
void pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer)
Definition: fe-trace.c:529
void pqTraceOutputNoTypeByteMessage(PGconn *conn, const char *message)
Definition: fe-trace.c:704
int outMsgStart
Definition: libpq-int.h:520

References conn, pg_conn::outBuffer, pg_conn::outCount, pg_conn::outMsgEnd, pg_conn::outMsgStart, pg_conn::Pfdebug, pg_hton32, pqSendSome(), pqTraceOutputMessage(), and pqTraceOutputNoTypeByteMessage().

Referenced by pg_SASL_init(), pqEndcopy3(), pqFunctionCall3(), pqPacketSend(), PQpipelineSync(), PQputCopyData(), PQputCopyEnd(), PQsendFlushRequest(), PQsendPrepare(), PQsendQueryGuts(), PQsendQueryInternal(), PQsendTypedCommand(), and sendTerminateConn().

◆ pqPutMsgStart()

int pqPutMsgStart ( char  msg_type,
PGconn conn 
)

Definition at line 459 of file fe-misc.c.

460 {
461  int lenPos;
462  int endPos;
463 
464  /* allow room for message type byte */
465  if (msg_type)
466  endPos = conn->outCount + 1;
467  else
468  endPos = conn->outCount;
469 
470  /* do we want a length word? */
471  lenPos = endPos;
472  /* allow room for message length */
473  endPos += 4;
474 
475  /* make sure there is room for message header */
476  if (pqCheckOutBufferSpace(endPos, conn))
477  return EOF;
478  /* okay, save the message type byte if any */
479  if (msg_type)
480  conn->outBuffer[conn->outCount] = msg_type;
481  /* set up the message pointers */
482  conn->outMsgStart = lenPos;
483  conn->outMsgEnd = endPos;
484  /* length word, if needed, will be filled in by pqPutMsgEnd */
485 
486  return 0;
487 }

References conn, pg_conn::outBuffer, pg_conn::outCount, pg_conn::outMsgEnd, pg_conn::outMsgStart, and pqCheckOutBufferSpace().

Referenced by pg_SASL_init(), pqEndcopy3(), pqFunctionCall3(), pqPacketSend(), PQpipelineSync(), PQputCopyData(), PQputCopyEnd(), PQsendFlushRequest(), PQsendPrepare(), PQsendQueryGuts(), PQsendQueryInternal(), PQsendTypedCommand(), and sendTerminateConn().

◆ pqPutnchar()

int pqPutnchar ( const char *  s,
size_t  len,
PGconn conn 
)

Definition at line 203 of file fe-misc.c.

204 {
205  if (pqPutMsgBytes(s, len, conn))
206  return EOF;
207 
208  return 0;
209 }

References conn, len, and pqPutMsgBytes().

Referenced by pg_SASL_init(), pqFunctionCall3(), pqPacketSend(), PQputCopyData(), and PQsendQueryGuts().

◆ pqPuts()

int pqPuts ( const char *  s,
PGconn conn 
)

Definition at line 153 of file fe-misc.c.

154 {
155  if (pqPutMsgBytes(s, strlen(s) + 1, conn))
156  return EOF;
157 
158  return 0;
159 }

References conn, and pqPutMsgBytes().

Referenced by pg_SASL_init(), PQputCopyEnd(), PQsendPrepare(), PQsendQueryGuts(), PQsendQueryInternal(), and PQsendTypedCommand().

◆ pqReadData()

int pqReadData ( PGconn conn)

Definition at line 566 of file fe-misc.c.

567 {
568  int someread = 0;
569  int nread;
570 
571  if (conn->sock == PGINVALID_SOCKET)
572  {
573  libpq_append_conn_error(conn, "connection not open");
574  return -1;
575  }
576 
577  /* Left-justify any data in the buffer to make room */
578  if (conn->inStart < conn->inEnd)
579  {
580  if (conn->inStart > 0)
581  {
582  memmove(conn->inBuffer, conn->inBuffer + conn->inStart,
583  conn->inEnd - conn->inStart);
584  conn->inEnd -= conn->inStart;
585  conn->inCursor -= conn->inStart;
586  conn->inStart = 0;
587  }
588  }
589  else
590  {
591  /* buffer is logically empty, reset it */
592  conn->inStart = conn->inCursor = conn->inEnd = 0;
593  }
594 
595  /*
596  * If the buffer is fairly full, enlarge it. We need to be able to enlarge
597  * the buffer in case a single message exceeds the initial buffer size. We
598  * enlarge before filling the buffer entirely so as to avoid asking the
599  * kernel for a partial packet. The magic constant here should be large
600  * enough for a TCP packet or Unix pipe bufferload. 8K is the usual pipe
601  * buffer size, so...
602  */
603  if (conn->inBufSize - conn->inEnd < 8192)
604  {
605  if (pqCheckInBufferSpace(conn->inEnd + (size_t) 8192, conn))
606  {
607  /*
608  * We don't insist that the enlarge worked, but we need some room
609  */
610  if (conn->inBufSize - conn->inEnd < 100)
611  return -1; /* errorMessage already set */
612  }
613  }
614 
615  /* OK, try to read some data */
616 retry3:
617  nread = pqsecure_read(conn, conn->inBuffer + conn->inEnd,
618  conn->inBufSize - conn->inEnd);
619  if (nread < 0)
620  {
621  switch (SOCK_ERRNO)
622  {
623  case EINTR:
624  goto retry3;
625 
626  /* Some systems return EAGAIN/EWOULDBLOCK for no data */
627 #ifdef EAGAIN
628  case EAGAIN:
629  return someread;
630 #endif
631 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
632  case EWOULDBLOCK:
633  return someread;
634 #endif
635 
636  /* We might get ECONNRESET etc here if connection failed */
638  goto definitelyFailed;
639 
640  default:
641  /* pqsecure_read set the error message for us */
642  return -1;
643  }
644  }
645  if (nread > 0)
646  {
647  conn->inEnd += nread;
648 
649  /*
650  * Hack to deal with the fact that some kernels will only give us back
651  * 1 packet per recv() call, even if we asked for more and there is
652  * more available. If it looks like we are reading a long message,
653  * loop back to recv() again immediately, until we run out of data or
654  * buffer space. Without this, the block-and-restart behavior of
655  * libpq's higher levels leads to O(N^2) performance on long messages.
656  *
657  * Since we left-justified the data above, conn->inEnd gives the
658  * amount of data already read in the current message. We consider
659  * the message "long" once we have acquired 32k ...
660  */
661  if (conn->inEnd > 32768 &&
662  (conn->inBufSize - conn->inEnd) >= 8192)
663  {
664  someread = 1;
665  goto retry3;
666  }
667  return 1;
668  }
669 
670  if (someread)
671  return 1; /* got a zero read after successful tries */
672 
673  /*
674  * A return value of 0 could mean just that no data is now available, or
675  * it could mean EOF --- that is, the server has closed the connection.
676  * Since we have the socket in nonblock mode, the only way to tell the
677  * difference is to see if select() is saying that the file is ready.
678  * Grumble. Fortunately, we don't expect this path to be taken much,
679  * since in normal practice we should not be trying to read data unless
680  * the file selected for reading already.
681  *
682  * In SSL mode it's even worse: SSL_read() could say WANT_READ and then
683  * data could arrive before we make the pqReadReady() test, but the second
684  * SSL_read() could still say WANT_READ because the data received was not
685  * a complete SSL record. So we must play dumb and assume there is more
686  * data, relying on the SSL layer to detect true EOF.
687  */
688 
689 #ifdef USE_SSL
690  if (conn->ssl_in_use)
691  return 0;
692 #endif
693 
694  switch (pqReadReady(conn))
695  {
696  case 0:
697  /* definitely no data available */
698  return 0;
699  case 1:
700  /* ready for read */
701  break;
702  default:
703  /* we override pqReadReady's message with something more useful */
704  goto definitelyEOF;
705  }
706 
707  /*
708  * Still not sure that it's EOF, because some data could have just
709  * arrived.
710  */
711 retry4:
712  nread = pqsecure_read(conn, conn->inBuffer + conn->inEnd,
713  conn->inBufSize - conn->inEnd);
714  if (nread < 0)
715  {
716  switch (SOCK_ERRNO)
717  {
718  case EINTR:
719  goto retry4;
720 
721  /* Some systems return EAGAIN/EWOULDBLOCK for no data */
722 #ifdef EAGAIN
723  case EAGAIN:
724  return 0;
725 #endif
726 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
727  case EWOULDBLOCK:
728  return 0;
729 #endif
730 
731  /* We might get ECONNRESET etc here if connection failed */
733  goto definitelyFailed;
734 
735  default:
736  /* pqsecure_read set the error message for us */
737  return -1;
738  }
739  }
740  if (nread > 0)
741  {
742  conn->inEnd += nread;
743  return 1;
744  }
745 
746  /*
747  * OK, we are getting a zero read even though select() says ready. This
748  * means the connection has been closed. Cope.
749  */
750 definitelyEOF:
751  libpq_append_conn_error(conn, "server closed the connection unexpectedly\n"
752  "\tThis probably means the server terminated abnormally\n"
753  "\tbefore or while processing the request.");
754 
755  /* Come here if lower-level code already set a suitable errorMessage */
756 definitelyFailed:
757  /* Do *not* drop any already-read data; caller still wants it */
758  pqDropConnection(conn, false);
759  conn->status = CONNECTION_BAD; /* No more connection to backend */
760  return -1;
761 }
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:467
int pqReadReady(PGconn *conn)
Definition: fe-misc.c:1015
int pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn)
Definition: fe-misc.c:352
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
Definition: fe-misc.c:1312
ssize_t pqsecure_read(PGconn *conn, void *ptr, size_t len)
Definition: fe-secure.c:182
@ CONNECTION_BAD
Definition: libpq-fe.h:61
#define SOCK_ERRNO
Definition: libpq-int.h:921
#define ALL_CONNECTION_FAILURE_ERRNOS
Definition: port.h:121
#define PGINVALID_SOCKET
Definition: port.h:31
pgsocket sock
Definition: libpq-int.h:459
bool ssl_in_use
Definition: libpq-int.h:547
ConnStatusType status
Definition: libpq-int.h:425
#define EINTR
Definition: win32_port.h:374
#define EWOULDBLOCK
Definition: win32_port.h:380
#define EAGAIN
Definition: win32_port.h:372

References ALL_CONNECTION_FAILURE_ERRNOS, conn, CONNECTION_BAD, EAGAIN, EINTR, EWOULDBLOCK, pg_conn::inBuffer, pg_conn::inBufSize, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, libpq_append_conn_error(), PGINVALID_SOCKET, pqCheckInBufferSpace(), pqDropConnection(), pqReadReady(), pqsecure_read(), pg_conn::sock, SOCK_ERRNO, pg_conn::ssl_in_use, and pg_conn::status.

Referenced by PQconnectPoll(), PQconsumeInput(), pqFunctionCall3(), pqGetCopyData3(), pqGetline3(), PQgetResult(), and pqSendSome().

◆ pqReadReady()

int pqReadReady ( PGconn conn)

Definition at line 1015 of file fe-misc.c.

1016 {
1017  return pqSocketCheck(conn, 1, 0, (time_t) 0);
1018 }
static int pqSocketCheck(PGconn *conn, int forRead, int forWrite, time_t end_time)
Definition: fe-misc.c:1039

References conn, and pqSocketCheck().

Referenced by gss_read(), and pqReadData().

◆ pqSendSome()

static int pqSendSome ( PGconn conn,
int  len 
)
static

Definition at line 785 of file fe-misc.c.

786 {
787  char *ptr = conn->outBuffer;
788  int remaining = conn->outCount;
789  int result = 0;
790 
791  /*
792  * If we already had a write failure, we will never again try to send data
793  * on that connection. Even if the kernel would let us, we've probably
794  * lost message boundary sync with the server. conn->write_failed
795  * therefore persists until the connection is reset, and we just discard
796  * all data presented to be written. However, as long as we still have a
797  * valid socket, we should continue to absorb data from the backend, so
798  * that we can collect any final error messages.
799  */
800  if (conn->write_failed)
801  {
802  /* conn->write_err_msg should be set up already */
803  conn->outCount = 0;
804  /* Absorb input data if any, and detect socket closure */
805  if (conn->sock != PGINVALID_SOCKET)
806  {
807  if (pqReadData(conn) < 0)
808  return -1;
809  }
810  return 0;
811  }
812 
813  if (conn->sock == PGINVALID_SOCKET)
814  {
815  conn->write_failed = true;
816  /* Store error message in conn->write_err_msg, if possible */
817  /* (strdup failure is OK, we'll cope later) */
818  conn->write_err_msg = strdup(libpq_gettext("connection not open\n"));
819  /* Discard queued data; no chance it'll ever be sent */
820  conn->outCount = 0;
821  return 0;
822  }
823 
824  /* while there's still data to send */
825  while (len > 0)
826  {
827  int sent;
828 
829 #ifndef WIN32
830  sent = pqsecure_write(conn, ptr, len);
831 #else
832 
833  /*
834  * Windows can fail on large sends, per KB article Q201213. The
835  * failure-point appears to be different in different versions of
836  * Windows, but 64k should always be safe.
837  */
838  sent = pqsecure_write(conn, ptr, Min(len, 65536));
839 #endif
840 
841  if (sent < 0)
842  {
843  /* Anything except EAGAIN/EWOULDBLOCK/EINTR is trouble */
844  switch (SOCK_ERRNO)
845  {
846 #ifdef EAGAIN
847  case EAGAIN:
848  break;
849 #endif
850 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
851  case EWOULDBLOCK:
852  break;
853 #endif
854  case EINTR:
855  continue;
856 
857  default:
858  /* Discard queued data; no chance it'll ever be sent */
859  conn->outCount = 0;
860 
861  /* Absorb input data if any, and detect socket closure */
862  if (conn->sock != PGINVALID_SOCKET)
863  {
864  if (pqReadData(conn) < 0)
865  return -1;
866  }
867 
868  /*
869  * Lower-level code should already have filled
870  * conn->write_err_msg (and set conn->write_failed) or
871  * conn->errorMessage. In the former case, we pretend
872  * there's no problem; the write_failed condition will be
873  * dealt with later. Otherwise, report the error now.
874  */
875  if (conn->write_failed)
876  return 0;
877  else
878  return -1;
879  }
880  }
881  else
882  {
883  ptr += sent;
884  len -= sent;
885  remaining -= sent;
886  }
887 
888  if (len > 0)
889  {
890  /*
891  * We didn't send it all, wait till we can send more.
892  *
893  * There are scenarios in which we can't send data because the
894  * communications channel is full, but we cannot expect the server
895  * to clear the channel eventually because it's blocked trying to
896  * send data to us. (This can happen when we are sending a large
897  * amount of COPY data, and the server has generated lots of
898  * NOTICE responses.) To avoid a deadlock situation, we must be
899  * prepared to accept and buffer incoming data before we try
900  * again. Furthermore, it is possible that such incoming data
901  * might not arrive until after we've gone to sleep. Therefore,
902  * we wait for either read ready or write ready.
903  *
904  * In non-blocking mode, we don't wait here directly, but return 1
905  * to indicate that data is still pending. The caller should wait
906  * for both read and write ready conditions, and call
907  * PQconsumeInput() on read ready, but just in case it doesn't, we
908  * call pqReadData() ourselves before returning. That's not
909  * enough if the data has not arrived yet, but it's the best we
910  * can do, and works pretty well in practice. (The documentation
911  * used to say that you only need to wait for write-ready, so
912  * there are still plenty of applications like that out there.)
913  *
914  * Note that errors here don't result in write_failed becoming
915  * set.
916  */
917  if (pqReadData(conn) < 0)
918  {
919  result = -1; /* error message already set up */
920  break;
921  }
922 
923  if (pqIsnonblocking(conn))
924  {
925  result = 1;
926  break;
927  }
928 
929  if (pqWait(true, true, conn))
930  {
931  result = -1;
932  break;
933  }
934  }
935  }
936 
937  /* shift the remaining contents of the buffer */
938  if (remaining > 0)
939  memmove(conn->outBuffer, ptr, remaining);
941 
942  return result;
943 }
#define Min(x, y)
Definition: c.h:993
int pqReadData(PGconn *conn)
Definition: fe-misc.c:566
int pqWait(int forRead, int forWrite, PGconn *conn)
Definition: fe-misc.c:979
ssize_t pqsecure_write(PGconn *conn, const void *ptr, size_t len)
Definition: fe-secure.c:275
int remaining
Definition: informix.c:667
#define pqIsnonblocking(conn)
Definition: libpq-int.h:889
char * write_err_msg
Definition: libpq-int.h:471
bool write_failed
Definition: libpq-int.h:470

References conn, EAGAIN, EINTR, EWOULDBLOCK, len, libpq_gettext, Min, pg_conn::outBuffer, pg_conn::outCount, PGINVALID_SOCKET, pqIsnonblocking, pqReadData(), pqsecure_write(), pqWait(), remaining, pg_conn::sock, SOCK_ERRNO, pg_conn::write_err_msg, and pg_conn::write_failed.

Referenced by pqFlush(), and pqPutMsgEnd().

◆ pqSkipnchar()

int pqSkipnchar ( size_t  len,
PGconn conn 
)

Definition at line 188 of file fe-misc.c.

189 {
190  if (len > (size_t) (conn->inEnd - conn->inCursor))
191  return EOF;
192 
193  conn->inCursor += len;
194 
195  return 0;
196 }

References conn, pg_conn::inCursor, pg_conn::inEnd, and len.

Referenced by getAnotherTuple().

◆ pqSocketCheck()

static int pqSocketCheck ( PGconn conn,
int  forRead,
int  forWrite,
time_t  end_time 
)
static

Definition at line 1039 of file fe-misc.c.

1040 {
1041  int result;
1042 
1043  if (!conn)
1044  return -1;
1045  if (conn->sock == PGINVALID_SOCKET)
1046  {
1047  libpq_append_conn_error(conn, "invalid socket");
1048  return -1;
1049  }
1050 
1051 #ifdef USE_SSL
1052  /* Check for SSL library buffering read bytes */
1053  if (forRead && conn->ssl_in_use && pgtls_read_pending(conn))
1054  {
1055  /* short-circuit the select */
1056  return 1;
1057  }
1058 #endif
1059 
1060  /* We will retry as long as we get EINTR */
1061  do
1062  result = pqSocketPoll(conn->sock, forRead, forWrite, end_time);
1063  while (result < 0 && SOCK_ERRNO == EINTR);
1064 
1065  if (result < 0)
1066  {
1067  char sebuf[PG_STRERROR_R_BUFLEN];
1068 
1069  libpq_append_conn_error(conn, "%s() failed: %s", "select",
1070  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
1071  }
1072 
1073  return result;
1074 }
static int pqSocketPoll(int sock, int forRead, int forWrite, time_t end_time)
Definition: fe-misc.c:1087
bool pgtls_read_pending(PGconn *conn)
#define SOCK_STRERROR
Definition: libpq-int.h:922
int64 end_time
Definition: pgbench.c:175
#define PG_STRERROR_R_BUFLEN
Definition: port.h:256

References conn, EINTR, end_time, libpq_append_conn_error(), PG_STRERROR_R_BUFLEN, PGINVALID_SOCKET, pgtls_read_pending(), pqSocketPoll(), pg_conn::sock, SOCK_ERRNO, SOCK_STRERROR, and pg_conn::ssl_in_use.

Referenced by pqReadReady(), pqWaitTimed(), and pqWriteReady().

◆ pqSocketPoll()

static int pqSocketPoll ( int  sock,
int  forRead,
int  forWrite,
time_t  end_time 
)
static

Definition at line 1087 of file fe-misc.c.

1088 {
1089  /* We use poll(2) if available, otherwise select(2) */
1090 #ifdef HAVE_POLL
1091  struct pollfd input_fd;
1092  int timeout_ms;
1093 
1094  if (!forRead && !forWrite)
1095  return 0;
1096 
1097  input_fd.fd = sock;
1098  input_fd.events = POLLERR;
1099  input_fd.revents = 0;
1100 
1101  if (forRead)
1102  input_fd.events |= POLLIN;
1103  if (forWrite)
1104  input_fd.events |= POLLOUT;
1105 
1106  /* Compute appropriate timeout interval */
1107  if (end_time == ((time_t) -1))
1108  timeout_ms = -1;
1109  else
1110  {
1111  time_t now = time(NULL);
1112 
1113  if (end_time > now)
1114  timeout_ms = (end_time - now) * 1000;
1115  else
1116  timeout_ms = 0;
1117  }
1118 
1119  return poll(&input_fd, 1, timeout_ms);
1120 #else /* !HAVE_POLL */
1121 
1122  fd_set input_mask;
1123  fd_set output_mask;
1124  fd_set except_mask;
1125  struct timeval timeout;
1126  struct timeval *ptr_timeout;
1127 
1128  if (!forRead && !forWrite)
1129  return 0;
1130 
1131  FD_ZERO(&input_mask);
1132  FD_ZERO(&output_mask);
1133  FD_ZERO(&except_mask);
1134  if (forRead)
1135  FD_SET(sock, &input_mask);
1136 
1137  if (forWrite)
1138  FD_SET(sock, &output_mask);
1139  FD_SET(sock, &except_mask);
1140 
1141  /* Compute appropriate timeout interval */
1142  if (end_time == ((time_t) -1))
1143  ptr_timeout = NULL;
1144  else
1145  {
1146  time_t now = time(NULL);
1147 
1148  if (end_time > now)
1149  timeout.tv_sec = end_time - now;
1150  else
1151  timeout.tv_sec = 0;
1152  timeout.tv_usec = 0;
1153  ptr_timeout = &timeout;
1154  }
1155 
1156  return select(sock + 1, &input_mask, &output_mask,
1157  &except_mask, ptr_timeout);
1158 #endif /* HAVE_POLL */
1159 }
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1547
#define select(n, r, w, e, timeout)
Definition: win32_port.h:495

References end_time, now(), and select.

Referenced by pqSocketCheck().

◆ pqWait()

int pqWait ( int  forRead,
int  forWrite,
PGconn conn 
)

Definition at line 979 of file fe-misc.c.

980 {
981  return pqWaitTimed(forRead, forWrite, conn, (time_t) -1);
982 }
int pqWaitTimed(int forRead, int forWrite, PGconn *conn, time_t finish_time)
Definition: fe-misc.c:992

References conn, and pqWaitTimed().

Referenced by pqFunctionCall3(), pqGetCopyData3(), pqGetline3(), PQgetResult(), and pqSendSome().

◆ pqWaitTimed()

int pqWaitTimed ( int  forRead,
int  forWrite,
PGconn conn,
time_t  finish_time 
)

Definition at line 992 of file fe-misc.c.

993 {
994  int result;
995 
996  result = pqSocketCheck(conn, forRead, forWrite, finish_time);
997 
998  if (result < 0)
999  return -1; /* errorMessage is already set */
1000 
1001  if (result == 0)
1002  {
1003  libpq_append_conn_error(conn, "timeout expired");
1004  return 1;
1005  }
1006 
1007  return 0;
1008 }

References conn, libpq_append_conn_error(), and pqSocketCheck().

Referenced by connectDBComplete(), and pqWait().

◆ pqWriteReady()

int pqWriteReady ( PGconn conn)

Definition at line 1025 of file fe-misc.c.

1026 {
1027  return pqSocketCheck(conn, 0, 1, (time_t) 0);
1028 }

References conn, and pqSocketCheck().