Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 44b0d16

Browse files
committed
Add support for TCP keepalives on Windows, both for backend and the new
libpq support.
1 parent d4d32ee commit 44b0d16

File tree

4 files changed

+175
-39
lines changed

4 files changed

+175
-39
lines changed

doc/src/sgml/config.sgml

+33-17
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.293 2010/07/06 22:55:26 rhaas Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.294 2010/07/08 10:20:13 mha Exp $ -->
22

33
<chapter Id="runtime-config">
44
<title>Server Configuration</title>
@@ -523,12 +523,17 @@ SET ENABLE_SEQSCAN TO OFF;
523523
</indexterm>
524524
<listitem>
525525
<para>
526-
On systems that support the <symbol>TCP_KEEPIDLE</symbol> or
527-
<symbol>TCP_KEEPALIVE</> socket option, specifies the
528-
number of seconds between sending keepalives on an otherwise idle
529-
connection. A value of zero uses the system default. If neither of
530-
these socket options is supported, this parameter must be zero. This
531-
parameter is ignored for connections made via a Unix-domain socket.
526+
Specifies the number of seconds before sending a keepalive packet on an otherwise idle
527+
connection. A value of 0 uses the system default. This parameter is supported
528+
only on systems that support the <symbol>TCP_KEEPIDLE</> or <symbol>TCP_KEEPALIVE</>
529+
symbols, and on Windows; on other systems, it must be zero. This parameter is
530+
ignored for connections made via a Unix-domain socket.
531+
<note>
532+
<para>
533+
On Windows, a value of 0 will set this parameter to 2 hours,
534+
since Windows does not provide a way to read the default value.
535+
</para>
536+
</note>
532537
</para>
533538
</listitem>
534539
</varlistentry>
@@ -540,11 +545,17 @@ SET ENABLE_SEQSCAN TO OFF;
540545
</indexterm>
541546
<listitem>
542547
<para>
543-
On systems that support the <symbol>TCP_KEEPINTVL</symbol> socket option, specifies how
544-
long, in seconds, to wait for a response to a keepalive before
545-
retransmitting. A value of zero uses the system default. If <symbol>TCP_KEEPINTVL</symbol>
546-
is not supported, this parameter must be zero. This parameter is ignored
547-
for connections made via a Unix-domain socket.
548+
Specifies the number of seconds between sending keepalives on an otherwise idle
549+
connection. A value of 0 uses the system default. This parameter is supported
550+
only on systems that support the <symbol>TCP_KEEPINTVL</>
551+
symbol, and on Windows; on other systems, it must be zero. This parameter is
552+
ignored for connections made via a Unix-domain socket.
553+
<note>
554+
<para>
555+
On Windows, a value of 0 will set this parameter to 1 second,
556+
since Windows does not provide a way to read the default value.
557+
</para>
558+
</note>
548559
</para>
549560
</listitem>
550561
</varlistentry>
@@ -556,11 +567,16 @@ SET ENABLE_SEQSCAN TO OFF;
556567
</indexterm>
557568
<listitem>
558569
<para>
559-
On systems that support the <symbol>TCP_KEEPCNT</symbol> socket option, specifies how
560-
many keepalives can be lost before the connection is considered dead.
561-
A value of zero uses the system default. If <symbol>TCP_KEEPCNT</symbol> is not
562-
supported, this parameter must be zero. This parameter is ignored
563-
for connections made via a Unix-domain socket.
570+
Specifies the number of keepalive packets to send on an otherwise idle
571+
connection. A value of 0 uses the system default. This parameter is supported
572+
only on systems that support the <symbol>TCP_KEEPCNT</>
573+
symbol; on other systems, it must be zero. This parameter is
574+
ignored for connections made via a Unix-domain socket.
575+
<note>
576+
<para>
577+
This parameter is not supported on Windows, and must be zero.
578+
</para>
579+
</note>
564580
</para>
565581
</listitem>
566582
</varlistentry>

doc/src/sgml/libpq.sgml

+15-13
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.312 2010/07/06 21:14:25 rhaas Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.313 2010/07/08 10:20:14 mha Exp $ -->
22

