Browse Source

Fix remaining valgrind problems with pconn and zval cache

HEAD merge will follow tomorrow.
PECL
Andrey Hristov 18 years ago
parent
commit
827b772c9f
  1. 27
      ext/mysql/php_mysql.c
  2. 30
      ext/mysqli/mysqli.c
  3. 1
      ext/mysqlnd/mysqlnd.c
  4. 85
      ext/mysqlnd/mysqlnd_palloc.c

27
ext/mysql/php_mysql.c

@ -365,9 +365,6 @@ static void _close_mysql_plink(zend_rsrc_list_entry *rsrc TSRMLS_DC)
void (*handler) (int);
handler = signal(SIGPIPE, SIG_IGN);
#ifdef MYSQL_USE_MYSQLND
mysqlnd_end_psession(link->conn);
#endif
mysql_close(link->conn);
signal(SIGPIPE, handler);
@ -520,6 +517,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)
@ -537,7 +546,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
@ -734,8 +745,9 @@ static void php_mysql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
mysql->conn = mysql_init(persistent);
#endif
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,12 +790,11 @@ static void php_mysql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
/* ensure that the link did not die */
if (mysql_ping(mysql->conn)) {
if (mysql_errno(mysql->conn) == 2006) {
#ifdef MYSQL_USE_MYSQLND
mysqlnd_end_psession(mysql->conn);
#ifndef MYSQL_USE_MYSQLND
if (mysql_real_connect(mysql->conn, host, user, passwd, NULL, port, socket, client_flags)==NULL)
#else
if (mysqlnd_connect(mysql->conn, host, user, passwd, 0, NULL, 0,
port, socket, client_flags, MySG(mysqlnd_thd_zval_cache) TSRMLS_CC) == NULL)
#else
if (mysql_real_connect(mysql->conn, host, user, passwd, NULL, port, socket, client_flags)==NULL)
#endif
{
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Link to server lost, unable to reconnect");

30
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);
}
@ -232,9 +228,6 @@ static void mysqli_link_free_storage(void *object TSRMLS_DC)
MY_MYSQL *mysql = (MY_MYSQL *)my_res->ptr;
if (mysql->mysql) {
if (!mysql->persistent) {
#ifdef MYSQLI_USE_MYSQLND
mysqlnd_end_psession(mysql->mysql);
#endif
mysqli_close(mysql->mysql, MYSQLI_CLOSE_IMPLICIT);
} else {
zend_rsrc_list_entry *le;
@ -959,6 +952,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)
@ -972,6 +985,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;

1
ext/mysqlnd/mysqlnd.c

@ -466,6 +466,7 @@ PHPAPI void _mysqlnd_end_psession(MYSQLND *conn TSRMLS_DC)
{
DBG_ENTER("_mysqlnd_end_psession");
/* The thd zval cache is always freed on request shutdown, so this has happened already */
mysqlnd_palloc_free_thd_cache_reference(&conn->zval_cache);
conn->zval_cache = NULL;
DBG_VOID_RETURN;
}

85
ext/mysqlnd/mysqlnd_palloc.c

@ -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,56 +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;
}
/*
!!! 080624 !!!
If the user has used Persistent Connections the reference counter
of the cache is not 1 but > 1 . Because the Pconns don't are not signalised
during RSHUT, then we need to take care here to decrease the counter.
A more proper fix will be to array_walk our pconns in RSHUT and ask them to
free their thd reference. This should be implemented sooner or later!
*/
/*
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);
/* We need to decrease Main cache's references as pconns don't clean correctly */
cache->references -= (thd_cache->references - 1); /* we start with 1 initial reference */
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);
/* We need to decrease thd cache's references as pconns don't clean correctly. See above! */
thd_cache->references = 1;
mysqlnd_palloc_free_thd_cache_reference(&thd_cache);
DBG_VOID_RETURN;
}
/* }}} */

Loading…
Cancel
Save