mirror of
https://github.com/php/php-src.git
synced 2025-08-15 13:38:49 +02:00
Partially backport GH-13782 to stable branches
This partially backports that PR to stable branches as it has been in master without reported problems so far. It's only a partial backport because the stable branches don't have the ZTS persistent resource fix that would fix shutdown crashes, i.e. the code change in mysqlnd_vio's close_stream is not backported. This is fully fixed on master. Closes GH-14324. Closes GH-10599.
This commit is contained in:
parent
709869c8bd
commit
c815cdcfe7
2 changed files with 50 additions and 23 deletions
5
NEWS
5
NEWS
|
@ -16,6 +16,11 @@ PHP NEWS
|
||||||
- DOM:
|
- DOM:
|
||||||
. Fixed bug GH-14343 (Memory leak in xml and dom). (nielsdos)
|
. Fixed bug GH-14343 (Memory leak in xml and dom). (nielsdos)
|
||||||
|
|
||||||
|
- MySQLnd:
|
||||||
|
. Partially fix bug GH-10599 (Apache crash on Windows when using a
|
||||||
|
self-referencing anonymous function inside a class with an active
|
||||||
|
mysqli connection). (nielsdos)
|
||||||
|
|
||||||
- Opcache:
|
- Opcache:
|
||||||
. Fixed bug GH-14267 (opcache.jit=off does not allow enabling JIT at runtime).
|
. Fixed bug GH-14267 (opcache.jit=off does not allow enabling JIT at runtime).
|
||||||
(ilutov)
|
(ilutov)
|
||||||
|
|
|
@ -112,6 +112,20 @@ MYSQLND_METHOD(mysqlnd_vio, network_write)(MYSQLND_VIO * const vio, const zend_u
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
static void mysqlnd_fixup_regular_list(php_stream *net_stream)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Streams are not meant for C extensions! Thus we need a hack. Every connected stream will
|
||||||
|
be registered as resource (in EG(regular_list). So far, so good. However, it won't be
|
||||||
|
unregistered until the script ends. So, we need to take care of that.
|
||||||
|
*/
|
||||||
|
dtor_func_t origin_dtor = EG(regular_list).pDestructor;
|
||||||
|
EG(regular_list).pDestructor = NULL;
|
||||||
|
zend_hash_index_del(&EG(regular_list), net_stream->res->handle);
|
||||||
|
EG(regular_list).pDestructor = origin_dtor;
|
||||||
|
efree(net_stream->res);
|
||||||
|
net_stream->res = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* {{{ mysqlnd_vio::open_pipe */
|
/* {{{ mysqlnd_vio::open_pipe */
|
||||||
static php_stream *
|
static php_stream *
|
||||||
|
@ -119,7 +133,6 @@ MYSQLND_METHOD(mysqlnd_vio, open_pipe)(MYSQLND_VIO * const vio, const MYSQLND_CS
|
||||||
MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info)
|
MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info)
|
||||||
{
|
{
|
||||||
unsigned int streams_options = 0;
|
unsigned int streams_options = 0;
|
||||||
dtor_func_t origin_dtor;
|
|
||||||
php_stream * net_stream = NULL;
|
php_stream * net_stream = NULL;
|
||||||
|
|
||||||
DBG_ENTER("mysqlnd_vio::open_pipe");
|
DBG_ENTER("mysqlnd_vio::open_pipe");
|
||||||
|
@ -132,16 +145,34 @@ MYSQLND_METHOD(mysqlnd_vio, open_pipe)(MYSQLND_VIO * const vio, const MYSQLND_CS
|
||||||
SET_CLIENT_ERROR(error_info, CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE, "Unknown error while connecting");
|
SET_CLIENT_ERROR(error_info, CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE, "Unknown error while connecting");
|
||||||
DBG_RETURN(NULL);
|
DBG_RETURN(NULL);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
Streams are not meant for C extensions! Thus we need a hack. Every connected stream will
|
if (persistent) {
|
||||||
be registered as resource (in EG(regular_list). So far, so good. However, it won't be
|
/* This is a similar hack as for mysqlnd_vio::open_tcp_or_unix.
|
||||||
unregistered until the script ends. So, we need to take care of that.
|
* The main difference here is that we have no access to the hashed key.
|
||||||
*/
|
* We can however perform a loop over the persistent resource list to find
|
||||||
origin_dtor = EG(regular_list).pDestructor;
|
* which one corresponds to our newly allocated stream.
|
||||||
EG(regular_list).pDestructor = NULL;
|
* This loop is pretty cheap because it will normally either be the last entry or second to last entry
|
||||||
zend_hash_index_del(&EG(regular_list), net_stream->res->handle); /* ToDO: should it be res->handle, do streams register with addref ?*/
|
* in the list, depending on whether the socket connection itself is persistent or not.
|
||||||
EG(regular_list).pDestructor = origin_dtor;
|
* That's why we use a reverse loop. */
|
||||||
net_stream->res = NULL;
|
Bucket *bucket;
|
||||||
|
/* Use a bucket loop to make deletion cheap. */
|
||||||
|
ZEND_HASH_MAP_REVERSE_FOREACH_BUCKET(&EG(persistent_list), bucket) {
|
||||||
|
zend_resource *current_res = Z_RES(bucket->val);
|
||||||
|
if (current_res->ptr == net_stream) {
|
||||||
|
dtor_func_t origin_dtor = EG(persistent_list).pDestructor;
|
||||||
|
EG(persistent_list).pDestructor = NULL;
|
||||||
|
zend_hash_del_bucket(&EG(persistent_list), bucket);
|
||||||
|
EG(persistent_list).pDestructor = origin_dtor;
|
||||||
|
pefree(current_res, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} ZEND_HASH_FOREACH_END();
|
||||||
|
#if ZEND_DEBUG
|
||||||
|
php_stream_auto_cleanup(net_stream);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
mysqlnd_fixup_regular_list(net_stream);
|
||||||
|
|
||||||
DBG_RETURN(net_stream);
|
DBG_RETURN(net_stream);
|
||||||
}
|
}
|
||||||
|
@ -205,6 +236,7 @@ MYSQLND_METHOD(mysqlnd_vio, open_tcp_or_unix)(MYSQLND_VIO * const vio, const MYS
|
||||||
zend_resource *le;
|
zend_resource *le;
|
||||||
|
|
||||||
if ((le = zend_hash_str_find_ptr(&EG(persistent_list), hashed_details, hashed_details_len))) {
|
if ((le = zend_hash_str_find_ptr(&EG(persistent_list), hashed_details, hashed_details_len))) {
|
||||||
|
ZEND_ASSERT(le->ptr == net_stream);
|
||||||
origin_dtor = EG(persistent_list).pDestructor;
|
origin_dtor = EG(persistent_list).pDestructor;
|
||||||
/*
|
/*
|
||||||
in_free will let streams code skip destructing - big HACK,
|
in_free will let streams code skip destructing - big HACK,
|
||||||
|
@ -218,22 +250,12 @@ MYSQLND_METHOD(mysqlnd_vio, open_tcp_or_unix)(MYSQLND_VIO * const vio, const MYS
|
||||||
}
|
}
|
||||||
#if ZEND_DEBUG
|
#if ZEND_DEBUG
|
||||||
/* Shut-up the streams, they don't know what they are doing */
|
/* Shut-up the streams, they don't know what they are doing */
|
||||||
net_stream->__exposed = 1;
|
php_stream_auto_cleanup(net_stream);
|
||||||
#endif
|
#endif
|
||||||
mnd_sprintf_free(hashed_details);
|
mnd_sprintf_free(hashed_details);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
mysqlnd_fixup_regular_list(net_stream);
|
||||||
Streams are not meant for C extensions! Thus we need a hack. Every connected stream will
|
|
||||||
be registered as resource (in EG(regular_list). So far, so good. However, it won't be
|
|
||||||
unregistered until the script ends. So, we need to take care of that.
|
|
||||||
*/
|
|
||||||
origin_dtor = EG(regular_list).pDestructor;
|
|
||||||
EG(regular_list).pDestructor = NULL;
|
|
||||||
zend_hash_index_del(&EG(regular_list), net_stream->res->handle); /* ToDO: should it be res->handle, do streams register with addref ?*/
|
|
||||||
efree(net_stream->res);
|
|
||||||
net_stream->res = NULL;
|
|
||||||
EG(regular_list).pDestructor = origin_dtor;
|
|
||||||
DBG_RETURN(net_stream);
|
DBG_RETURN(net_stream);
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue