Skip to content

Commit

Permalink
fix: add a socket timeout on cancel requests
Browse files Browse the repository at this point in the history
The timeout is configurable through cancelSignalTimeout in seconds with defult value of 10 seconds

fixes #603
  • Loading branch information
Tanya Gordeeva authored and vlsi committed Jul 13, 2016
1 parent b4d5976 commit ab2a6d8
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 12 deletions.
8 changes: 8 additions & 0 deletions pgjdbc/src/main/java/org/postgresql/PGProperty.java
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,14 @@ public enum PGProperty {
*/
SOCKET_TIMEOUT("socketTimeout", "0", "The timeout value used for socket read operations."),

/**
* Cancel command is sent out of band over its own connection, so cancel message can itself get
* stuck.
* This property controls "connect timeout" and "socket timeout" used for cancel commands.
* The timeout is specified in seconds. Default value is 10 seconds.
*/
CANCEL_SIGNAL_TIMEOUT("cancelSignalTimeout", "10", "The timeout that is used for sending cancel command."),

/**
* Socket factory used to create socket. A null value, which is the default, means system default.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,12 @@ public ProtocolConnection openConnectionImpl(HostSpec[] hostSpecs, String user,
// Do authentication (until AuthenticationOk).
doAuthentication(newStream, user, PGProperty.PASSWORD.get(info), logger);

int cancelSignalTimeout = PGProperty.CANCEL_SIGNAL_TIMEOUT.getInt(info) * 1000;

// Do final startup.
ProtocolConnectionImpl protoConnection =
new ProtocolConnectionImpl(newStream, user, database, logger, connectTimeout);
new ProtocolConnectionImpl(newStream, user, database, logger,
cancelSignalTimeout);
readStartupMessages(newStream, protoConnection, logger);

// Check Master or Slave
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@
*/
class ProtocolConnectionImpl implements ProtocolConnection {
ProtocolConnectionImpl(PGStream pgStream, String user, String database, Logger logger,
int connectTimeout) {
int cancelSignalTimeout) {
this.pgStream = pgStream;
this.user = user;
this.database = database;
this.logger = logger;
this.executor = new QueryExecutorImpl(this, pgStream, logger);
this.connectTimeout = connectTimeout;
this.cancelSignalTimeout = cancelSignalTimeout;
}

public HostSpec getHostSpec() {
Expand Down Expand Up @@ -102,7 +102,10 @@ public void sendQueryCancel() throws SQLException {
}

cancelStream =
new PGStream(pgStream.getSocketFactory(), pgStream.getHostSpec(), connectTimeout);
new PGStream(pgStream.getSocketFactory(), pgStream.getHostSpec(), cancelSignalTimeout);
if (cancelSignalTimeout > 0) {
cancelStream.getSocket().setSoTimeout(cancelSignalTimeout);
}
cancelStream.SendInteger4(16);
cancelStream.SendInteger2(1234);
cancelStream.SendInteger2(5678);
Expand Down Expand Up @@ -255,6 +258,5 @@ public String getApplicationName() {
private final String database;
private final QueryExecutorImpl executor;
private final Logger logger;

private final int connectTimeout;
private final int cancelSignalTimeout;
}
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,12 @@ public ProtocolConnection openConnectionImpl(HostSpec[] hostSpecs, String user,
// Do authentication (until AuthenticationOk).
doAuthentication(newStream, hostSpec.getHost(), user, info, logger);

int cancelSignalTimeout = PGProperty.CANCEL_SIGNAL_TIMEOUT.getInt(info) * 1000;

// Do final startup.
ProtocolConnectionImpl protoConnection =
new ProtocolConnectionImpl(newStream, user, database, info, logger, connectTimeout);
new ProtocolConnectionImpl(newStream, user, database, info, logger,
cancelSignalTimeout);
readStartupMessages(newStream, protoConnection, logger);

// Check Master or Slave
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@
*/
class ProtocolConnectionImpl implements ProtocolConnection {
ProtocolConnectionImpl(PGStream pgStream, String user, String database, Properties info,
Logger logger, int connectTimeout) {
Logger logger, int cancelSignalTimeout) {
this.pgStream = pgStream;
this.user = user;
this.database = database;
this.logger = logger;
this.executor = new QueryExecutorImpl(this, pgStream, info, logger);
// default value for server versions that don't report standard_conforming_strings
this.standardConformingStrings = false;
this.connectTimeout = connectTimeout;
this.cancelSignalTimeout = cancelSignalTimeout;
}

public HostSpec getHostSpec() {
Expand Down Expand Up @@ -103,7 +103,10 @@ public void sendQueryCancel() throws SQLException {
}

cancelStream =
new PGStream(pgStream.getSocketFactory(), pgStream.getHostSpec(), connectTimeout);
new PGStream(pgStream.getSocketFactory(), pgStream.getHostSpec(), cancelSignalTimeout);
if (cancelSignalTimeout > 0) {
cancelStream.getSocket().setSoTimeout(cancelSignalTimeout);
}
cancelStream.SendInteger4(16);
cancelStream.SendInteger2(1234);
cancelStream.SendInteger2(5678);
Expand Down Expand Up @@ -282,8 +285,7 @@ public String getApplicationName() {
private final String database;
private final QueryExecutorImpl executor;
private final Logger logger;

private final int connectTimeout;
private final int cancelSignalTimeout;

/**
* TimeZone of the current connection (TimeZone backend parameter)
Expand Down
16 changes: 16 additions & 0 deletions pgjdbc/src/main/java/org/postgresql/ds/common/BaseDataSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,22 @@ public int getSocketTimeout() {
return PGProperty.SOCKET_TIMEOUT.getIntNoCheck(properties);
}

/**
* @param seconds timeout that is used for sending cancel command
* @see PGProperty#CANCEL_SIGNAL_TIMEOUT
*/
public void setCancelSignalTimeout(int seconds) {
PGProperty.CANCEL_SIGNAL_TIMEOUT.set(properties, seconds);
}

/**
* @return timeout that is used for sending cancel command in seconds
* @see PGProperty#CANCEL_SIGNAL_TIMEOUT
*/
public int getCancelSignalTimeout() {
return PGProperty.CANCEL_SIGNAL_TIMEOUT.getIntNoCheck(properties);
}


/**
* @param enabled if SSL is enabled
Expand Down

0 comments on commit ab2a6d8

Please sign in to comment.