Commit 4355d214 authored by Tom Lane's avatar Tom Lane

On Windows, use pgwin32_waitforsinglesocket() instead of select() to wait for

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...
parent 8ff2bcce
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * 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) * Since the server static private key ($DataDir/server.key)
* will normally be stored unencrypted so that the database * will normally be stored unencrypted so that the database
...@@ -275,7 +275,8 @@ rloop: ...@@ -275,7 +275,8 @@ rloop:
#ifdef WIN32 #ifdef WIN32
pgwin32_waitforsinglesocket(SSL_get_fd(port->ssl), pgwin32_waitforsinglesocket(SSL_get_fd(port->ssl),
(err == SSL_ERROR_WANT_READ) ? (err == SSL_ERROR_WANT_READ) ?
FD_READ | FD_CLOSE : FD_WRITE | FD_CLOSE); FD_READ | FD_CLOSE : FD_WRITE | FD_CLOSE,
INFINITE);
#endif #endif
goto rloop; goto rloop;
case SSL_ERROR_SYSCALL: case SSL_ERROR_SYSCALL:
...@@ -374,7 +375,8 @@ wloop: ...@@ -374,7 +375,8 @@ wloop:
#ifdef WIN32 #ifdef WIN32
pgwin32_waitforsinglesocket(SSL_get_fd(port->ssl), pgwin32_waitforsinglesocket(SSL_get_fd(port->ssl),
(err == SSL_ERROR_WANT_READ) ? (err == SSL_ERROR_WANT_READ) ?
FD_READ | FD_CLOSE : FD_WRITE | FD_CLOSE); FD_READ | FD_CLOSE : FD_WRITE | FD_CLOSE,
INFINITE);
#endif #endif
goto wloop; goto wloop;
case SSL_ERROR_SYSCALL: case SSL_ERROR_SYSCALL:
...@@ -889,7 +891,8 @@ aloop: ...@@ -889,7 +891,8 @@ aloop:
#ifdef WIN32 #ifdef WIN32
pgwin32_waitforsinglesocket(SSL_get_fd(port->ssl), pgwin32_waitforsinglesocket(SSL_get_fd(port->ssl),
(err == SSL_ERROR_WANT_READ) ? (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 #endif
goto aloop; goto aloop;
case SSL_ERROR_SYSCALL: case SSL_ERROR_SYSCALL:
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* *
* IDENTIFICATION * 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) { ...@@ -114,7 +114,7 @@ isDataGram(SOCKET s) {
} }
int int
pgwin32_waitforsinglesocket(SOCKET s, int what) pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout)
{ {
static HANDLE waitevent = INVALID_HANDLE_VALUE; static HANDLE waitevent = INVALID_HANDLE_VALUE;
static SOCKET current_socket = -1; static SOCKET current_socket = -1;
...@@ -195,7 +195,7 @@ pgwin32_waitforsinglesocket(SOCKET s, int what) ...@@ -195,7 +195,7 @@ pgwin32_waitforsinglesocket(SOCKET s, int what)
} }
} }
else else
r = WaitForMultipleObjectsEx(2, events, FALSE, INFINITE, TRUE); r = WaitForMultipleObjectsEx(2, events, FALSE, timeout, TRUE);
if (r == WAIT_OBJECT_0 || r == WAIT_IO_COMPLETION) if (r == WAIT_OBJECT_0 || r == WAIT_IO_COMPLETION)
{ {
...@@ -205,6 +205,8 @@ pgwin32_waitforsinglesocket(SOCKET s, int what) ...@@ -205,6 +205,8 @@ pgwin32_waitforsinglesocket(SOCKET s, int what)
} }
if (r == WAIT_OBJECT_0 + 1) if (r == WAIT_OBJECT_0 + 1)
return 1; return 1;
if (r == WAIT_TIMEOUT)
return 0;
ereport(ERROR, ereport(ERROR,
(errmsg_internal("Bad return from WaitForMultipleObjects: %i (%i)", r, (int) GetLastError()))); (errmsg_internal("Bad return from WaitForMultipleObjects: %i (%i)", r, (int) GetLastError())));
return 0; return 0;
...@@ -274,7 +276,7 @@ pgwin32_connect(SOCKET s, const struct sockaddr * addr, int addrlen) ...@@ -274,7 +276,7 @@ pgwin32_connect(SOCKET s, const struct sockaddr * addr, int addrlen)
return -1; 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 */ /* Loop endlessly as long as we are just delivering signals */
} }
...@@ -310,7 +312,8 @@ pgwin32_recv(SOCKET s, char *buf, int len, int f) ...@@ -310,7 +312,8 @@ pgwin32_recv(SOCKET s, char *buf, int len, int f)
/* No error, zero bytes (win2000+) or error+WSAEWOULDBLOCK (<=nt4) */ /* 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; return -1;
r = WSARecv(s, &wbuf, 1, &b, &flags, NULL, NULL); r = WSARecv(s, &wbuf, 1, &b, &flags, NULL, NULL);
...@@ -355,7 +358,7 @@ pgwin32_send(SOCKET s, char *buf, int len, int flags) ...@@ -355,7 +358,7 @@ pgwin32_send(SOCKET s, char *buf, int len, int flags)
/* No error, zero bytes (win2000+) or error+WSAEWOULDBLOCK (<=nt4) */ /* 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; return -1;
} }
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* *
* Copyright (c) 2001-2007, PostgreSQL Global Development Group * 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" #include "postgres.h"
...@@ -1657,11 +1657,13 @@ PgstatCollectorMain(int argc, char *argv[]) ...@@ -1657,11 +1657,13 @@ PgstatCollectorMain(int argc, char *argv[])
int len; int len;
PgStat_Msg msg; PgStat_Msg msg;
#ifndef WIN32
#ifdef HAVE_POLL #ifdef HAVE_POLL
struct pollfd input_fd; struct pollfd input_fd;
#else #else
struct timeval sel_timeout; struct timeval sel_timeout;
fd_set rfds; fd_set rfds;
#endif
#endif #endif
IsUnderPostmaster = true; /* we are a postmaster subprocess now */ IsUnderPostmaster = true; /* we are a postmaster subprocess now */
...@@ -1724,7 +1726,7 @@ PgstatCollectorMain(int argc, char *argv[]) ...@@ -1724,7 +1726,7 @@ PgstatCollectorMain(int argc, char *argv[])
* Setup the descriptor set for select(2). Since only one bit in the set * Setup the descriptor set for select(2). Since only one bit in the set
* ever changes, we need not repeat FD_ZERO each time. * ever changes, we need not repeat FD_ZERO each time.
*/ */
#ifndef HAVE_POLL #if !defined(HAVE_POLL) && !defined(WIN32)
FD_ZERO(&rfds); FD_ZERO(&rfds);
#endif #endif
...@@ -1771,8 +1773,10 @@ PgstatCollectorMain(int argc, char *argv[]) ...@@ -1771,8 +1773,10 @@ PgstatCollectorMain(int argc, char *argv[])
* poll/select call, so this also limits speed of response to SIGQUIT, * poll/select call, so this also limits speed of response to SIGQUIT,
* which is more important.) * 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 #ifdef HAVE_POLL
input_fd.fd = pgStatSock; input_fd.fd = pgStatSock;
input_fd.events = POLLIN | POLLERR; input_fd.events = POLLIN | POLLERR;
...@@ -1810,6 +1814,10 @@ PgstatCollectorMain(int argc, char *argv[]) ...@@ -1810,6 +1814,10 @@ PgstatCollectorMain(int argc, char *argv[])
got_data = FD_ISSET(pgStatSock, &rfds); got_data = FD_ISSET(pgStatSock, &rfds);
#endif /* HAVE_POLL */ #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 * If there is a message on the socket, read it and check for
......
/* $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__) #if defined(_MSC_VER) || defined(__BORLANDC__)
#define WIN32_ONLY_COMPILER #define WIN32_ONLY_COMPILER
...@@ -289,7 +289,7 @@ int pgwin32_recv(SOCKET s, char *buf, int len, int flags); ...@@ -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); int pgwin32_send(SOCKET s, char *buf, int len, int flags);
const char *pgwin32_socket_strerror(int err); 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 */ /* in backend/port/win32/security.c */
extern int pgwin32_is_admin(void); extern int pgwin32_is_admin(void);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment