Re: libpq sockets on win32 - Mailing list pgsql-interfaces

From Bruce Momjian
Subject Re: libpq sockets on win32
Date
Msg-id 200106042002.f54K20L06218@candle.pha.pa.us
Whole thread Raw
In response to RE: libpq sockets on win32  ("Jeff Johnson" <jeff@jeffjohnson.net>)
List pgsql-interfaces
> > I have done exactly that.  I assume fcntl(), ioctl(),
> > select() use errno
> > even if used on a socket, while getsockopt(), setsockopt(),
> socket(),
> > connect(), getsockname(), send(), recv() use WSAGetLastError.  Is
> this
> > list correct?
>
> I don't know enough about such things.

The web page wasn't clear about that.

> >
> > The patch is attached.  Please let me know so I can finalize it and
> > apply it.
>
> Couple of changes required to compile on Win32:
>
> Change:
> #define sockerrno WSAGetLastError
> To:
> #define sockerrno WSAGetLastError()
>

OK.

>
> This has to go back into fe-connect.c, EINPROGRESS isn't defined in
> Win32 for some reason..
> #ifndef WIN32
>         if (errno == EINPROGRESS || errno == 0)
> #else
>         if (WSAGetLastError() == WSAEINPROGRESS)
> #endif
>

OK.  Not sure why it wasn't defined, but, oh well.

>
>
> I tested it out but I'm getting this error when sending a large SQL
> statement (>16k).
>     cu.execute(sql)
>   File "c:\python20\pgdb.py", line 189, in execute
>     self.executemany(operation, (params,))
>   File "c:\python20\pgdb.py", line 204, in executemany
>     rows = self.__source.execute(sql)
> ValueError: pqReadData() --  read() failed: errno=10035
> Unknown error

That errno is very high, 10035.  If I take a look at my sys/errno.h on
BSD/OS, I see:

    #define EAGAIN      35      /* Resource temporarily unavailable */

so my guess is that WSAGetLastError() returns errno plus 10,000.  What
value does your include file set for EAGAIN, 10035 or 35.  If it is 35,
the following patch may work.  It has all your suggested fixes.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026
Index: src/interfaces/libpq/fe-connect.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v
retrieving revision 1.164
diff -c -r1.164 fe-connect.c
*** src/interfaces/libpq/fe-connect.c    2001/03/31 23:14:37    1.164
--- src/interfaces/libpq/fe-connect.c    2001/06/04 19:18:14
***************
*** 735,741 ****
      {
          printfPQExpBuffer(&conn->errorMessage,
                   "connectNoDelay() -- setsockopt failed: errno=%d\n%s\n",
!                           errno, strerror(errno));
  #ifdef WIN32
          printf("Winsock error: %i\n", WSAGetLastError());
  #endif
--- 735,741 ----
      {
          printfPQExpBuffer(&conn->errorMessage,
                   "connectNoDelay() -- setsockopt failed: errno=%d\n%s\n",
!                           sockerrno, strerror(sockerrno));
  #ifdef WIN32
          printf("Winsock error: %i\n", WSAGetLastError());
  #endif
***************
*** 890,896 ****
          printfPQExpBuffer(&conn->errorMessage,
                            "connectDBStart() -- "
                            "socket() failed: errno=%d\n%s\n",
!                           errno, strerror(errno));
          goto connect_errReturn;
      }

--- 890,896 ----
          printfPQExpBuffer(&conn->errorMessage,
                            "connectDBStart() -- "
                            "socket() failed: errno=%d\n%s\n",
!                           sockerrno, strerror(sockerrno));
          goto connect_errReturn;
      }

***************
*** 950,956 ****
          else
          {
              /* Something's gone wrong */
!             connectFailureMessage(conn, "connectDBStart()", errno);
              goto connect_errReturn;
          }
      }
--- 946,952 ----
          else
          {
              /* Something's gone wrong */
!             connectFailureMessage(conn, "connectDBStart()", sockerrno);
              goto connect_errReturn;
          }
      }
***************
*** 970,983 ****
          {
              printfPQExpBuffer(&conn->errorMessage,
                                "connectDB() -- couldn't send SSL negotiation packet: errno=%d\n%s\n",
!                               errno, strerror(errno));
              goto connect_errReturn;
          }
          /* Now receive the postmasters response */
          if (recv(conn->sock, &SSLok, 1, 0) != 1)
          {
              printfPQExpBuffer(&conn->errorMessage, "PQconnectDB() -- couldn't read postmaster response:
errno=%d\n%s\n",
!                               errno, strerror(errno));
              goto connect_errReturn;
          }
          if (SSLok == 'S')
