From 4355d214c248c959cfbcd974b5e9ba8a6bf81074 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 26 Jan 2007 20:06:52 +0000 Subject: [PATCH] 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... --- src/backend/libpq/be-secure.c | 11 +++++++---- src/backend/port/win32/socket.c | 15 +++++++++------ src/backend/postmaster/pgstat.c | 14 +++++++++++--- src/include/port/win32.h | 4 ++-- 4 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/backend/libpq/be-secure.c b/src/backend/libpq/be-secure.c index 421c4b68ce4..ac0196cead4 100644 --- a/src/backend/libpq/be-secure.c +++ b/src/backend/libpq/be-secure.c @@ -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: diff --git a/src/backend/port/win32/socket.c b/src/backend/port/win32/socket.c index 01624e2515c..c7557034b75 100644 --- a/src/backend/port/win32/socket.c +++ b/src/backend/port/win32/socket.c @@ -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; } diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index 97c11d0fb00..6a5907c466e 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -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 diff --git a/src/include/port/win32.h b/src/include/port/win32.h index d1789b25265..047d513befe 100644 --- a/src/include/port/win32.h +++ b/src/include/port/win32.h @@ -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); -- 2.39.5