From: Andrey Hristov Date: Tue, 24 Jun 2008 22:22:48 +0000 (+0000) Subject: Fix remaining valgrind problems with pconn and zval cache X-Git-Tag: php-5.3.0alpha1~608 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=827b772c9fbfc52fb1fdabf96813eca6f319f961;p=php Fix remaining valgrind problems with pconn and zval cache HEAD merge will follow tomorrow. --- diff --git a/ext/mysql/php_mysql.c b/ext/mysql/php_mysql.c index 594a1de623..c441d4def6 100644 --- a/ext/mysql/php_mysql.c +++ b/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"); diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c index f8350be3fb..fda5a846a8 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); } @@ -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; diff --git a/ext/mysqlnd/mysqlnd.c b/ext/mysqlnd/mysqlnd.c index 5f50d80e06..12b215ac4c 100644 --- a/ext/mysqlnd/mysqlnd.c +++ b/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; } diff --git a/ext/mysqlnd/mysqlnd_palloc.c b/ext/mysqlnd/mysqlnd_palloc.c index f429af49f5..da6e2b07a6 100644 --- a/ext/mysqlnd/mysqlnd_palloc.c +++ b/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; } /* }}} */