--- 966,979 ----
          {
              printfPQExpBuffer(&conn->errorMessage,
                                "connectDB() -- couldn't send SSL negotiation packet: errno=%d\n%s\n",
!                               sockerrno, strerror(sockerrno));
              goto connect_errReturn;
          }
          /* Now receive the postmasters response */
          if (recv(conn->sock, &SSLok, 1, 0) != 1)
          {
              printfPQExpBuffer(&conn->errorMessage, "PQconnectDB() -- couldn't read postmaster response:
errno=%d\n%s\n",
!                               sockerrno, strerror(sockerrno));
              goto connect_errReturn;
          }
          if (SSLok == 'S')
***************
*** 1233,1239 ****
                      printfPQExpBuffer(&conn->errorMessage,
                                 "PQconnectPoll() -- getsockopt() failed: "
                                        "errno=%d\n%s\n",
!                                       errno, strerror(errno));
                      goto error_return;
                  }
                  else if (optval != 0)
--- 1229,1235 ----
                      printfPQExpBuffer(&conn->errorMessage,
                                 "PQconnectPoll() -- getsockopt() failed: "
                                        "errno=%d\n%s\n",
!                                       sockerrno, strerror(sockerrno));
                      goto error_return;
                  }
                  else if (optval != 0)
***************
*** 1255,1261 ****
                      printfPQExpBuffer(&conn->errorMessage,
                                "PQconnectPoll() -- getsockname() failed: "
                                        "errno=%d\n%s\n",
!                                       errno, strerror(errno));
                      goto error_return;
                  }

--- 1251,1257 ----
                      printfPQExpBuffer(&conn->errorMessage,
                                "PQconnectPoll() -- getsockname() failed: "
                                        "errno=%d\n%s\n",
!                                       sockerrno, strerror(sockerrno));
                      goto error_return;
                  }

***************
*** 1296,1302 ****
                                        "PQconnectPoll() --  "
                                        "couldn't send startup packet: "
                                        "errno=%d\n%s\n",
!                                       errno, strerror(errno));
                      goto error_return;
                  }

--- 1292,1298 ----
                                        "PQconnectPoll() --  "
                                        "couldn't send startup packet: "
                                        "errno=%d\n%s\n",
!                                       sockerrno, strerror(sockerrno));
                      goto error_return;
                  }

***************
*** 2110,2116 ****
--- 2106,2114 ----
  int
  PQrequestCancel(PGconn *conn)
  {
+ #ifndef WIN32
      int            save_errno = errno;
+ #endif
      int            tmpsock = -1;
      struct
      {
***************
*** 2127,2133 ****
--- 2125,2133 ----
          strcpy(conn->errorMessage.data,
                 "PQrequestCancel() -- connection is not open\n");
          conn->errorMessage.len = strlen(conn->errorMessage.data);
+ #ifndef WIN32
          errno = save_errno;
+ #endif
          return FALSE;
      }

***************
*** 2173,2183 ****
      close(tmpsock);
  #endif

      errno = save_errno;
      return TRUE;

  cancel_errReturn:
!     strcat(conn->errorMessage.data, strerror(errno));
      strcat(conn->errorMessage.data, "\n");
      conn->errorMessage.len = strlen(conn->errorMessage.data);
      if (tmpsock >= 0)
--- 2173,2185 ----
      close(tmpsock);
  #endif

+ #ifndef WIN32
      errno = save_errno;
+ #endif
      return TRUE;

  cancel_errReturn:
!     strcat(conn->errorMessage.data, strerror(sockerrno));
      strcat(conn->errorMessage.data, "\n");
      conn->errorMessage.len = strlen(conn->errorMessage.data);
      if (tmpsock >= 0)
***************
*** 2188,2194 ****
--- 2190,2198 ----
          close(tmpsock);
  #endif
      }
+ #ifndef WIN32
      errno = save_errno;
+ #endif
      return FALSE;
  }

Index: src/interfaces/libpq/fe-misc.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v
retrieving revision 1.49
diff -c -r1.49 fe-misc.c
*** src/interfaces/libpq/fe-misc.c    2001/05/28 15:29:51    1.49
--- src/interfaces/libpq/fe-misc.c    2001/06/04 19:18:20
***************
*** 447,471 ****
                       conn->inBufSize - conn->inEnd, 0);
      if (nread < 0)
      {
!         if (errno == EINTR)
              goto tryAgain;
          /* Some systems return EAGAIN/EWOULDBLOCK for no data */
  #ifdef EAGAIN
!         if (errno == EAGAIN)
              return someread;
  #endif
  #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
!         if (errno == EWOULDBLOCK)
              return someread;
  #endif
          /* We might get ECONNRESET here if using TCP and backend died */
  #ifdef ECONNRESET
!         if (errno == ECONNRESET)
              goto definitelyFailed;
  #endif
          printfPQExpBuffer(&conn->errorMessage,
                          "pqReadData() --  read() failed: errno=%d\n%s\n",
!                           errno, strerror(errno));
          return -1;
      }
      if (nread > 0)
