Skip to content

Commit

Permalink
Improved dead connection detection.
Browse files Browse the repository at this point in the history
  • Loading branch information
anthony-tuininga committed May 13, 2021
1 parent c0a406a commit 0727393
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 33 deletions.
10 changes: 9 additions & 1 deletion doc/src/releasenotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,15 @@ Version 4.2 (TBD)
in order to provide for greater safety. Although there may be instances
where threaded mode is not strictly needed, these are few and any
advantages are minimal.
#) Improved dead connection detection in a number of scenarios.
#) Improved dead connection detection. If any error occurs that indicates that
the connection is no longer usable, the connection is marked as dead and
the unified error `DPI-1080: connection was closed by ORA-%d` (where the
`%d` is replaced by the Oracle error that caused the connection to be
closed) is returned instead. Attempts to use the connection after this
result in the error `DPI-1010: not connected` being returned. This includes
call timeout errors such as when :func:`dpiConn_setCallTimeout()` is called
with a value set too low to allow the connection to break the executing
statement and reset after the timeout occurs.
#) Improved documentation and the test suite.


Expand Down
75 changes: 43 additions & 32 deletions src/dpiError.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,42 +189,53 @@ int dpiError__setFromOCI(dpiError *error, int status, dpiConn *conn,
"get server status", error) < 0 ||
serverStatus != DPI_OCI_SERVER_NORMAL) {
conn->deadSession = 1;
return DPI_FAILURE;
}
}

// otherwise, check for certain errors which indicate that the session
// is dead; also check for call timeout and raise unified message
// instead
// check for certain errors which indicate that the session is dead
if (!conn->deadSession) {
switch (error->buffer->code) {
case 22: // invalid session ID; access denied
case 28: // your session has been killed
case 31: // your session has been marked for kill
case 45: // your session has been terminated with no replay
case 378: // buffer pools cannot be created as specified
case 602: // internal programming exception
case 603: // ORACLE server session terminated by fatal error
case 609: // could not attach to incoming connection
case 1012: // not logged on
case 1041: // internal error. hostdef extension doesn't exist
case 1043: // user side memory corruption
case 1089: // immediate shutdown or close in progress
case 1092: // ORACLE instance terminated. Disconnection forced
case 2396: // exceeded maximum idle time, please connect again
case 3113: // end-of-file on communication channel
case 3114: // not connected to ORACLE
case 3122: // attempt to close ORACLE-side window on user side
case 3135: // connection lost contact
case 12153: // TNS:not connected
case 12537: // TNS:connection closed
case 12547: // TNS:lost contact
case 12570: // TNS:packet reader failure
case 12583: // TNS:no reader
case 27146: // post/wait initialization failed
case 28511: // lost RPC connection
case 56600: // an illegal OCI function call was issued
conn->deadSession = 1;
break;
}
}

// if session is marked as dead, return a unified error message
if (conn->deadSession) {
dpiError__set(error, action, DPI_ERR_CONN_CLOSED,
error->buffer->code);
error->buffer->code = 0;
return DPI_FAILURE;
}

// check for call timeout and return a unified message instead
switch (error->buffer->code) {
case 22: // invalid session ID; access denied
case 28: // your session has been killed
case 31: // your session has been marked for kill
case 45: // your session has been terminated with no replay
case 378: // buffer pools cannot be created as specified
case 602: // internal programming exception
case 603: // ORACLE server session terminated by fatal error
case 609: // could not attach to incoming connection
case 1012: // not logged on
case 1041: // internal error. hostdef extension doesn't exist
case 1043: // user side memory corruption
case 1089: // immediate shutdown or close in progress
case 1092: // ORACLE instance terminated. Disconnection forced
case 2396: // exceeded maximum idle time, please connect again
case 3113: // end-of-file on communication channel
case 3114: // not connected to ORACLE
case 3122: // attempt to close ORACLE-side window on user side
case 3135: // connection lost contact
case 12153: // TNS:not connected
case 12537: // TNS:connection closed
case 12547: // TNS:lost contact
case 12570: // TNS:packet reader failure
case 12583: // TNS:no reader
case 27146: // post/wait initialization failed
case 28511: // lost RPC connection
case 56600: // an illegal OCI function call was issued
conn->deadSession = 1;
break;
case 3136: // inbound connection timed out
case 3156: // OCI call timed out
case 12161: // TNS:internal error: partial data received
Expand Down
1 change: 1 addition & 0 deletions src/dpiErrorMessages.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,5 @@ static const char* const dpiErrorMessages[DPI_ERR_MAX - DPI_ERR_NO_ERR] = {
"DPI-1077: JSON scalar type %d is not supported", // DPI_ERR_UNHANDLED_JSON_SCALAR_TYPE
"DPI-1078: native type %d with Oracle type %d is not supported by JSON", // DPI_ERR_UNHANDLED_CONVERSION_TO_JSON
"DPI-1079: Oracle Client library is at version %d.%d but either version %d.%d (or later DBRU) or version %d.%d (or higher) is needed", // DPI_ERR_ORACLE_CLIENT_TOO_OLD_MULTI
"DPI-1080: connection was closed by ORA-%d", // DPI_ERR_CONN_CLOSED
};
1 change: 1 addition & 0 deletions src/dpiImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,7 @@ typedef enum {
DPI_ERR_UNHANDLED_JSON_SCALAR_TYPE,
DPI_ERR_UNHANDLED_CONVERSION_TO_JSON,
DPI_ERR_ORACLE_CLIENT_TOO_OLD_MULTI,
DPI_ERR_CONN_CLOSED,
DPI_ERR_MAX
} dpiErrorNum;

Expand Down

0 comments on commit 0727393

Please sign in to comment.