]> granicus.if.org Git - php/commitdiff
Fix remaining valgrind problems with pconn and zval cache
authorAndrey Hristov <andrey@php.net>
Tue, 24 Jun 2008 22:22:48 +0000 (22:22 +0000)
committerAndrey Hristov <andrey@php.net>
Tue, 24 Jun 2008 22:22:48 +0000 (22:22 +0000)
HEAD merge will follow tomorrow.

ext/mysql/php_mysql.c
ext/mysqli/mysqli.c
ext/mysqlnd/mysqlnd.c
ext/mysqlnd/mysqlnd_palloc.c

index 594a1de6231b3712bbb6c529cdcbbf05f60c2646..c441d4def6eb2644d0bbb048429e4bd08140c5ed 100644 (file)
@@ -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");
index f8350be3fbbe76ac438b6c4bc4d1bb7eacabf5be..fda5a846a838c9ba0d180249c1edc8caf5cedc8b 100644 (file)
@@ -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;
index 5f50d80e0649aaf15bf2a916a8f263b62e1e859c..12b215ac4c8a5589701e846ff483c4a822ead4ee 100644 (file)
@@ -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;
 }
index f429af49f5c418d474dbafae6fbd14cab62bd924..da6e2b07a6d786ae2e20726faf30c6eb06d44d1f 100644 (file)
@@ -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;
 }
 /* }}} */