33
<chapter id="libpq">
44
<title><application>libpq</application> - C Library</title>
@@ -298,10 +298,11 @@
298298
<para>
299299
Controls the number of seconds of inactivity after which TCP should
300300
send a keepalive message to the server. A value of zero uses the
301-
system default. This parameter is ignored if the neither the
302-
<symbol>TCP_KEEPIDLE</> nor the <symbol>TCP_KEEPALIVE</> socket
303-
options are supported, for connections made via a Unix-domain
304-
socket, or if keepalives are disabled.
301+
system default. This parameter is ignored for connections made via a
302+
Unix-domain socket, or if keepalives are disabled. It is only supported
303+
on systems where the <symbol>TCP_KEEPIDLE</> or <symbol>TCP_KEEPALIVE</>
304+
socket option is available, and on Windows; on other systems, it has no
305+
effect.
305306
</para>
306307
</listitem>
307308
</varlistentry>
@@ -312,10 +313,11 @@
312313
<para>
313314
Controls the number of seconds after which a TCP keepalive message
314315
that is not acknowledged by the server should be retransmitted. A
315-
value of zero uses the system default. This parameter is ignored if
316-
the <symbol>TCP_KEEPINTVL</> socket option is not supported, for
317-
connections made via a Unix-domain socket, or if keepalives are
318-
disabled.
316+
value of zero uses the system default. This parameter is ignored for
317+
connections made via a Unix-domain socket, or if keepalives are disabled.
318+
It is only supported on systems where the <symbol>TCP_KEEPINTVL</>
319+
socket option is available, and on Windows; on other systems, it has no
320+
effect.
319321
</para>
320322
</listitem>
321323
</varlistentry>
@@ -326,10 +328,10 @@
326328
<para>
327329
Controls the number of TCP keepalives that can be lost before the
328330
client's connection to the server is considered dead. A value of
329-
zero uses the system default. This parameter is ignored if the
330-
<symbol>TCP_KEEPCNT</> socket option is not supported, for
331-
connections made via a Unix-domain socket, or if keepalives are
332-
disabled.
331+
zero uses the system default. This parameter is ignored for
332+
connections made via a Unix-domain socket, or if keepalives are disabled.
333+
It is only supported on systems where the <symbol>TCP_KEEPINTVL</>
334+
socket option is available; on other systems, it has no effect.
333335
</para>
334336
</listitem>
335337
</varlistentry>

src/backend/libpq/pqcomm.c

+73-8
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
3131
* Portions Copyright (c) 1994, Regents of the University of California
3232
*
33-
* $PostgreSQL: pgsql/src/backend/libpq/pqcomm.c,v 1.210 2010/07/06 21:14:25 rhaas Exp $
33+
* $PostgreSQL: pgsql/src/backend/libpq/pqcomm.c,v 1.211 2010/07/08 10:20:12 mha Exp $
3434
*
3535
*-------------------------------------------------------------------------
3636
*/
@@ -83,6 +83,9 @@
8383
#ifdef HAVE_UTIME_H
8484
#include <utime.h>
8585
#endif
86+
#ifdef WIN32
87+
#include <mstcpip.h>
88+
#endif
8689

8790
#include "libpq/ip.h"
8891
#include "libpq/libpq.h"
@@ -1314,10 +1317,55 @@ pq_endcopyout(bool errorAbort)
13141317
* Support for TCP Keepalive parameters
13151318
*/
13161319

1320+
/*
1321+
* On Windows, we need to set both idle and interval at the same time.
1322+
* We also cannot reset them to the default (setting to zero will
1323+
* actually set them to zero, not default), therefor we fallback to
1324+
* the out-of-the-box default instead.
1325+
*/
1326+
#ifdef WIN32
1327+
static int
1328+
pq_setkeepaliveswin32(Port *port, int idle, int interval)
1329+
{
1330+
struct tcp_keepalive ka;
1331+
DWORD retsize;
1332+
1333+
if (idle <= 0)
1334+
idle = 2 * 60 * 60; /* default = 2 hours */
1335+
if (interval <= 0)
1336+
interval = 1; /* default = 1 second */
1337+
1338+
ka.onoff = 1;
1339+
ka.keepalivetime = idle * 1000;
1340+
ka.keepaliveinterval = interval * 1000;
1341+
1342+
if (WSAIoctl(port->sock,
1343+
SIO_KEEPALIVE_VALS,
1344+
(LPVOID) &ka,
1345+
sizeof(ka),
1346+
NULL,
1347+
0,
1348+
&retsize,
1349+
NULL,
1350+
NULL)
1351+
!= 0)
1352+
{
1353+
elog(LOG, "WSAIoctl(SIO_KEEPALIVE_VALS) failed: %ui",
1354+
WSAGetLastError());
1355+
return STATUS_ERROR;
1356+
}
1357+
if (port->keepalives_idle != idle)
1358+
port->keepalives_idle = idle;
1359+
if (port->keepalives_interval != interval)
1360+
port->keepalives_interval = interval;
1361+
return STATUS_OK;
1362+
}
1363+
#endif
1364+
13171365
int
13181366
pq_getkeepalivesidle(Port *port)
13191367
{
1320-
#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPALIVE)
1368+
#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPALIVE) || defined(WIN32)
13211369
if (port == NULL || IS_AF_UNIX(port->laddr.addr.ss_family))
13221370
return 0;
13231371

@@ -1326,6 +1374,7 @@ pq_getkeepalivesidle(Port *port)
13261374

13271375
if (port->default_keepalives_idle == 0)
13281376
{
1377+
#ifndef WIN32
13291378
ACCEPT_TYPE_ARG3 size = sizeof(port->default_keepalives_idle);
13301379

13311380
#ifdef TCP_KEEPIDLE
@@ -1344,7 +1393,11 @@ pq_getkeepalivesidle(Port *port)
13441393
elog(LOG, "getsockopt(TCP_KEEPALIVE) failed: %m");
13451394
port->default_keepalives_idle = -1; /* don't know */
13461395
}
1347-
#endif
1396+
#endif /* TCP_KEEPIDLE */
1397+
#else /* WIN32 */
1398+
/* We can't get the defaults on Windows, so return "don't know" */
1399+
port->default_keepalives_idle = -1;
1400+
#endif /* WIN32 */
13481401
}
13491402

