On Windows, use pgwin32_waitforsinglesocket() instead of select() to wait for
authorTom Lane
Fri, 26 Jan 2007 20:06:52 +0000 (20:06 +0000)
committerTom Lane
Fri, 26 Jan 2007 20:06:52 +0000 (20:06 +0000)
input in the stats collector.  Our select() emulation is apparently buggy
for UDP sockets :-(.  This should resolve problems with stats collection
(and hence autovacuum) failing under more than minimal load.  Diagnosis
and patch by Magnus Hagander.

Patch probably needs to be back-ported to 8.1 and 8.0, but first let's
see if it makes the buildfarm happy...

src/backend/libpq/be-secure.c
src/backend/port/win32/socket.c
src/backend/postmaster/pgstat.c
src/include/port/win32.h

index 421c4b68ce4c4483d683a0c8d2d7c8eb1a4ca2d6..ac0196cead41f7c10412519b93085a887f8a4894 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/libpq/be-secure.c,v 1.75 2007/01/05 22:19:29 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/libpq/be-secure.c,v 1.76 2007/01/26 20:06:52 tgl Exp $
  *
  *   Since the server static private key ($DataDir/server.key)
  *   will normally be stored unencrypted so that the database
@@ -275,7 +275,8 @@ rloop:
 #ifdef WIN32
                pgwin32_waitforsinglesocket(SSL_get_fd(port->ssl),
                                            (err == SSL_ERROR_WANT_READ) ?
-                                  FD_READ | FD_CLOSE : FD_WRITE | FD_CLOSE);
+                                  FD_READ | FD_CLOSE : FD_WRITE | FD_CLOSE,
+                                           INFINITE);
 #endif
                goto rloop;
            case SSL_ERROR_SYSCALL:
@@ -374,7 +375,8 @@ wloop:
 #ifdef WIN32
                pgwin32_waitforsinglesocket(SSL_get_fd(port->ssl),
                                            (err == SSL_ERROR_WANT_READ) ?
-                                  FD_READ | FD_CLOSE : FD_WRITE | FD_CLOSE);
+                                  FD_READ | FD_CLOSE : FD_WRITE | FD_CLOSE,
+                                           INFINITE);
 #endif
                goto wloop;
            case SSL_ERROR_SYSCALL:
@@ -889,7 +891,8 @@ aloop:
 #ifdef WIN32
                pgwin32_waitforsinglesocket(SSL_get_fd(port->ssl),
                                            (err == SSL_ERROR_WANT_READ) ?
-                      FD_READ | FD_CLOSE | FD_ACCEPT : FD_WRITE | FD_CLOSE);
+                      FD_READ | FD_CLOSE | FD_ACCEPT : FD_WRITE | FD_CLOSE,
+                                           INFINITE);
 #endif
                goto aloop;
            case SSL_ERROR_SYSCALL:
index 01624e2515c7a6d49a0ece2caf55561bc86d047e..c7557034b755b4ca9a9d216951bdf6bcfecc5253 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/port/win32/socket.c,v 1.16 2007/01/05 22:19:35 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/port/win32/socket.c,v 1.17 2007/01/26 20:06:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -114,7 +114,7 @@ isDataGram(SOCKET s) {
 }
 
 int
-pgwin32_waitforsinglesocket(SOCKET s, int what)
+pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout)
 {
    static HANDLE waitevent = INVALID_HANDLE_VALUE;
    static SOCKET current_socket = -1;
@@ -195,7 +195,7 @@ pgwin32_waitforsinglesocket(SOCKET s, int what)
        }
    }
    else
-       r = WaitForMultipleObjectsEx(2, events, FALSE, INFINITE, TRUE);
+       r = WaitForMultipleObjectsEx(2, events, FALSE, timeout, TRUE);
 
    if (r == WAIT_OBJECT_0 || r == WAIT_IO_COMPLETION)
    {
@@ -205,6 +205,8 @@ pgwin32_waitforsinglesocket(SOCKET s, int what)
    }
    if (r == WAIT_OBJECT_0 + 1)
        return 1;
+   if (r == WAIT_TIMEOUT)
+       return 0;
    ereport(ERROR,
            (errmsg_internal("Bad return from WaitForMultipleObjects: %i (%i)", r, (int) GetLastError())));
    return 0;
@@ -274,7 +276,7 @@ pgwin32_connect(SOCKET s, const struct sockaddr * addr, int addrlen)
        return -1;
    }
 