--- 447,471 ----
                       conn->inBufSize - conn->inEnd, 0);
      if (nread < 0)
      {
!         if (sockerrno == EINTR)
              goto tryAgain;
          /* Some systems return EAGAIN/EWOULDBLOCK for no data */
  #ifdef EAGAIN
!         if (sockerrno == EAGAIN)
              return someread;
  #endif
  #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
!         if (sockerrno == EWOULDBLOCK)
              return someread;
  #endif
          /* We might get ECONNRESET here if using TCP and backend died */
  #ifdef ECONNRESET
!         if (sockerrno == ECONNRESET)
              goto definitelyFailed;
  #endif
          printfPQExpBuffer(&conn->errorMessage,
                          "pqReadData() --  read() failed: errno=%d\n%s\n",
!                           sockerrno, strerror(sockerrno));
          return -1;
      }
      if (nread > 0)
***************
*** 533,557 ****
                       conn->inBufSize - conn->inEnd, 0);
      if (nread < 0)
      {
!         if (errno == EINTR)
              goto tryAgain2;
          /* Some systems return EAGAIN/EWOULDBLOCK for no data */
  #ifdef EAGAIN
!         if (errno == EAGAIN)
              return 0;
  #endif
  #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
!         if (errno == EWOULDBLOCK)
              return 0;
  #endif
          /* We might get ECONNRESET here if using TCP and backend died */
  #ifdef ECONNRESET
!         if (errno == ECONNRESET)
              goto definitelyFailed;
  #endif
          printfPQExpBuffer(&conn->errorMessage,
                          "pqReadData() --  read() failed: errno=%d\n%s\n",
!                           errno, strerror(errno));
          return -1;
      }
      if (nread > 0)
--- 533,557 ----
                       conn->inBufSize - conn->inEnd, 0);
      if (nread < 0)
      {
!         if (sockerrno == EINTR)
              goto tryAgain2;
          /* Some systems return EAGAIN/EWOULDBLOCK for no data */
  #ifdef EAGAIN
!         if (sockerrno == EAGAIN)
              return 0;
  #endif
  #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
!         if (sockerrno == EWOULDBLOCK)
              return 0;
  #endif
          /* We might get ECONNRESET here if using TCP and backend died */
  #ifdef ECONNRESET
!         if (sockerrno == ECONNRESET)
              goto definitelyFailed;
  #endif
          printfPQExpBuffer(&conn->errorMessage,
                          "pqReadData() --  read() failed: errno=%d\n%s\n",
!                           sockerrno, strerror(sockerrno));
          return -1;
      }
      if (nread > 0)
***************
*** 633,639 ****
               * EPIPE or ECONNRESET, assume we've lost the backend
               * connection permanently.
               */
!             switch (errno)
              {
  #ifdef EAGAIN
                  case EAGAIN:
--- 633,639 ----
               * EPIPE or ECONNRESET, assume we've lost the backend
               * connection permanently.
               */
!             switch (sockerrno)
              {
  #ifdef EAGAIN
                  case EAGAIN:
***************
*** 668,674 ****
                  default:
                      printfPQExpBuffer(&conn->errorMessage,
                        "pqFlush() --  couldn't send data: errno=%d\n%s\n",
!                                       errno, strerror(errno));
                      /* We don't assume it's a fatal error... */
                      return EOF;
              }
--- 668,674 ----
                  default:
                      printfPQExpBuffer(&conn->errorMessage,
                        "pqFlush() --  couldn't send data: errno=%d\n%s\n",
!                                       sockerrno, strerror(sockerrno));
                      /* We don't assume it's a fatal error... */
                      return EOF;
              }
Index: src/interfaces/libpq/libpq-int.h
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/libpq/libpq-int.h,v
retrieving revision 1.33
diff -c -r1.33 libpq-int.h
*** src/interfaces/libpq/libpq-int.h    2001/03/22 04:01:27    1.33
--- src/interfaces/libpq/libpq-int.h    2001/06/04 19:18:23
***************
*** 34,39 ****
--- 34,45 ----
  #include <openssl/err.h>
  #endif

+ #ifndef WIN32
+ #define sockerrno errno
+ #else
+ #define sockerrno (WSAGetLastError() - 10000)
+ #endif
+
  /* libpq supports this version of the frontend/backend protocol.
   *
   * NB: we used to use PG_PROTOCOL_LATEST from the backend pqcomm.h file,

pgsql-interfaces by date:

Previous
From: "Jeff Johnson"
Date:
Subject: RE: libpq sockets on win32
Next
From: "Jeff Johnson"
Date:
Subject: RE: libpq sockets on win32