13501403
return port->default_keepalives_idle;
@@ -1359,10 +1412,11 @@ pq_setkeepalivesidle(int idle, Port *port)
13591412
if (port == NULL || IS_AF_UNIX(port->laddr.addr.ss_family))
13601413
return STATUS_OK;
13611414

1362-
#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPALIVE)
1415+
#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPALIVE) || defined(WIN32)
13631416
if (idle == port->keepalives_idle)
13641417
return STATUS_OK;
13651418

1419+
#ifndef WIN32
13661420
if (port->default_keepalives_idle <= 0)
13671421
{
13681422
if (pq_getkeepalivesidle(port) < 0)
@@ -1394,21 +1448,23 @@ pq_setkeepalivesidle(int idle, Port *port)
13941448
#endif
13951449

13961450
port->keepalives_idle = idle;
1397-
#else
1451+
#else /* WIN32 */
1452+
return pq_setkeepaliveswin32(port, idle, port->keepalives_interval);
1453+
#endif
1454+
#else /* TCP_KEEPIDLE || WIN32 */
13981455
if (idle != 0)
13991456
{
14001457
elog(LOG, "setting the keepalive idle time is not supported");
14011458
return STATUS_ERROR;
14021459
}
14031460
#endif
1404-
14051461
return STATUS_OK;
14061462
}
14071463

14081464
int
14091465
pq_getkeepalivesinterval(Port *port)
14101466
{
1411-
#ifdef TCP_KEEPINTVL
1467+
#if defined(TCP_KEEPINTVL) || defined(WIN32)
14121468
if (port == NULL || IS_AF_UNIX(port->laddr.addr.ss_family))
14131469
return 0;
14141470

@@ -1417,6 +1473,7 @@ pq_getkeepalivesinterval(Port *port)
14171473

14181474
if (port->default_keepalives_interval == 0)
14191475
{
1476+
#ifndef WIN32
14201477
ACCEPT_TYPE_ARG3 size = sizeof(port->default_keepalives_interval);
14211478

14221479
if (getsockopt(port->sock, IPPROTO_TCP, TCP_KEEPINTVL,
@@ -1426,6 +1483,10 @@ pq_getkeepalivesinterval(Port *port)
14261483
elog(LOG, "getsockopt(TCP_KEEPINTVL) failed: %m");
14271484
port->default_keepalives_interval = -1; /* don't know */
14281485
}
1486+
#else
1487+
/* We can't get the defaults on Windows, so return "don't know" */
1488+
port->default_keepalives_interval = -1;
1489+
#endif /* WIN32 */
14291490
}
14301491

14311492
return port->default_keepalives_interval;
@@ -1440,10 +1501,11 @@ pq_setkeepalivesinterval(int interval, Port *port)
14401501
if (port == NULL || IS_AF_UNIX(port->laddr.addr.ss_family))
14411502
return STATUS_OK;
14421503

1443-
#ifdef TCP_KEEPINTVL
1504+
#if defined(TCP_KEEPINTVL) || defined (WIN32)
14441505
if (interval == port->keepalives_interval)
14451506
return STATUS_OK;
14461507

1508+
#ifndef WIN32
14471509
if (port->default_keepalives_interval <= 0)
14481510
{
14491511
if (pq_getkeepalivesinterval(port) < 0)
@@ -1466,6 +1528,9 @@ pq_setkeepalivesinterval(int interval, Port *port)
14661528
}
14671529

14681530
port->keepalives_interval = interval;
1531+
#else /* WIN32 */
1532+
return pq_setkeepaliveswin32(port, port->keepalives_idle, interval);
1533+
#endif
14691534
#else
14701535
if (interval != 0)
14711536
{

0 commit comments

Comments
 (0)