summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/mysql/php_mysql.c25
-rw-r--r--ext/mysqli/mysqli.c33
-rw-r--r--ext/mysqlnd/mysqlnd.c18
-rw-r--r--ext/mysqlnd/mysqlnd_palloc.c74
-rw-r--r--ext/mysqlnd/mysqlnd_ps.c2
-rw-r--r--ext/mysqlnd/mysqlnd_wireprotocol.c2
6 files changed, 93 insertions, 61 deletions
diff --git a/ext/mysql/php_mysql.c b/ext/mysql/php_mysql.c
index bb30952b00..d808255e37 100644
--- a/ext/mysql/php_mysql.c
+++ b/ext/mysql/php_mysql.c
@@ -514,6 +514,18 @@ PHP_RINIT_FUNCTION(mysql)
}
/* }}} */
+
+#ifdef MYSQL_USE_MYSQLND
+static int php_mysql_persistent_helper(zend_rsrc_list_entry *le TSRMLS_DC)
+{
+ if (le->type == le_plink) {
+ mysqlnd_end_psession(((php_mysql_conn *) le->ptr)->conn);
+ }
+ return ZEND_HASH_APPLY_KEEP;
+} /* }}} */
+#endif
+
+
/* {{{ PHP_RSHUTDOWN_FUNCTION
*/
PHP_RSHUTDOWN_FUNCTION(mysql)
@@ -531,7 +543,9 @@ PHP_RSHUTDOWN_FUNCTION(mysql)
if (MySG(connect_error)!=NULL) {
efree(MySG(connect_error));
}
+
#ifdef MYSQL_USE_MYSQLND
+ zend_hash_apply(&EG(persistent_list), (apply_func_t) php_mysql_persistent_helper TSRMLS_CC);
mysqlnd_palloc_rshutdown(MySG(mysqlnd_thd_zval_cache));
#endif
@@ -572,6 +586,7 @@ PHP_MINFO_FUNCTION(mysql)
}
}
#endif
+
php_info_print_table_end();
DISPLAY_INI_ENTRIES();
@@ -644,7 +659,7 @@ static void php_mysql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
passwd = MySG(default_password);
/* mysql_pconnect does not support new_link parameter */
- if (persistent) {
+ if (persistent) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s&s&s&l", &host_and_port, &host_len, UG(utf8_conv),
&user, &user_len, UG(utf8_conv), &passwd, &passwd_len, UG(utf8_conv),
&client_flags)==FAILURE) {
@@ -663,6 +678,8 @@ static void php_mysql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
client_flags ^= CLIENT_LOCAL_FILES;
}
+ client_flags &= ~CLIENT_MULTI_STATEMENTS; /* don't allow multi_queries via connect parameter */
+
hashed_details_length = spprintf(&hashed_details, 0, "mysql_%s_%s_%s_%ld", SAFE_STRING(host_and_port), SAFE_STRING(user), SAFE_STRING(passwd), client_flags);
}
@@ -714,7 +731,7 @@ static void php_mysql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
/* create the link */
mysql = (php_mysql_conn *) malloc(sizeof(php_mysql_conn));
mysql->active_result_id = 0;
- mysql->multi_query = 1;
+ mysql->multi_query = client_flags & CLIENT_MULTI_STATEMENTS? 1:0;
#ifndef MYSQL_USE_MYSQLND
mysql->conn = mysql_init(NULL);
#else
@@ -724,8 +741,9 @@ static void php_mysql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
mysql_options(mysql->conn, MYSQL_SET_CHARSET_NAME, "utf8");
}
- if (connect_timeout != -1)
+ if (connect_timeout != -1) {
mysql_options(mysql->conn, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&connect_timeout);
+ }
#ifndef MYSQL_USE_MYSQLND
if (mysql_real_connect(mysql->conn, host, user, passwd, NULL, port, socket, client_flags)==NULL)
#else
@@ -778,6 +796,7 @@ static void php_mysql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
}
mysql = (php_mysql_conn *) le->ptr;
mysql->active_result_id = 0;
+ mysql->multi_query = client_flags & CLIENT_MULTI_STATEMENTS? 1:0;
/* ensure that the link did not die */
if (mysql_ping(mysql->conn)) {
if (mysql_errno(mysql->conn) == 2006) {
diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c
index 1fe06770f2..7cfa6714c0 100644
--- a/ext/mysqli/mysqli.c
+++ b/ext/mysqli/mysqli.c
@@ -94,12 +94,8 @@ static int le_pmysqli;
/* Destructor for mysqli entries in free_links/used_links */
void php_mysqli_dtor_p_elements(void *data)
{
- MYSQL *mysql = (MYSQL *) data;
-#if defined(MYSQLI_USE_MYSQLND)
TSRMLS_FETCH();
-
- mysqlnd_end_psession(mysql);
-#endif
+ MYSQL *mysql = (MYSQL *) data;
mysqli_close(mysql, MYSQLI_CLOSE_IMPLICIT);
}
@@ -903,6 +899,12 @@ PHP_MINIT_FUNCTION(mysqli)
#endif
#endif
+ REGISTER_LONG_CONSTANT("MYSQLI_SERVER_QUERY_NO_GOOD_INDEX_USED", SERVER_QUERY_NO_GOOD_INDEX_USED, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("MYSQLI_SERVER_QUERY_NO_INDEX_USED", SERVER_QUERY_NO_INDEX_USED, CONST_CS | CONST_PERSISTENT);
+#ifdef SERVER_QUERY_WAS_SLOW
+ REGISTER_LONG_CONSTANT("MYSQLI_SERVER_QUERY_WAS_SLOW", SERVER_QUERY_WAS_SLOW, CONST_CS | CONST_PERSISTENT);
+#endif
+
return SUCCESS;
}
/* }}} */
@@ -962,6 +964,26 @@ PHP_RINIT_FUNCTION(mysqli)
}
/* }}} */
+
+#ifdef MYSQLI_USE_MYSQLND
+static void php_mysqli_persistent_helper_for_every(void *p)
+{
+ TSRMLS_FETCH();
+ mysqlnd_end_psession((MYSQLND *) p);
+} /* }}} */
+
+
+static int php_mysqli_persistent_helper_once(zend_rsrc_list_entry *le TSRMLS_DC)
+{
+ if (le->type == php_le_pmysqli()) {
+ mysqli_plist_entry *plist = (mysqli_plist_entry *) le->ptr;
+ zend_ptr_stack_apply(&plist->free_links, php_mysqli_persistent_helper_for_every);
+ }
+ return ZEND_HASH_APPLY_KEEP;
+} /* }}} */
+#endif
+
+
/* {{{ PHP_RSHUTDOWN_FUNCTION
*/
PHP_RSHUTDOWN_FUNCTION(mysqli)
@@ -975,6 +997,7 @@ PHP_RSHUTDOWN_FUNCTION(mysqli)
efree(MyG(error_msg));
}
#ifdef MYSQLI_USE_MYSQLND
+ zend_hash_apply(&EG(persistent_list), (apply_func_t) php_mysqli_persistent_helper_once TSRMLS_CC);
mysqlnd_palloc_rshutdown(MyG(mysqlnd_thd_zval_cache));
#endif
return SUCCESS;
diff --git a/ext/mysqlnd/mysqlnd.c b/ext/mysqlnd/mysqlnd.c
index cd21ebed56..fb57ca70f5 100644
--- a/ext/mysqlnd/mysqlnd.c
+++ b/ext/mysqlnd/mysqlnd.c
@@ -451,7 +451,11 @@ PHPAPI void _mysqlnd_restart_psession(MYSQLND *conn, MYSQLND_THD_ZVAL_PCACHE *ca
mnd_pefree(conn->last_message, conn->persistent);
conn->last_message = NULL;
}
- conn->zval_cache = cache;
+ /*
+ The thd zval cache is always freed on request shutdown, so this has happened already.
+ Don't touch the old value! Get new reference
+ */
+ conn->zval_cache = mysqlnd_palloc_get_thd_cache_reference(cache);
DBG_VOID_RETURN;
}
/* }}} */
@@ -461,16 +465,8 @@ PHPAPI void _mysqlnd_restart_psession(MYSQLND *conn, MYSQLND_THD_ZVAL_PCACHE *ca
PHPAPI void _mysqlnd_end_psession(MYSQLND *conn TSRMLS_DC)
{
DBG_ENTER("_mysqlnd_end_psession");
- /*
- BEWARE!!!! This will have a problem with a query cache.
- We need to move the data out of the zval cache before we end the psession.
- Or we will use nirvana pointers!!
- */
- if (conn->zval_cache) {
- DBG_INF("Freeing zval cache reference");
- mysqlnd_palloc_free_thd_cache_reference(&conn->zval_cache);
- conn->zval_cache = NULL;
- }
+ /* The thd zval cache is always freed on request shutdown, so this has happened already */
+ mysqlnd_palloc_free_thd_cache_reference(&conn->zval_cache);
DBG_VOID_RETURN;
}
/* }}} */
diff --git a/ext/mysqlnd/mysqlnd_palloc.c b/ext/mysqlnd/mysqlnd_palloc.c
index cff217eaae..f64dd17ada 100644
--- a/ext/mysqlnd/mysqlnd_palloc.c
+++ b/ext/mysqlnd/mysqlnd_palloc.c
@@ -172,7 +172,7 @@ MYSQLND_THD_ZVAL_PCACHE* _mysqlnd_palloc_get_thd_cache_reference(MYSQLND_THD_ZVA
if (cache) {
++cache->references;
DBG_INF_FMT("cache=%p new_refc=%d gc_list.canary1=%p gc_list.canary2=%p",
- *cache, cache->references, cache->gc_list.canary1, cache->gc_list.canary2);
+ cache, cache->references, cache->gc_list.canary1, cache->gc_list.canary2);
mysqlnd_palloc_get_cache_reference(cache->parent);
}
DBG_RETURN(cache);
@@ -189,13 +189,43 @@ MYSQLND_THD_ZVAL_PCACHE* _mysqlnd_palloc_get_thd_cache_reference(MYSQLND_THD_ZVA
constructor of the cache.
*/
static
-void mysqlnd_palloc_free_thd_cache(MYSQLND_THD_ZVAL_PCACHE *cache TSRMLS_DC)
+void mysqlnd_palloc_free_thd_cache(MYSQLND_THD_ZVAL_PCACHE *thd_cache TSRMLS_DC)
{
+ MYSQLND_ZVAL_PCACHE *global_cache;
+ mysqlnd_zval **p;
+
DBG_ENTER("mysqlnd_palloc_free_thd_cache");
- DBG_INF_FMT("cache=%p", cache);
+ DBG_INF_FMT("thd_cache=%p", thd_cache);
- mnd_free(cache->gc_list.ptr_line);
- mnd_free(cache);
+ if ((global_cache = thd_cache->parent)) {
+ /*
+ Keep in mind that for pthreads pthread_equal() should be used to be
+ fully standard compliant. However, the PHP code all-around, incl. the
+ the Zend MM uses direct comparison.
+ */
+ p = thd_cache->gc_list.ptr_line;
+ while (p < thd_cache->gc_list.last_added) {
+ zval_dtor(&(*p)->zv);
+ p++;
+ }
+
+ p = thd_cache->gc_list.ptr_line;
+
+ LOCK_PCACHE(global_cache);
+ while (p < thd_cache->gc_list.last_added) {
+ (*p)->point_type = MYSQLND_POINTS_FREE;
+ *(--global_cache->free_list.last_added) = *p;
+ ++global_cache->free_items;
+#ifdef ZTS
+ memset(&((*p)->thread_id), 0, sizeof(THREAD_T));
+#endif
+ p++;
+ }
+ UNLOCK_PCACHE(global_cache);
+
+ }
+ mnd_free(thd_cache->gc_list.ptr_line);
+ mnd_free(thd_cache);
DBG_VOID_RETURN;
}
@@ -508,43 +538,9 @@ PHPAPI MYSQLND_THD_ZVAL_PCACHE * _mysqlnd_palloc_rinit(MYSQLND_ZVAL_PCACHE * cac
/* {{{ _mysqlnd_palloc_rshutdown */
PHPAPI void _mysqlnd_palloc_rshutdown(MYSQLND_THD_ZVAL_PCACHE * thd_cache TSRMLS_DC)
{
- MYSQLND_ZVAL_PCACHE *cache;
- mysqlnd_zval **p;
-
DBG_ENTER("_mysqlnd_palloc_rshutdown");
DBG_INF_FMT("cache=%p", thd_cache);
-
- if (!thd_cache || !(cache = thd_cache->parent)) {
- return;
- }
-
- /*
- Keep in mind that for pthreads pthread_equal() should be used to be
- fully standard compliant. However, the PHP code all-around, incl. the
- the Zend MM uses direct comparison.
- */
- p = thd_cache->gc_list.ptr_line;
- while (p < thd_cache->gc_list.last_added) {
- zval_dtor(&(*p)->zv);
- p++;
- }
-
- p = thd_cache->gc_list.ptr_line;
-
- LOCK_PCACHE(cache);
- while (p < thd_cache->gc_list.last_added) {
- (*p)->point_type = MYSQLND_POINTS_FREE;
- *(--cache->free_list.last_added) = *p;
- ++cache->free_items;
-#ifdef ZTS
- memset(&((*p)->thread_id), 0, sizeof(THREAD_T));
-#endif
- p++;
- }
- UNLOCK_PCACHE(cache);
-
mysqlnd_palloc_free_thd_cache_reference(&thd_cache);
-
DBG_VOID_RETURN;
}
/* }}} */
diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c
index acacee22ef..30154bfe54 100644
--- a/ext/mysqlnd/mysqlnd_ps.c
+++ b/ext/mysqlnd/mysqlnd_ps.c
@@ -582,7 +582,7 @@ MYSQLND_METHOD(mysqlnd_stmt, execute)(MYSQLND_STMT * const stmt TSRMLS_DC)
SET_ERROR_AFF_ROWS(stmt);
SET_ERROR_AFF_ROWS(stmt->conn);
- if (stmt->state > MYSQLND_STMT_PREPARED && stmt->field_count) {
+ if (stmt->result && stmt->state > MYSQLND_STMT_PREPARED && stmt->field_count) {
/*
We don need to copy the data from the buffers which we will clean.
Because it has already been copied. See
diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c
index 4816a4fb37..c59e1b216c 100644
--- a/ext/mysqlnd/mysqlnd_wireprotocol.c
+++ b/ext/mysqlnd/mysqlnd_wireprotocol.c
@@ -690,8 +690,6 @@ size_t php_mysqlnd_auth_write(void *_packet, MYSQLND *conn TSRMLS_DC)
packet->client_flags ^= CLIENT_LOCAL_FILES;
}
- /* don't allow multi_queries via connect parameter */
- packet->client_flags ^= CLIENT_MULTI_STATEMENTS;
int4store(p, packet->client_flags);
p+= 4;