Skip to content

Fix persistent procedural ODBC connections not getting closed (8.1) #12132

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions ext/odbc/php_odbc.c
Original file line number Diff line number Diff line change
Expand Up @@ -753,12 +753,14 @@ void odbc_transact(INTERNAL_FUNCTION_PARAMETERS, int type)
/* }}} */

/* {{{ _close_pconn_with_res */
static int _close_pconn_with_res(zend_resource *le, zend_resource *res)
static int _close_pconn_with_res(zval *zv, void *p)
{
if (le->type == le_pconn && (((odbc_connection *)(le->ptr))->res == res)){
return 1;
}else{
return 0;
zend_resource *le = Z_RES_P(zv);
zend_resource *res = (zend_resource*)p;
if (le->type == le_pconn && (((odbc_connection *)(le->ptr))->res == res)) {
return ZEND_HASH_APPLY_REMOVE;
} else {
return ZEND_HASH_APPLY_KEEP;
}
}
/* }}} */
Expand Down Expand Up @@ -837,7 +839,7 @@ PHP_FUNCTION(odbc_close_all)
zend_list_close(p);
/* Delete the persistent connection */
zend_hash_apply_with_argument(&EG(persistent_list),
(apply_func_arg_t) _close_pconn_with_res, (void *)p);
_close_pconn_with_res, (void *)p);
}
}
} ZEND_HASH_FOREACH_END();
Expand Down Expand Up @@ -2365,7 +2367,7 @@ PHP_FUNCTION(odbc_close)
zend_list_close(Z_RES_P(pv_conn));

if(is_pconn){
zend_hash_apply_with_argument(&EG(persistent_list), (apply_func_arg_t) _close_pconn_with_res, (void *) Z_RES_P(pv_conn));
zend_hash_apply_with_argument(&EG(persistent_list), _close_pconn_with_res, (void *) Z_RES_P(pv_conn));
}
}
/* }}} */
Expand Down
65 changes: 65 additions & 0 deletions ext/odbc/tests/odbc_persistent_close.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
--TEST--
odbc_pconnect(): Make sure closing a persistent connection works
--EXTENSIONS--
odbc
--SKIPIF--
<?php

include 'skipif.inc';

// The test can affect multiple drivers, but testing it is driver-specific.
// Since CI runs ODBC tests with SQL Server, just use an SQL Server specific way of testing.
$conn = odbc_connect($dsn, $user, $pass);
$result = @odbc_exec($conn, "SELECT @@Version");
if ($result) {
$array = odbc_fetch_array($result);
$info = (string) reset($array);
if (!str_contains($info, "Microsoft SQL Server")) {
echo "skip MS SQL specific test";
}
}
?>
--FILE--
<?php

include 'config.inc';

// set a session specific variable via CONTEXT_INFO, if we get the same connection again, it should be identical
function set_context_info($conn, $string) {
$hexstring = bin2hex($string);
return odbc_exec($conn, "SET CONTEXT_INFO 0x$hexstring");
}

function fetch_context_info($conn) {
$stmt = odbc_exec($conn, "SELECT CONTEXT_INFO() AS CONTEXT_INFO");
if (!$stmt) {
return false;
}
$res = odbc_fetch_array($stmt);
if ($res) {
// this is a binary, so we get a bunch of nulls at the end
return $res["CONTEXT_INFO"] ? trim($res["CONTEXT_INFO"]) : null;
} else {
return false;
}
}

// run 1: set expectations
$conn = odbc_pconnect($dsn, $user, $pass);
set_context_info($conn, "PHP odbc_pconnect test");
var_dump(fetch_context_info($conn));

// run 2: reuse same connection (imagine this is another request)
$conn = odbc_pconnect($dsn, $user, $pass);
var_dump(fetch_context_info($conn));

// run 3: close it and see if it's the same connection
odbc_close($conn);
$conn = odbc_pconnect($dsn, $user, $pass);
var_dump(fetch_context_info($conn));

?>
--EXPECT--
string(22) "PHP odbc_pconnect test"
string(22) "PHP odbc_pconnect test"
NULL