-   while (pgwin32_waitforsinglesocket(s, FD_CONNECT) == 0)
+   while (pgwin32_waitforsinglesocket(s, FD_CONNECT, INFINITE) == 0)
    {
        /* Loop endlessly as long as we are just delivering signals */
    }
@@ -310,7 +312,8 @@ pgwin32_recv(SOCKET s, char *buf, int len, int f)
 
    /* No error, zero bytes (win2000+) or error+WSAEWOULDBLOCK (<=nt4) */
 
-   if (pgwin32_waitforsinglesocket(s, FD_READ | FD_CLOSE | FD_ACCEPT) == 0)
+   if (pgwin32_waitforsinglesocket(s, FD_READ | FD_CLOSE | FD_ACCEPT,
+                                   INFINITE) == 0)
        return -1;
 
    r = WSARecv(s, &wbuf, 1, &b, &flags, NULL, NULL);
@@ -355,7 +358,7 @@ pgwin32_send(SOCKET s, char *buf, int len, int flags)
 
        /* No error, zero bytes (win2000+) or error+WSAEWOULDBLOCK (<=nt4) */
 
-       if (pgwin32_waitforsinglesocket(s, FD_WRITE | FD_CLOSE) == 0)
+       if (pgwin32_waitforsinglesocket(s, FD_WRITE | FD_CLOSE, INFINITE) == 0)
            return -1;
    }
 
index 97c11d0fb00446791c8d011c43e396df59f79566..6a5907c466e2e1134b31bfdb9ecaf9cd85c6e147 100644 (file)
@@ -13,7 +13,7 @@
  *
  * Copyright (c) 2001-2007, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.143 2007/01/11 23:06:03 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.144 2007/01/26 20:06:52 tgl Exp $
  * ----------
  */
 #include "postgres.h"
@@ -1657,11 +1657,13 @@ PgstatCollectorMain(int argc, char *argv[])
    int         len;
    PgStat_Msg  msg;
 
+#ifndef WIN32
 #ifdef HAVE_POLL
    struct pollfd input_fd;
 #else
    struct timeval sel_timeout;
    fd_set      rfds;
+#endif
 #endif
 
    IsUnderPostmaster = true;   /* we are a postmaster subprocess now */
@@ -1724,7 +1726,7 @@ PgstatCollectorMain(int argc, char *argv[])
     * Setup the descriptor set for select(2).  Since only one bit in the set
     * ever changes, we need not repeat FD_ZERO each time.
     */
-#ifndef HAVE_POLL
+#if !defined(HAVE_POLL) && !defined(WIN32)
    FD_ZERO(&rfds);
 #endif
 
@@ -1771,8 +1773,10 @@ PgstatCollectorMain(int argc, char *argv[])
         * poll/select call, so this also limits speed of response to SIGQUIT,
         * which is more important.)
         *
-        * We use poll(2) if available, otherwise select(2)
+        * We use poll(2) if available, otherwise select(2).
+        * Win32 has its own implementation.
         */
+#ifndef WIN32
 #ifdef HAVE_POLL
        input_fd.fd = pgStatSock;
        input_fd.events = POLLIN | POLLERR;
@@ -1810,6 +1814,10 @@ PgstatCollectorMain(int argc, char *argv[])
 
        got_data = FD_ISSET(pgStatSock, &rfds);
 #endif   /* HAVE_POLL */
+#else /* WIN32 */
+       got_data = pgwin32_waitforsinglesocket(pgStatSock, FD_READ,
+                                              PGSTAT_SELECT_TIMEOUT*1000);
+#endif
 
        /*
         * If there is a message on the socket, read it and check for
index d1789b25265754ca68a6e79b82679c9e745f4298..047d513befe9fd8094d6c57f63d073ae34a8b9e6 100644 (file)
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/include/port/win32.h,v 1.71 2007/01/25 21:50:49 momjian Exp $ */
+/* $PostgreSQL: pgsql/src/include/port/win32.h,v 1.72 2007/01/26 20:06:52 tgl Exp $ */
 
 #if defined(_MSC_VER) || defined(__BORLANDC__)
 #define WIN32_ONLY_COMPILER
@@ -289,7 +289,7 @@ int         pgwin32_recv(SOCKET s, char *buf, int len, int flags);
 int            pgwin32_send(SOCKET s, char *buf, int len, int flags);
 
 const char *pgwin32_socket_strerror(int err);
-int            pgwin32_waitforsinglesocket(SOCKET s, int what);
+int            pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout);
 
 /* in backend/port/win32/security.c */
 extern int pgwin32_is_admin(void);