diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c index 410fb559aad6c..de1da1d1e3483 100644 --- a/ext/mysqli/mysqli.c +++ b/ext/mysqli/mysqli.c @@ -166,11 +166,13 @@ static void mysqli_link_free_storage(zend_object *object) if (my_res && my_res->ptr) { MY_MYSQL *mysql = (MY_MYSQL *)my_res->ptr; - if (mysql->mysql) { - php_mysqli_close(mysql, MYSQLI_CLOSE_EXPLICIT, my_res->status); + if (!mysql->disable_cleanup) { + if (mysql->mysql) { + php_mysqli_close(mysql, MYSQLI_CLOSE_EXPLICIT, my_res->status); + } + php_clear_mysql(mysql); + efree(mysql); } - php_clear_mysql(mysql); - efree(mysql); my_res->status = MYSQLI_STATUS_UNKNOWN; } mysqli_objects_free_storage(object); diff --git a/ext/mysqli/mysqli.stub.php b/ext/mysqli/mysqli.stub.php index e9311166c8ec6..630060698b253 100644 --- a/ext/mysqli/mysqli.stub.php +++ b/ext/mysqli/mysqli.stub.php @@ -199,6 +199,12 @@ public function dump_debug_info(): bool {} */ public function debug(string $options) {} // TODO make return type void + /** + * @tentative-return-type + * @alias mysqli_disable_cleanup + */ + public function disable_cleanup(bool $enable): bool {} + /** * @tentative-return-type * @alias mysqli_get_charset @@ -766,6 +772,8 @@ function mysqli_connect_error(): ?string {} function mysqli_data_seek(mysqli_result $result, int $offset): bool {} +function mysqli_disable_cleanup(bool $enable): bool {} + function mysqli_dump_debug_info(mysqli $mysql): bool {} /** @return true */ diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c index fb0f6b43d2a5c..64af34df60a1c 100644 --- a/ext/mysqli/mysqli_api.c +++ b/ext/mysqli/mysqli_api.c @@ -372,6 +372,22 @@ PHP_FUNCTION(mysqli_debug) } /* }}} */ +/* {{{ Turn link cleanup on or off when the object is destroyed */ +PHP_FUNCTION(mysqli_disable_cleanup) +{ + MY_MYSQL *mysql; + zval *mysql_link; + bool enable; + + if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ob", &mysql_link, mysqli_link_class_entry, &enable) == FAILURE) { + RETURN_THROWS(); + } + MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID); + mysql->disable_cleanup = enable; + RETURN_TRUE; +} +/* }}} */ + /* {{{ */ PHP_FUNCTION(mysqli_dump_debug_info) { @@ -862,6 +878,7 @@ void php_mysqli_init(INTERNAL_FUNCTION_PARAMETERS, bool is_method) RETURN_FALSE; } + mysql->disable_cleanup = false; mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE)); mysqli_resource->ptr = (void *)mysql; mysqli_resource->status = MYSQLI_STATUS_INITIALIZED; diff --git a/ext/mysqli/mysqli_arginfo.h b/ext/mysqli/mysqli_arginfo.h index 0b3457b447a52..02707b6772caa 100644 --- a/ext/mysqli/mysqli_arginfo.h +++ b/ext/mysqli/mysqli_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: a2f2992afd959a13215bfdfd00096f368b3bc392 */ + * Stub hash: 9894c3e237ecd523f8e755248eca926830ce115b */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_mysqli_affected_rows, 0, 1, MAY_BE_LONG|MAY_BE_STRING) ZEND_ARG_OBJ_INFO(0, mysql, mysqli, 0) @@ -53,6 +53,10 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mysqli_data_seek, 0, 2, _IS_BOOL ZEND_ARG_TYPE_INFO(0, offset, IS_LONG, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mysqli_disable_cleanup, 0, 1, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, enable, _IS_BOOL, 0) +ZEND_END_ARG_INFO() + #define arginfo_mysqli_dump_debug_info arginfo_mysqli_close ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mysqli_debug, 0, 1, _IS_BOOL, 0) @@ -451,6 +455,8 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_mysqli_debug, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, options, IS_STRING, 0) ZEND_END_ARG_INFO() +#define arginfo_class_mysqli_disable_cleanup arginfo_class_mysqli_autocommit + ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_mysqli_get_charset, 0, 0, IS_OBJECT, 1) ZEND_END_ARG_INFO() @@ -703,6 +709,7 @@ ZEND_FUNCTION(mysqli_connect); ZEND_FUNCTION(mysqli_connect_errno); ZEND_FUNCTION(mysqli_connect_error); ZEND_FUNCTION(mysqli_data_seek); +ZEND_FUNCTION(mysqli_disable_cleanup); ZEND_FUNCTION(mysqli_dump_debug_info); ZEND_FUNCTION(mysqli_debug); ZEND_FUNCTION(mysqli_errno); @@ -816,6 +823,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(mysqli_connect_errno, arginfo_mysqli_connect_errno) ZEND_FE(mysqli_connect_error, arginfo_mysqli_connect_error) ZEND_FE(mysqli_data_seek, arginfo_mysqli_data_seek) + ZEND_FE(mysqli_disable_cleanup, arginfo_mysqli_disable_cleanup) ZEND_FE(mysqli_dump_debug_info, arginfo_mysqli_dump_debug_info) ZEND_FE(mysqli_debug, arginfo_mysqli_debug) ZEND_FE(mysqli_errno, arginfo_mysqli_errno) @@ -930,6 +938,7 @@ static const zend_function_entry class_mysqli_methods[] = { ZEND_ME_MAPPING(connect, mysqli_connect, arginfo_class_mysqli_connect, ZEND_ACC_PUBLIC) ZEND_ME_MAPPING(dump_debug_info, mysqli_dump_debug_info, arginfo_class_mysqli_dump_debug_info, ZEND_ACC_PUBLIC) ZEND_ME_MAPPING(debug, mysqli_debug, arginfo_class_mysqli_debug, ZEND_ACC_PUBLIC) + ZEND_ME_MAPPING(disable_cleanup, mysqli_disable_cleanup, arginfo_class_mysqli_disable_cleanup, ZEND_ACC_PUBLIC) ZEND_ME_MAPPING(get_charset, mysqli_get_charset, arginfo_class_mysqli_get_charset, ZEND_ACC_PUBLIC) ZEND_ME_MAPPING(get_client_info, mysqli_get_client_info, arginfo_class_mysqli_get_client_info, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED) ZEND_ME_MAPPING(get_connection_stats, mysqli_get_connection_stats, arginfo_class_mysqli_get_connection_stats, ZEND_ACC_PUBLIC) diff --git a/ext/mysqli/php_mysqli_structs.h b/ext/mysqli/php_mysqli_structs.h index c57a26603c49c..458ff4f328c53 100644 --- a/ext/mysqli/php_mysqli_structs.h +++ b/ext/mysqli/php_mysqli_structs.h @@ -67,6 +67,7 @@ typedef struct { unsigned int multi_query; bool persistent; int async_result_fetch_type; + bool disable_cleanup; } MY_MYSQL; typedef struct { diff --git a/ext/mysqli/tests/mysqli_class_mysqli_interface.phpt b/ext/mysqli/tests/mysqli_class_mysqli_interface.phpt index 793d5b1150835..45c42aeb25732 100644 --- a/ext/mysqli/tests/mysqli_class_mysqli_interface.phpt +++ b/ext/mysqli/tests/mysqli_class_mysqli_interface.phpt @@ -27,6 +27,7 @@ require_once('skipifconnectfailure.inc'); 'close' => true, 'commit' => true, 'connect' => true, + 'disable_cleanup' => true, 'dump_debug_info' => true, 'escape_string' => true, 'get_charset' => true,