mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-08-23 17:17:17 +02:00
In libpq for Windows, call WSAStartup once and WSACleanup not at all.
The Windows documentation insists that every WSAStartup call should have a matching WSACleanup call. However, if that ever had actual relevance, it wasn't in this century. Every remotely-modern Windows kernel is capable of cleaning up when a process exits without doing that, and must be so to avoid resource leaks in case of a process crash. Moreover, Postgres backends have done WSAStartup without WSACleanup since commit4cdf51e64
in 2004, and we've never seen any indication of a problem with that. libpq's habit of doing WSAStartup during connection start and WSACleanup during shutdown is also rather inefficient, since a series of non-overlapping connection requests leads to repeated, quite expensive DLL unload/reload cycles. We document a workaround for that (having the application call WSAStartup for itself), but that's just a kluge. It's also worth noting that it's far from uncommon for applications to exit without doing PQfinish, and we've not heard reports of trouble from that either. However, the real reason for acting on this is that recent experiments by Alexander Lakhin show that calling WSACleanup during PQfinish is triggering the symptom we occasionally see that a process using libpq fails to emit expected stdio output. Therefore, let's change libpq so that it calls WSAStartup only once per process, during the first connection attempt, and never calls WSACleanup at all. While at it, get rid of the only other WSACleanup call in our code tree, in pg_dump/parallel.c; that presumably is equally useless. Back-patch of HEAD commit7d00a6b2d
. Discussion: https://postgr.es/m/ac976d8c-03df-d6b8-025c-15a2de8d9af1@postgrespro.ru
This commit is contained in:
parent
aa560d3a6b
commit
883226441d
@ -91,21 +91,6 @@
|
|||||||
</para>
|
</para>
|
||||||
</warning>
|
</warning>
|
||||||
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
On Windows, there is a way to improve performance if a single
|
|
||||||
database connection is repeatedly started and shutdown. Internally,
|
|
||||||
libpq calls <function>WSAStartup()</function> and <function>WSACleanup()</function> for connection startup
|
|
||||||
and shutdown, respectively. <function>WSAStartup()</function> increments an internal
|
|
||||||
Windows library reference count which is decremented by <function>WSACleanup()</function>.
|
|
||||||
When the reference count is just one, calling <function>WSACleanup()</function> frees
|
|
||||||
all resources and all DLLs are unloaded. This is an expensive
|
|
||||||
operation. To avoid this, an application can manually call
|
|
||||||
<function>WSAStartup()</function> so resources will not be freed when the last database
|
|
||||||
connection is closed.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
<variablelist>
|
<variablelist>
|
||||||
<varlistentry id="libpq-pqconnectdbparams">
|
<varlistentry id="libpq-pqconnectdbparams">
|
||||||
<term><function>PQconnectdbParams</function><indexterm><primary>PQconnectdbParams</primary></indexterm></term>
|
<term><function>PQconnectdbParams</function><indexterm><primary>PQconnectdbParams</primary></indexterm></term>
|
||||||
|
@ -234,19 +234,6 @@ static char *readMessageFromPipe(int fd);
|
|||||||
(strcmp(msg, pattern) == 0)
|
(strcmp(msg, pattern) == 0)
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Shutdown callback to clean up socket access
|
|
||||||
*/
|
|
||||||
#ifdef WIN32
|
|
||||||
static void
|
|
||||||
shutdown_parallel_dump_utils(int code, void *unused)
|
|
||||||
{
|
|
||||||
/* Call the cleanup function only from the main thread */
|
|
||||||
if (mainThreadId == GetCurrentThreadId())
|
|
||||||
WSACleanup();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize parallel dump support --- should be called early in process
|
* Initialize parallel dump support --- should be called early in process
|
||||||
* startup. (Currently, this is called whether or not we intend parallel
|
* startup. (Currently, this is called whether or not we intend parallel
|
||||||
@ -272,8 +259,7 @@ init_parallel_dump_utils(void)
|
|||||||
fprintf(stderr, _("%s: WSAStartup failed: %d\n"), progname, err);
|
fprintf(stderr, _("%s: WSAStartup failed: %d\n"), progname, err);
|
||||||
exit_nicely(1);
|
exit_nicely(1);
|
||||||
}
|
}
|
||||||
/* ... and arrange to shut it down at exit */
|
|
||||||
on_exit_nicely(shutdown_parallel_dump_utils, NULL);
|
|
||||||
parallel_init_done = true;
|
parallel_init_done = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -3437,23 +3437,30 @@ makeEmptyPGconn(void)
|
|||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure socket support is up and running.
|
* Make sure socket support is up and running in this process.
|
||||||
|
*
|
||||||
|
* Note: the Windows documentation says that we should eventually do a
|
||||||
|
* matching WSACleanup() call, but experience suggests that that is at
|
||||||
|
* least as likely to cause problems as fix them. So we don't.
|
||||||
*/
|
*/
|
||||||
|
static bool wsastartup_done = false;
|
||||||
|
|
||||||
|
if (!wsastartup_done)
|
||||||
|
{
|
||||||
WSADATA wsaData;
|
WSADATA wsaData;
|
||||||
|
|
||||||
if (WSAStartup(MAKEWORD(1, 1), &wsaData))
|
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
wsastartup_done = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Forget any earlier error */
|
||||||
WSASetLastError(0);
|
WSASetLastError(0);
|
||||||
#endif
|
#endif /* WIN32 */
|
||||||
|
|
||||||
conn = (PGconn *) malloc(sizeof(PGconn));
|
conn = (PGconn *) malloc(sizeof(PGconn));
|
||||||
if (conn == NULL)
|
if (conn == NULL)
|
||||||
{
|
|
||||||
#ifdef WIN32
|
|
||||||
WSACleanup();
|
|
||||||
#endif
|
|
||||||
return conn;
|
return conn;
|
||||||
}
|
|
||||||
|
|
||||||
/* Zero all pointers and booleans */
|
/* Zero all pointers and booleans */
|
||||||
MemSet(conn, 0, sizeof(PGconn));
|
MemSet(conn, 0, sizeof(PGconn));
|
||||||
@ -3621,10 +3628,6 @@ freePGconn(PGconn *conn)
|
|||||||
termPQExpBuffer(&conn->workBuffer);
|
termPQExpBuffer(&conn->workBuffer);
|
||||||
|
|
||||||
free(conn);
|
free(conn);
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
WSACleanup();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user